summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorjb150015 <none@none>2008-06-02 13:50:26 -0700
committerjb150015 <none@none>2008-06-02 13:50:26 -0700
commit3ad684d66b78e06edd37e2c4fd3b3949f095194b (patch)
treec8a46bd6352a4d612c208b2da5baa3d9817a28e4 /usr/src
parent25c3d9a2161e0ea7e7d2783b5f991fd797282b63 (diff)
downloadillumos-gate-3ad684d66b78e06edd37e2c4fd3b3949f095194b.tar.gz
6686467 Panic in smb_trans_net_share_enum() while browsing over 200 shares from Mac
6693094 zfs_frlock panic while running stress tests. 6696744 smbd dumped core while joining Windows 2K domain 6698934 ofile state needs to be checked before doing share (i.e. open/deny mode) checks 6705282 configuration changes are not propagated to kernel 6708562 SID filtering breaks trusted domain users --HG-- rename : usr/src/uts/common/fs/smbsrv/smb_share_kdoor_client.c => usr/src/uts/common/fs/smbsrv/smb_kshare.c
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd.h9
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c5
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_logon.c4
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_main.c7
-rwxr-xr-xusr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c7
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c288
-rw-r--r--usr/src/common/smbsrv/smb_share_door_decode.c48
-rw-r--r--usr/src/lib/libshare/smb/libshare_smb.c15
-rw-r--r--usr/src/lib/libshare/smb/smb_share_doorclnt.c141
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c57
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h10
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/lmshare.c148
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers7
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c47
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c94
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/smb_share_util.c29
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/libsmb.h2
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/mapfile-vers3
-rw-r--r--usr/src/uts/common/Makefile.files9
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_transact.c801
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_tree.c20
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fsops.c21
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_kshare.c311
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_lock_svc.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_mbuf_util.c6
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_node.c169
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_ofile.c178
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_server.c6
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_share_kdoor_client.c604
-rw-r--r--usr/src/uts/common/smbsrv/lmshare.h108
-rw-r--r--usr/src/uts/common/smbsrv/lmshare_door.h41
-rw-r--r--usr/src/uts/common/smbsrv/smb_common_door.h4
-rw-r--r--usr/src/uts/common/smbsrv/smb_kproto.h7
-rw-r--r--usr/src/uts/common/smbsrv/smb_ktypes.h1
-rwxr-xr-xusr/src/uts/common/smbsrv/smb_winpipe.h3
35 files changed, 1186 insertions, 2028 deletions
diff --git a/usr/src/cmd/smbsrv/smbd/smbd.h b/usr/src/cmd/smbsrv/smbd/smbd.h
index 10b5b083f5..b60445cd8f 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd.h
+++ b/usr/src/cmd/smbsrv/smbd/smbd.h
@@ -40,13 +40,9 @@ extern "C" {
extern int smb_winpipe_doorsvc_start(void);
extern void smb_winpipe_doorsvc_stop(void);
-extern int smb_lmshrd_srv_start(void);
-extern void smb_lmshrd_srv_stop(void);
-extern int smb_doorsrv_start(void);
-extern void smb_doorsrv_stop(void);
-extern int smb_ntgroup_doorsrv_start(void);
-extern void smb_ntgroup_doorsrv_stop(void);
+extern int smb_share_dsrv_start(void);
+extern void smb_share_dsrv_stop(void);
extern int smb_netlogon_init(void);
extern void smb_set_netlogon_cred(void);
@@ -56,6 +52,7 @@ extern void smbd_user_nonauth_logon(uint32_t);
extern void smbd_user_auth_logoff(uint32_t);
extern uint32_t smbd_join(smb_joininfo_t *);
+
typedef struct smbd {
const char *s_version; /* smbd version string */
const char *s_pname; /* basename to use for messages */
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
index d1cfec3b63..4571324877 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
@@ -167,6 +167,11 @@ smb_door_srv_func(void *cookie, char *argp, size_t arg_size, door_desc_t *dp,
int err;
smb_dr_op_t smbop;
+ if ((cookie != SMB_DR_SVC_COOKIE) || (argp == NULL) ||
+ (arg_size < sizeof (uint32_t))) {
+ (void) door_return(NULL, 0, NULL, 0);
+ }
+
if ((opcode = smb_dr_get_opcode(argp, arg_size)) < 0) {
tmpbuf = smb_door_srv_err_hdlr(SMB_DR_OP_ERR_DECODE,
&rbufsize);
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_logon.c b/usr/src/cmd/smbsrv/smbd/smbd_logon.c
index e0560e7598..0b88309dbf 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_logon.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_logon.c
@@ -158,7 +158,7 @@ smbd_user_auth_logon(netr_client_t *clnt)
entry->sa_username = strdup(clnt->username);
entry->sa_domain = strdup(clnt->domain);
- (void) smb_autohome_add(entry->sa_username);
+ smb_autohome_add(entry->sa_username);
smbd_audit_link(entry);
token->tkn_audit_sid = entry->sa_audit_sid;
}
@@ -205,7 +205,7 @@ smbd_user_auth_logoff(uint32_t audit_sid)
if ((entry = smbd_audit_unlink(audit_sid)) == NULL)
return;
- (void) smb_autohome_remove(entry->sa_username);
+ smb_autohome_remove(entry->sa_username);
ah = entry->sa_handle;
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_main.c b/usr/src/cmd/smbsrv/smbd/smbd_main.c
index 92284e18c3..8811a24f6f 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_main.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c
@@ -407,7 +407,7 @@ smbd_service_init(void)
(void) lsa_query_primary_domain_info();
}
- smbd.s_door_lmshr = smb_lmshrd_srv_start();
+ smbd.s_door_lmshr = smb_share_dsrv_start();
if (smbd.s_door_lmshr < 0) {
smbd_report("share initialization failed");
}
@@ -457,7 +457,7 @@ smbd_service_fini(void)
smbd_refresh_fini();
smbd_kernel_unbind();
smb_door_srv_stop();
- smb_lmshrd_srv_stop();
+ smb_share_dsrv_stop();
lmshare_stop();
smb_nicmon_stop();
smb_idmap_stop();
@@ -529,6 +529,9 @@ smbd_refresh_monitor(void *arg)
char fqdn[MAXHOSTNAMELEN];
int rc = 0;
+ bzero(&smb_io, sizeof (smb_io));
+ smb_io.sio_version = SMB_IOC_VERSION;
+
(void) pthread_mutex_lock(&refresh_mutex);
while (pthread_cond_wait(&refresh_cond, &refresh_mutex) == 0) {
/*
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c
index 0b77424731..9e20d3bef6 100755
--- a/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c
@@ -166,6 +166,11 @@ smb_winpipe_request(void *cookie, char *argp, size_t arg_size,
char lfp[START_OUTDOOR_SIZE];
boolean_t more_data = B_FALSE;
+ if ((cookie != &smb_winpipe_cookie) || (argp == NULL) ||
+ (arg_size < SMB_WINPIPE_MIN_REQ_SIZE)) {
+ (void) door_return(NULL, 0, NULL, 0);
+ }
+
bufp = argp;
bcopy(bufp, &mdhin.md_tid, sizeof (uint64_t));
bytes_off = sizeof (uint64_t);
@@ -338,5 +343,5 @@ smb_winpipe_request(void *cookie, char *argp, size_t arg_size,
zero_exit:
smb_user_ctx_free(user_ctx);
- (void) door_return(0, 0, NULL, 0);
+ (void) door_return(NULL, 0, NULL, 0);
}
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c
index 60a19b4f05..31ef703e9a 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c
@@ -37,6 +37,7 @@
#include <errno.h>
#include <syslog.h>
#include <string.h>
+#include <strings.h>
#include <pthread.h>
#include <smbsrv/libsmb.h>
@@ -45,155 +46,123 @@
#include <smbsrv/lmshare_door.h>
#include <smbsrv/smbinfo.h>
-static smb_kmod_cfg_t smb_kcfg;
+static int smb_share_dsrv_fd = -1;
+static pthread_mutex_t smb_share_dsrv_mtx = PTHREAD_MUTEX_INITIALIZER;
-static int smb_lmshrd_fildes = -1;
-static pthread_mutex_t smb_lmshrd_srv_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/* forward declaration */
-static void smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size,
- door_desc_t *dp, uint_t n_desc);
-static int smb_lmshrd_srv_check(int opcode, char *sharename);
+static void smb_share_dsrv_dispatch(void *, char *, size_t, door_desc_t *,
+ uint_t);
+static int smb_share_dsrv_check(int, char *);
+static int smb_share_dsrv_enum(smb_enumshare_info_t *esi);
/*
- * smb_lmshrd_srv_start
+ * smb_share_dsrv_start
*
* Start the LanMan share door service.
* Returns 0 on success. Otherwise, -1.
*/
int
-smb_lmshrd_srv_start(void)
+smb_share_dsrv_start(void)
{
int newfd;
- (void) pthread_mutex_lock(&smb_lmshrd_srv_mutex);
+ (void) pthread_mutex_lock(&smb_share_dsrv_mtx);
- if (smb_lmshrd_fildes != -1) {
- syslog(LOG_ERR, "smb_lmshrd_srv_start: duplicate");
- (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex);
- return (smb_lmshrd_fildes);
+ if (smb_share_dsrv_fd != -1) {
+ syslog(LOG_ERR, "smb_share_dsrv_start: duplicate");
+ (void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
+ return (smb_share_dsrv_fd);
}
- if ((smb_lmshrd_fildes = door_create(smb_lmshrd_srv_door,
+ if ((smb_share_dsrv_fd = door_create(smb_share_dsrv_dispatch,
LMSHR_DOOR_COOKIE, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) {
- syslog(LOG_ERR, "smb_lmshrd_srv_start: door_create: %s",
+ syslog(LOG_ERR, "smb_share_dsrv_start: door_create: %s",
strerror(errno));
- (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex);
+ (void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
return (-1);
}
(void) unlink(LMSHR_DOOR_NAME);
if ((newfd = creat(LMSHR_DOOR_NAME, 0644)) < 0) {
- syslog(LOG_ERR, "smb_lmshrd_srv_start: open: %s",
+ syslog(LOG_ERR, "smb_share_dsrv_start: open: %s",
strerror(errno));
- (void) door_revoke(smb_lmshrd_fildes);
- smb_lmshrd_fildes = -1;
- (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex);
+ (void) door_revoke(smb_share_dsrv_fd);
+ smb_share_dsrv_fd = -1;
+ (void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
return (-1);
}
(void) close(newfd);
(void) fdetach(LMSHR_DOOR_NAME);
- if (fattach(smb_lmshrd_fildes, LMSHR_DOOR_NAME) < 0) {
- syslog(LOG_ERR, "smb_lmshrd_srv_start: fattach: %s",
+ if (fattach(smb_share_dsrv_fd, LMSHR_DOOR_NAME) < 0) {
+ syslog(LOG_ERR, "smb_share_dsrv_start: fattach: %s",
strerror(errno));
- (void) door_revoke(smb_lmshrd_fildes);
- smb_lmshrd_fildes = -1;
- (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex);
+ (void) door_revoke(smb_share_dsrv_fd);
+ smb_share_dsrv_fd = -1;
+ (void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
return (-1);
}
- (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex);
- return (smb_lmshrd_fildes);
+ (void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
+ return (smb_share_dsrv_fd);
}
-
/*
- * smb_lmshrd_srv_stop
+ * smb_share_dsrv_stop
*
* Stop the LanMan share door service.
*/
void
-smb_lmshrd_srv_stop(void)
+smb_share_dsrv_stop(void)
{
- (void) pthread_mutex_lock(&smb_lmshrd_srv_mutex);
+ (void) pthread_mutex_lock(&smb_share_dsrv_mtx);
- if (smb_lmshrd_fildes != -1) {
+ if (smb_share_dsrv_fd != -1) {
(void) fdetach(LMSHR_DOOR_NAME);
- (void) door_revoke(smb_lmshrd_fildes);
- smb_lmshrd_fildes = -1;
+ (void) door_revoke(smb_share_dsrv_fd);
+ smb_share_dsrv_fd = -1;
}
- (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex);
+ (void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
}
-
/*
- * smb_lmshrd_srv_door
+ * 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*/
-void
-smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp,
+static void
+smb_share_dsrv_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
uint_t n_desc)
{
DWORD rc;
- int req_type, mode, rc2;
+ int req_type, rc2;
char buf[LMSHR_DOOR_SIZE];
unsigned int used;
- smb_dr_ctx_t *dec_ctx = smb_dr_decode_start(ptr, size);
- smb_dr_ctx_t *enc_ctx = smb_dr_encode_start(buf, sizeof (buf));
+ smb_dr_ctx_t *dec_ctx;
+ smb_dr_ctx_t *enc_ctx;
unsigned int dec_status;
unsigned int enc_status;
char *sharename, *sharename2;
lmshare_info_t lmshr_info;
- lmshare_info_t *lmshr_infop;
- lmshare_iterator_t *lmshr_iter;
- int offset;
lmshare_list_t lmshr_list;
+ smb_enumshare_info_t esi;
+ int offset;
+
+ if ((cookie != LMSHR_DOOR_COOKIE) || (ptr == NULL) ||
+ (size < sizeof (uint32_t))) {
+ (void) door_return(NULL, 0, NULL, 0);
+ }
+ dec_ctx = smb_dr_decode_start(ptr, size);
+ enc_ctx = smb_dr_encode_start(buf, sizeof (buf));
req_type = smb_dr_get_uint32(dec_ctx);
switch (req_type) {
- case LMSHR_DOOR_OPEN_ITERATOR:
- mode = smb_dr_get_int32(dec_ctx);
-
- if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
- goto decode_error;
-
- lmshr_iter = lmshare_open_iterator(mode);
- smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
- smb_dr_put_lmshr_iterator(enc_ctx,
- (uint64_t)(uintptr_t)lmshr_iter);
-
- break;
-
- case LMSHR_DOOR_CLOSE_ITERATOR:
- lmshr_iter = (lmshare_iterator_t *)(uintptr_t)
- smb_dr_get_lmshr_iterator(dec_ctx);
- if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
- goto decode_error;
-
- lmshare_close_iterator(lmshr_iter);
- smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
- break;
-
- case LMSHR_DOOR_ITERATE:
- lmshr_iter = (lmshare_iterator_t *)(uintptr_t)
- smb_dr_get_lmshr_iterator(dec_ctx);
- if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
- goto decode_error;
-
- lmshr_infop = lmshare_iterate(lmshr_iter);
- smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
- smb_dr_put_lmshare(enc_ctx, lmshr_infop);
- break;
-
case LMSHR_DOOR_NUM_SHARES:
if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
goto decode_error;
@@ -281,7 +250,7 @@ smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp,
goto decode_error;
}
- rc2 = smb_lmshrd_srv_check(req_type, sharename);
+ rc2 = smb_share_dsrv_check(req_type, sharename);
smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
smb_dr_put_uint32(enc_ctx, rc2);
smb_dr_free_string(sharename);
@@ -292,19 +261,33 @@ smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp,
if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
goto decode_error;
- rc = lmshare_list(offset, &lmshr_list);
+ lmshare_list(offset, &lmshr_list);
smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
- smb_dr_put_uint32(enc_ctx, rc);
smb_dr_put_lmshr_list(enc_ctx, &lmshr_list);
break;
- case SMB_GET_KCONFIG:
- if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
+ case LMSHR_DOOR_ENUM:
+ esi.es_bufsize = smb_dr_get_ushort(dec_ctx);
+ esi.es_username = smb_dr_get_string(dec_ctx);
+ if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
+ smb_dr_free_string(esi.es_username);
goto decode_error;
+ }
+
+ rc = smb_share_dsrv_enum(&esi);
+
+ smb_dr_free_string(esi.es_username);
- smb_load_kconfig(&smb_kcfg);
smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
- smb_dr_put_kconfig(enc_ctx, &smb_kcfg);
+ smb_dr_put_uint32(enc_ctx, rc);
+ if (rc == NERR_Success) {
+ smb_dr_put_ushort(enc_ctx, esi.es_ntotal);
+ smb_dr_put_ushort(enc_ctx, esi.es_nsent);
+ smb_dr_put_ushort(enc_ctx, esi.es_datasize);
+ smb_dr_put_buf(enc_ctx,
+ (unsigned char *)esi.es_buf, esi.es_bufsize);
+ free(esi.es_buf);
+ }
break;
default:
@@ -312,11 +295,14 @@ smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp,
goto decode_error;
}
- if ((enc_status = smb_dr_encode_finish(enc_ctx, &used)) != 0)
- goto encode_error;
+ if ((enc_status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
+ enc_ctx = smb_dr_encode_start(buf, sizeof (buf));
+ smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_ERROR);
+ smb_dr_put_uint32(enc_ctx, enc_status);
+ (void) smb_dr_encode_finish(enc_ctx, &used);
+ }
(void) door_return(buf, used, NULL, 0);
-
return;
decode_error:
@@ -324,25 +310,17 @@ decode_error:
smb_dr_put_uint32(enc_ctx, dec_status);
(void) smb_dr_encode_finish(enc_ctx, &used);
(void) door_return(buf, used, NULL, 0);
- return;
-
-encode_error:
- enc_ctx = smb_dr_encode_start(buf, sizeof (buf));
- smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_ERROR);
- smb_dr_put_uint32(enc_ctx, enc_status);
- (void) smb_dr_encode_finish(enc_ctx, &used);
- (void) door_return(buf, used, NULL, 0);
}
/*
- * smb_lmshrd_srv_check
+ * smb_share_dsrv_check
*
* Depending upon the opcode, this function will
* either check the existence of a share/dir or
* the the type of the specified share.
*/
static int
-smb_lmshrd_srv_check(int opcode, char *sharename)
+smb_share_dsrv_check(int opcode, char *sharename)
{
int rc;
@@ -373,3 +351,111 @@ smb_lmshrd_srv_check(int opcode, char *sharename)
return (rc);
}
+
+/*
+ * 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
+ * twice. In the first round the total number of shares which their OEM
+ * name is shorter than 13 chars (esi->es_ntotal) and also the number of
+ * shares that fit in the given buffer are calculated. In the second
+ * round the shares data are encoded in the buffer.
+ *
+ * The data associated with each share has two parts, a fixed size part and
+ * a variable size part which is share's comment. The outline of the response
+ * buffer is so that fixed part for all the shares will appear first and follows
+ * with the comments for all those shares and that's why the data cannot be
+ * encoded in one round without unnecessarily complicating the code.
+ */
+static int
+smb_share_dsrv_enum(smb_enumshare_info_t *esi)
+{
+ lmshare_iterator_t shi;
+ lmshare_info_t *si;
+ int remained;
+ uint16_t infolen = 0;
+ uint16_t cmntlen = 0;
+ uint16_t sharelen;
+ uint16_t clen;
+ uint32_t cmnt_offs;
+ smb_msgbuf_t info_mb;
+ smb_msgbuf_t cmnt_mb;
+ boolean_t autohome_added = B_FALSE;
+
+ esi->es_ntotal = esi->es_nsent = 0;
+
+ if ((esi->es_buf = malloc(esi->es_bufsize)) == NULL)
+ return (NERR_InternalError);
+
+ bzero(esi->es_buf, esi->es_bufsize);
+ remained = esi->es_bufsize;
+
+ /* Do the necessary calculations in the first round */
+ lmshare_init_iterator(&shi, LMSHRM_ALL);
+
+ while ((si = lmshare_iterate(&shi)) != NULL) {
+ if (si->mode & LMSHRM_LONGNAME)
+ continue;
+
+ if ((si->mode & LMSHRM_AUTOHOME) && !autohome_added) {
+ if (strcasecmp(esi->es_username, si->share_name) == 0)
+ autohome_added = B_TRUE;
+ else
+ continue;
+ }
+
+ esi->es_ntotal++;
+
+ if (remained <= 0)
+ continue;
+
+ clen = strlen(si->comment) + 1;
+ sharelen = SHARE_INFO_1_SIZE + clen;
+
+ if (sharelen <= remained) {
+ infolen += SHARE_INFO_1_SIZE;
+ cmntlen += clen;
+ }
+
+ remained -= sharelen;
+ }
+
+ esi->es_datasize = infolen + cmntlen;
+
+ smb_msgbuf_init(&info_mb, (uint8_t *)esi->es_buf, infolen, 0);
+ smb_msgbuf_init(&cmnt_mb, (uint8_t *)esi->es_buf + infolen, cmntlen, 0);
+ cmnt_offs = infolen;
+
+ /* Encode the data in the second round */
+ lmshare_init_iterator(&shi, LMSHRM_ALL);
+ autohome_added = B_FALSE;
+
+ while ((si = lmshare_iterate(&shi)) != NULL) {
+ if (si->mode & LMSHRM_LONGNAME)
+ continue;
+
+ if ((si->mode & LMSHRM_AUTOHOME) && !autohome_added) {
+ if (strcasecmp(esi->es_username, si->share_name) == 0)
+ autohome_added = B_TRUE;
+ else
+ continue;
+ }
+
+ if (smb_msgbuf_encode(&info_mb, "13c.wl",
+ si->oem_name, si->stype, cmnt_offs) < 0)
+ break;
+
+ if (smb_msgbuf_encode(&cmnt_mb, "s", si->comment) < 0)
+ break;
+
+ cmnt_offs += strlen(si->comment) + 1;
+ esi->es_nsent++;
+ }
+
+ smb_msgbuf_term(&info_mb);
+ smb_msgbuf_term(&cmnt_mb);
+
+ return (NERR_Success);
+}
diff --git a/usr/src/common/smbsrv/smb_share_door_decode.c b/usr/src/common/smbsrv/smb_share_door_decode.c
index cc3f2884e8..62628063dc 100644
--- a/usr/src/common/smbsrv/smb_share_door_decode.c
+++ b/usr/src/common/smbsrv/smb_share_door_decode.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,28 +46,6 @@
#include <smbsrv/smbinfo.h>
void
-smb_dr_get_kconfig(smb_dr_ctx_t *ctx, smb_kmod_cfg_t *cfg)
-{
- if (ctx->status == 0) {
- (void) memcpy(cfg, ctx->ptr, sizeof (smb_kmod_cfg_t));
- ctx->ptr += sizeof (smb_kmod_cfg_t);
- }
- else
- bzero(cfg, sizeof (smb_kmod_cfg_t));
-}
-
-void
-smb_dr_put_kconfig(smb_dr_ctx_t *ctx, smb_kmod_cfg_t *cfg)
-{
- if (ctx->ptr + sizeof (smb_kmod_cfg_t) <= ctx->end_ptr) {
- (void) memcpy(ctx->ptr, cfg, sizeof (smb_kmod_cfg_t));
- ctx->ptr += sizeof (smb_kmod_cfg_t);
- }
- else
- ctx->status = ENOSPC;
-}
-
-void
smb_dr_get_lmshare(smb_dr_ctx_t *ctx, lmshare_info_t *si)
{
if (ctx->status == 0) {
@@ -98,30 +76,6 @@ smb_dr_put_lmshare(smb_dr_ctx_t *ctx, lmshare_info_t *si)
smb_dr_put_int32(ctx, 0);
}
-uint64_t
-smb_dr_get_lmshr_iterator(smb_dr_ctx_t *ctx)
-{
- uint64_t lmshr_iter;
-
- if (smb_dr_get_int32(ctx))
- lmshr_iter = smb_dr_get_uint64(ctx);
- else
- lmshr_iter = 0;
-
- return (lmshr_iter);
-}
-
-void
-smb_dr_put_lmshr_iterator(smb_dr_ctx_t *ctx, uint64_t lmshr_iter)
-{
- if (lmshr_iter) {
- smb_dr_put_int32(ctx, 1);
- smb_dr_put_uint64(ctx, lmshr_iter);
- }
- else
- smb_dr_put_int32(ctx, 0);
-}
-
void
smb_dr_get_lmshr_list(smb_dr_ctx_t *ctx, lmshare_list_t *shrlist)
{
diff --git a/usr/src/lib/libshare/smb/libshare_smb.c b/usr/src/lib/libshare/smb/libshare_smb.c
index bec97b7c39..cbbc9297cb 100644
--- a/usr/src/lib/libshare/smb/libshare_smb.c
+++ b/usr/src/lib/libshare/smb/libshare_smb.c
@@ -413,7 +413,6 @@ smb_enable_share(sa_share_t share)
for (resource = sa_get_share_resource(share, NULL);
resource != NULL;
resource = sa_get_next_resource(resource)) {
- sa_optionset_t opts;
bzero(&si, sizeof (lmshare_info_t));
rname = sa_get_resource_attr(resource, "name");
if (rname == NULL) {
@@ -421,11 +420,9 @@ smb_enable_share(sa_share_t share)
return (SA_NO_SUCH_RESOURCE);
}
- opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
- smb_build_lmshare_info(rname, path, opts, &si);
+ smb_build_lmshare_info(rname, path, resource, &si);
sa_free_attr_string(rname);
- sa_free_derived_optionset(opts);
if (!iszfs) {
err = lmshrd_add(&si);
} else {
@@ -458,7 +455,6 @@ smb_enable_resource(sa_resource_t resource)
{
char *path;
char *rname;
- sa_optionset_t opts;
sa_share_t share;
lmshare_info_t si;
int ret = SA_OK;
@@ -492,11 +488,9 @@ smb_enable_resource(sa_resource_t resource)
return (SA_NO_SUCH_RESOURCE);
}
- opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
- smb_build_lmshare_info(rname, path, opts, &si);
+ smb_build_lmshare_info(rname, path, resource, &si);
sa_free_attr_string(path);
sa_free_attr_string(rname);
- sa_free_derived_optionset(opts);
/*
* Attempt to add the share. Any error that occurs if it was
@@ -595,7 +589,6 @@ smb_resource_changed(sa_resource_t resource)
lmshare_info_t si;
lmshare_info_t new_si;
char *rname, *path;
- sa_optionset_t opts;
sa_share_t share;
rname = sa_get_resource_attr(resource, "name");
@@ -627,9 +620,7 @@ smb_resource_changed(sa_resource_t resource)
return (SA_CONFIG_ERR);
}
- opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
- smb_build_lmshare_info(rname, path, opts, &new_si);
- sa_free_derived_optionset(opts);
+ smb_build_lmshare_info(rname, path, resource, &new_si);
sa_free_attr_string(path);
sa_free_attr_string(rname);
diff --git a/usr/src/lib/libshare/smb/smb_share_doorclnt.c b/usr/src/lib/libshare/smb/smb_share_doorclnt.c
index 1a06278568..731b70c47c 100644
--- a/usr/src/lib/libshare/smb/smb_share_doorclnt.c
+++ b/usr/src/lib/libshare/smb/smb_share_doorclnt.c
@@ -54,9 +54,6 @@ static cond_t lmshrd_cv;
char *lmshrd_desc[] = {
"",
- "LmshrdOpenIter",
- "LmshrdCloseIter",
- "LmshrdIterate",
"LmshrdNumShares",
"LmshrdDelete",
"LmshrdRename",
@@ -70,7 +67,6 @@ char *lmshrd_desc[] = {
"LmshrdIsValid",
"LmshrdIsDir",
"LmshrdList",
- "LmshrdListTrans",
"LmshrdNumTrans",
"N/A",
0
@@ -179,140 +175,6 @@ lmshrd_door_check_status(smb_dr_ctx_t *dec_ctx)
return (0);
}
-uint64_t
-lmshrd_open_iterator(int mode)
-{
- door_arg_t *arg;
- smb_dr_ctx_t *dec_ctx;
- smb_dr_ctx_t *enc_ctx;
- uint64_t lmshr_iter = 0;
- int rc;
-
- if ((arg = lmshrd_door_enter()) == NULL)
- return (lmshr_iter);
-
- enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE);
- smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_OPEN_ITERATOR);
- smb_dr_put_int32(enc_ctx, mode);
-
- rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
- if (rc != 0) {
- lmshrd_door_exit(arg, "encode error");
- return (lmshr_iter);
- }
-
- if (door_call(lmshrd_fildes, arg) < 0) {
- lmshrd_door_exit(arg, "door call error");
- lmshrd_door_close();
- return (lmshr_iter);
- }
-
- dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
- if (lmshrd_door_check_status(dec_ctx) != 0) {
- (void) smb_dr_decode_finish(dec_ctx);
- lmshrd_door_exit(arg, "decode error");
- return (lmshr_iter);
- }
-
- lmshr_iter = smb_dr_get_lmshr_iterator(dec_ctx);
- if (smb_dr_decode_finish(dec_ctx) != 0) {
- lmshrd_door_exit(arg, "decode error");
- return (lmshr_iter);
- }
-
- lmshrd_door_exit(arg, NULL);
- return (lmshr_iter);
-}
-
-
-DWORD
-lmshrd_close_iterator(uint64_t iterator)
-{
- door_arg_t *arg;
- smb_dr_ctx_t *dec_ctx;
- smb_dr_ctx_t *enc_ctx;
- int rc;
-
- if ((arg = lmshrd_door_enter()) == NULL)
- return (NERR_InternalError);
-
- enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE);
- smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_CLOSE_ITERATOR);
- smb_dr_put_lmshr_iterator(enc_ctx, iterator);
-
- rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
- if (rc != 0) {
- lmshrd_door_exit(arg, "encode error");
- return (NERR_InternalError);
- }
-
- if (door_call(lmshrd_fildes, arg) < 0) {
- lmshrd_door_exit(arg, "door call error");
- lmshrd_door_close();
- return (NERR_InternalError);
- }
-
- dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
- if (lmshrd_door_check_status(dec_ctx) != 0) {
- (void) smb_dr_decode_finish(dec_ctx);
- lmshrd_door_exit(arg, "decode error");
- return (NERR_InternalError);
- }
-
- if (smb_dr_decode_finish(dec_ctx) != 0) {
- lmshrd_door_exit(arg, "decode error");
- return (NERR_InternalError);
- }
-
- lmshrd_door_exit(arg, NULL);
- return (NERR_Success);
-}
-
-DWORD
-lmshrd_iterate(uint64_t iterator, lmshare_info_t *si)
-{
- door_arg_t *arg;
- smb_dr_ctx_t *dec_ctx;
- smb_dr_ctx_t *enc_ctx;
- int rc;
-
- if ((arg = lmshrd_door_enter()) == NULL)
- return (NERR_InternalError);
-
- bzero(si, sizeof (lmshare_info_t));
- enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE);
- smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_ITERATE);
- smb_dr_put_lmshr_iterator(enc_ctx, iterator);
-
- rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
- if (rc != 0) {
- lmshrd_door_exit(arg, "encode error");
- return (NERR_InternalError);
- }
-
- if (door_call(lmshrd_fildes, arg) < 0) {
- lmshrd_door_exit(arg, "door call error");
- lmshrd_door_close();
- return (NERR_InternalError);
- }
-
- dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
- if (lmshrd_door_check_status(dec_ctx) != 0) {
- (void) smb_dr_decode_finish(dec_ctx);
- lmshrd_door_exit(arg, "decode error");
- return (NERR_InternalError);
- }
-
- smb_dr_get_lmshare(dec_ctx, si);
- if (smb_dr_decode_finish(dec_ctx) != 0) {
- lmshrd_door_exit(arg, "decode error");
- return (NERR_InternalError);
- }
-
- lmshrd_door_exit(arg, NULL);
- return (NERR_Success);
-}
-
DWORD
lmshrd_list(int offset, lmshare_list_t *list)
{
@@ -347,7 +209,6 @@ lmshrd_list(int offset, lmshare_list_t *list)
return (NERR_InternalError);
}
- rc = smb_dr_get_uint32(dec_ctx);
smb_dr_get_lmshr_list(dec_ctx, list);
if (smb_dr_decode_finish(dec_ctx) != 0) {
lmshrd_door_exit(arg, "decode error");
@@ -355,7 +216,7 @@ lmshrd_list(int offset, lmshare_list_t *list)
}
lmshrd_door_exit(arg, NULL);
- return (rc);
+ return (NERR_Success);
}
int
diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c
index b64ada2955..c6f889f5d7 100644
--- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c
+++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c
@@ -899,11 +899,14 @@ mlndr_outer_conformant_array(struct ndr_reference *outer_ref)
return (0);
}
- valp = MLNDS_MALLOC(mlnds, n_alloc, outer_ref);
- if (!valp) {
- NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
- return (0);
+ if (size_is > 0) {
+ valp = MLNDS_MALLOC(mlnds, n_alloc, outer_ref);
+ if (!valp) {
+ NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
+ return (0);
+ }
}
+
if (outer_ref->backptr)
*outer_ref->backptr = valp;
outer_ref->datum = valp;
@@ -914,28 +917,30 @@ mlndr_outer_conformant_array(struct ndr_reference *outer_ref)
return (0);
}
- bzero(&myref, sizeof (myref));
- myref.stream = mlnds;
- myref.enclosing = outer_ref;
- myref.ti = outer_ref->ti;
- myref.datum = outer_ref->datum;
- myref.name = "CONFORMANT-ARRAY";
- myref.outer_flags = NDR_F_NONE;
- myref.inner_flags = NDR_F_SIZE_IS;
- myref.size_is = outer_ref->size_is;
-
- myref.inner_flags = NDR_F_DIMENSION_IS; /* convenient */
- myref.dimension_is = outer_ref->size_is; /* convenient */
-
- myref.pdu_offset = outer_ref->pdu_offset + 4;
outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total;
-
outer_ref->type_flags = NDR_F_NONE;
outer_ref->inner_flags = NDR_F_NONE;
- rc = mlndr_inner(&myref);
- if (!rc)
- return (rc); /* error already set */
+ if (size_is > 0) {
+ bzero(&myref, sizeof (myref));
+ myref.stream = mlnds;
+ myref.enclosing = outer_ref;
+ myref.ti = outer_ref->ti;
+ myref.datum = outer_ref->datum;
+ myref.name = "CONFORMANT-ARRAY";
+ myref.outer_flags = NDR_F_NONE;
+ myref.inner_flags = NDR_F_SIZE_IS;
+ myref.size_is = outer_ref->size_is;
+
+ myref.inner_flags = NDR_F_DIMENSION_IS; /* convenient */
+ myref.dimension_is = outer_ref->size_is; /* convenient */
+
+ myref.pdu_offset = outer_ref->pdu_offset + 4;
+
+ rc = mlndr_inner(&myref);
+ if (!rc)
+ return (rc); /* error already set */
+ }
mlnds->pdu_scan_offset = outer_ref->pdu_end_offset;
return (1);
@@ -1041,6 +1046,10 @@ mlndr_outer_conformant_construct(struct ndr_reference *outer_ref)
return (0);
}
+ outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total;
+ outer_ref->type_flags = NDR_F_SIZE_IS; /* indicate pending */
+ outer_ref->inner_flags = NDR_F_NONE; /* indicate pending */
+
bzero(&myref, sizeof (myref));
myref.stream = mlnds;
myref.enclosing = outer_ref;
@@ -1052,10 +1061,6 @@ mlndr_outer_conformant_construct(struct ndr_reference *outer_ref)
myref.size_is = outer_ref->size_is;
myref.pdu_offset = outer_ref->pdu_offset + 4;
- outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total;
-
- outer_ref->type_flags = NDR_F_SIZE_IS; /* indicate pending */
- outer_ref->inner_flags = NDR_F_NONE; /* indicate pending */
rc = mlndr_inner(&myref);
if (!rc)
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h
index 102f6d2ca4..07b25d1805 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h
+++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h
@@ -62,13 +62,9 @@ typedef struct smb_autohome {
char *ah_container; /* ADS container distinguished name */
} smb_autohome_t;
-extern int smb_autohome_add(const char *);
-extern int smb_autohome_remove(const char *);
-extern int smb_is_autohome(const lmshare_info_t *);
-extern void smb_autohome_setent(void);
-extern void smb_autohome_endent(void);
-extern smb_autohome_t *smb_autohome_getent(const char *name);
-extern smb_autohome_t *smb_autohome_lookup(const char *name);
+extern void smb_autohome_add(const char *);
+extern void smb_autohome_remove(const char *);
+extern boolean_t smb_is_autohome(const lmshare_info_t *);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c b/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c
index 5a52c64513..b64b7ac1ad 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c
@@ -68,10 +68,11 @@ static HT_HANDLE *lmshare_handle = NULL;
static rwlock_t lmshare_lock;
static pthread_t lmshare_load_thread;
static void *lmshare_load(void *);
-static DWORD lmshare_create_table();
+static DWORD lmshare_create_table(void);
static int lmshare_delete_shmgr(struct lmshare_info *);
static int lmshare_setinfo_shmgr(struct lmshare_info *);
-static DWORD lmshare_set_refcnt(char *share_name, int refcnt);
+static DWORD lmshare_set_refcnt(char *, int);
+static void lmshare_set_oemname(lmshare_info_t *);
typedef struct lmshare_ad_item {
TAILQ_ENTRY(lmshare_ad_item) next;
@@ -139,7 +140,6 @@ lmshare_load_shares(sa_group_t group)
{
sa_share_t share;
sa_resource_t resource;
- sa_optionset_t opts;
lmshare_info_t si;
char *path, *rname;
@@ -162,10 +162,7 @@ lmshare_load_shares(sa_group_t group)
"resource for path: %s", path);
continue;
}
- opts = sa_get_derived_optionset(resource,
- SMB_PROTOCOL_NAME, 1);
- smb_build_lmshare_info(rname, path, opts, &si);
- sa_free_derived_optionset(opts);
+ smb_build_lmshare_info(rname, path, resource, &si);
sa_free_attr_string(rname);
if (lmshare_add(&si, 0) != NERR_Success) {
syslog(LOG_ERR, "Failed to load "
@@ -250,7 +247,7 @@ static void
lmshare_callback(HT_ITEM *item)
{
if (item && item->hi_data)
- (void) free(item->hi_data);
+ free(item->hi_data);
}
/*
@@ -297,7 +294,7 @@ lmshare_add_adminshare(char *volname, unsigned char drive)
bzero(&si, sizeof (lmshare_info_t));
(void) strcpy(si.directory, volname);
- si.mode = LMSHRM_TRANS;
+ si.mode = LMSHRM_TRANS | LMSHRM_ADMIN;
(void) snprintf(si.share_name, sizeof (si.share_name), "%c$", drive);
rc = lmshare_add(&si, 0);
@@ -324,55 +321,22 @@ lmshare_num_shares(void)
}
/*
- * lmshare_open_iterator
+ * lmshare_init_iterator
*
- * Create and initialize an iterator for traversing hash table.
- * It gets a mode that can be LMSHR_IM_ALL to iterate through all
- * the shares stored in table or LMSHR_IM_PRES to iterate through
- * only presentable shares.
- *
- * It also accepts a local IP address. This is used in dual head
- * systems to only return the shares that belong to the head which
- * is specified by the 'ipaddr'. If ipaddr is 0 it'll return shares
- * of both heads.
- *
- * On success return pointer to the new iterator.
- * On failure return (NULL).
- */
-lmshare_iterator_t *
-lmshare_open_iterator(int mode)
-{
- lmshare_iterator_t *shi;
- int sz = sizeof (lmshare_iterator_t) + sizeof (HT_ITERATOR);
-
- shi = malloc(sz);
- if (shi != NULL) {
- bzero(shi, sz);
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- shi->iterator = (HT_ITERATOR *)
- ((char *)shi + sizeof (lmshare_iterator_t));
- shi->mode = mode;
- } else {
- syslog(LOG_DEBUG, "Failed to create share iterator handle");
- }
- return (shi);
-}
-
-/*
- * lmshare_close_iterator
- *
- * Free memory allocated by the given iterator.
+ * Initialize an iterator for traversing hash table.
+ * 'mode' is used for filtering shares when iterating.
*/
void
-lmshare_close_iterator(lmshare_iterator_t *shi)
+lmshare_init_iterator(lmshare_iterator_t *shi, uint32_t mode)
{
- (void) free(shi);
+ bzero(shi, sizeof (lmshare_iterator_t));
+ shi->mode = mode;
}
/*
* lmshare_iterate
*
- * Iterate on the shares in the hash table. The iterator must be opened
+ * Iterate on the shares in the hash table. The iterator must be initialized
* before the first iteration. On subsequent calls, the iterator must be
* passed unchanged.
*
@@ -396,6 +360,7 @@ lmshare_iterate(lmshare_iterator_t *shi)
* IPC$ is always first.
*/
(void) strcpy(shi->si.share_name, "IPC$");
+ lmshare_set_oemname(&shi->si);
shi->si.mode = LMSHRM_TRANS;
shi->si.stype = (int)(STYPE_IPC | STYPE_SPECIAL);
shi->iteration = 1;
@@ -404,7 +369,7 @@ lmshare_iterate(lmshare_iterator_t *shi)
if (shi->iteration == 1) {
if ((item = ht_findfirst(
- lmshare_handle, shi->iterator)) == NULL) {
+ lmshare_handle, &shi->iterator)) == NULL) {
return (NULL);
}
@@ -412,18 +377,16 @@ lmshare_iterate(lmshare_iterator_t *shi)
++shi->iteration;
if (si->mode & shi->mode) {
- (void) memcpy(&(shi->si), si,
- sizeof (lmshare_info_t));
+ (void) memcpy(&(shi->si), si, sizeof (lmshare_info_t));
return (&(shi->si));
}
}
- while ((item = ht_findnext(shi->iterator)) != NULL) {
+ while ((item = ht_findnext(&shi->iterator)) != NULL) {
si = (lmshare_info_t *)(item->hi_data);
++shi->iteration;
if (si->mode & shi->mode) {
(void) memcpy(&(shi->si), si, sizeof (lmshare_info_t));
-
return (&(shi->si));
}
}
@@ -451,7 +414,10 @@ lmshare_add(lmshare_info_t *si, int doshm)
(void) utf8_strlwr(si->share_name);
if (lmshare_exists(si->share_name)) {
- if ((si->mode & LMSHRM_TRANS) == 0)
+ /*
+ * Only autohome shares can be added multiple times
+ */
+ if ((si->mode & LMSHRM_AUTOHOME) == 0)
return (NERR_DuplicateShare);
}
@@ -460,7 +426,7 @@ lmshare_add(lmshare_info_t *si, int doshm)
lmshare_do_publish(si, LMSHR_PUBLISH, 1);
}
- if ((si->mode & LMSHRM_TRANS) && (status == NERR_Success)) {
+ if ((si->mode & LMSHRM_AUTOHOME) && (status == NERR_Success)) {
si->refcnt++;
status = lmshare_set_refcnt(si->share_name, si->refcnt);
}
@@ -507,7 +473,7 @@ lmshare_delete(char *share_name, int doshm)
return (NERR_InternalError);
}
- if ((si->mode & LMSHRM_TRANS) != 0) {
+ if ((si->mode & LMSHRM_AUTOHOME) == LMSHRM_AUTOHOME) {
si->refcnt--;
if (si->refcnt > 0) {
status = lmshare_set_refcnt(si->share_name, si->refcnt);
@@ -993,11 +959,13 @@ lmshare_setinfo(lmshare_info_t *si, int doshm)
}
} else {
/* Unpublish old share from AD */
- if ((si->mode & LMSHRM_TRANS) == 0) {
+ if ((add_si->mode & LMSHRM_PERM) == LMSHRM_PERM)
lmshare_do_publish(&old_si, LMSHR_UNPUBLISH, 1);
- }
(void) del_fromhash(si->share_name);
}
+
+ lmshare_set_oemname(add_si);
+
/* if it's not transient it should be permanent */
if ((add_si->mode & LMSHRM_TRANS) == 0)
add_si->mode |= LMSHRM_PERM;
@@ -1016,7 +984,7 @@ lmshare_setinfo(lmshare_info_t *si, int doshm)
}
(void) rw_unlock(&lmshare_lock);
- if ((add_si->mode & LMSHRM_TRANS) == 0) {
+ if ((add_si->mode & LMSHRM_PERM) == LMSHRM_PERM) {
if (doshm && (lmshare_setinfo_shmgr(add_si) != 0)) {
syslog(LOG_ERR, "Update share %s in sharemgr failed",
add_si->share_name);
@@ -1028,21 +996,20 @@ lmshare_setinfo(lmshare_info_t *si, int doshm)
return (res);
}
-DWORD
+void
lmshare_list(int offset, lmshare_list_t *list)
{
- lmshare_iterator_t *iterator;
+ lmshare_iterator_t iterator;
lmshare_info_t *si;
int list_idx = 0;
int i = 0;
bzero(list, sizeof (lmshare_list_t));
- if ((iterator = lmshare_open_iterator(LMSHRM_ALL)) == NULL)
- return (NERR_InternalError);
+ lmshare_init_iterator(&iterator, LMSHRM_ALL);
- (void) lmshare_iterate(iterator); /* To skip IPC$ */
+ (void) lmshare_iterate(&iterator); /* To skip IPC$ */
- while ((si = lmshare_iterate(iterator)) != NULL) {
+ while ((si = lmshare_iterate(&iterator)) != NULL) {
if (lmshare_is_special(si->share_name)) {
/*
* Don't return restricted shares.
@@ -1059,11 +1026,8 @@ lmshare_list(int offset, lmshare_list_t *list)
if (++list_idx == LMSHARES_PER_REQUEST)
break;
}
- lmshare_close_iterator(iterator);
list->no = list_idx;
-
- return (NERR_Success);
}
/*
@@ -1076,8 +1040,10 @@ lmshare_do_publish(lmshare_info_t *si, char flag, int poke)
if (publish_on == 0)
return;
+
if ((si == NULL) || (si->container[0] == '\0'))
return;
+
(void) mutex_lock(&lmshare_publish_mutex);
item = (lmshare_ad_item_t *)malloc(sizeof (lmshare_ad_item_t));
if (item == NULL) {
@@ -1221,3 +1187,47 @@ lmshare_get_realpath(const char *clipath, char *realpath, int maxlen)
/* XXX do this translation */
return (NERR_Success);
}
+
+/*
+ * lmshare_set_oemname
+ *
+ * Generates the OEM name of the given share. If it's
+ * shorter than 13 chars it'll be saved in si->oem_name.
+ * Otherwise si->oem_name will be empty and LMSHRM_LONGNAME
+ * will be set in si->mode.
+ */
+static void
+lmshare_set_oemname(lmshare_info_t *si)
+{
+ unsigned int cpid = oem_get_smb_cpid();
+ mts_wchar_t *unibuf;
+ char *oem_name;
+ int length;
+
+ length = strlen(si->share_name) + 1;
+
+ oem_name = malloc(length);
+ unibuf = malloc(length * sizeof (mts_wchar_t));
+ if ((oem_name == NULL) || (unibuf == NULL)) {
+ free(oem_name);
+ free(unibuf);
+ return;
+ }
+
+ (void) mts_mbstowcs(unibuf, si->share_name, length);
+
+ if (unicodestooems(oem_name, unibuf, length, cpid) == 0)
+ (void) strcpy(oem_name, si->share_name);
+
+ free(unibuf);
+
+ if (strlen(oem_name) + 1 > LMSHR_OEM_NAME_MAX) {
+ si->mode |= LMSHRM_LONGNAME;
+ *si->oem_name = '\0';
+ } else {
+ si->mode &= ~LMSHRM_LONGNAME;
+ (void) strlcpy(si->oem_name, oem_name, LMSHR_OEM_NAME_MAX);
+ }
+
+ free(oem_name);
+}
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
index 96ef7d3d9d..a33e61cad5 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
@@ -28,7 +28,6 @@
SUNWprivate {
global:
lmshare_add;
- lmshare_close_iterator;
lmshare_delete;
lmshare_exists;
lmshare_getinfo;
@@ -41,7 +40,7 @@ SUNWprivate {
lmshare_iterate;
lmshare_list;
lmshare_num_shares;
- lmshare_open_iterator;
+ lmshare_init_iterator;
lmshare_rename;
lmshare_setinfo;
lmshare_start;
@@ -60,11 +59,7 @@ SUNWprivate {
smb_build_lmshare_info;
smb_get_smb_share_group;
smb_autohome_add;
- smb_autohome_endent;
- smb_autohome_getent;
- smb_autohome_lookup;
smb_autohome_remove;
- smb_autohome_setent;
smb_is_autohome;
local:
*;
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c
index 65d96399ed..bbd3b2c6cc 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c
@@ -1328,7 +1328,7 @@ mlsvc_NetShareEnumLevel0(struct mlrpc_xaction *mxa,
struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
{
struct mslm_SHARE_INFO_0 *info0;
- lmshare_iterator_t *iterator;
+ lmshare_iterator_t iterator;
lmshare_info_t *si;
DWORD status;
@@ -1341,12 +1341,10 @@ mlsvc_NetShareEnumLevel0(struct mlrpc_xaction *mxa,
if (info0 == NULL)
return (ERROR_NOT_ENOUGH_MEMORY);
- iterator = lmshare_open_iterator(LMSHRM_ALL);
- if (iterator == NULL)
- return (ERROR_NOT_ENOUGH_MEMORY);
+ lmshare_init_iterator(&iterator, LMSHRM_ALL);
se->se_n_read = 0;
- while ((si = lmshare_iterate(iterator)) != NULL) {
+ while ((si = lmshare_iterate(&iterator)) != NULL) {
if (se->se_n_skip > 0) {
--se->se_n_skip;
continue;
@@ -1377,7 +1375,6 @@ mlsvc_NetShareEnumLevel0(struct mlrpc_xaction *mxa,
++se->se_n_read;
}
- lmshare_close_iterator(iterator);
infonres->entriesread = se->se_n_read;
infonres->entries = info0;
return (ERROR_SUCCESS);
@@ -1391,7 +1388,7 @@ mlsvc_NetShareEnumLevel1(struct mlrpc_xaction *mxa,
struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
{
struct mslm_SHARE_INFO_1 *info1;
- lmshare_iterator_t *iterator;
+ lmshare_iterator_t iterator;
lmshare_info_t *si;
DWORD status;
@@ -1404,12 +1401,10 @@ mlsvc_NetShareEnumLevel1(struct mlrpc_xaction *mxa,
if (info1 == NULL)
return (ERROR_NOT_ENOUGH_MEMORY);
- iterator = lmshare_open_iterator(LMSHRM_ALL);
- if (iterator == NULL)
- return (ERROR_NOT_ENOUGH_MEMORY);
+ lmshare_init_iterator(&iterator, LMSHRM_ALL);
se->se_n_read = 0;
- while ((si = lmshare_iterate(iterator)) != 0) {
+ while ((si = lmshare_iterate(&iterator)) != 0) {
if (se->se_n_skip > 0) {
--se->se_n_skip;
continue;
@@ -1440,7 +1435,6 @@ mlsvc_NetShareEnumLevel1(struct mlrpc_xaction *mxa,
++se->se_n_read;
}
- lmshare_close_iterator(iterator);
infonres->entriesread = se->se_n_read;
infonres->entries = info1;
return (ERROR_SUCCESS);
@@ -1454,7 +1448,7 @@ mlsvc_NetShareEnumLevel2(struct mlrpc_xaction *mxa,
struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
{
struct mslm_SHARE_INFO_2 *info2;
- lmshare_iterator_t *iterator;
+ lmshare_iterator_t iterator;
lmshare_info_t *si;
DWORD status;
@@ -1467,12 +1461,10 @@ mlsvc_NetShareEnumLevel2(struct mlrpc_xaction *mxa,
if (info2 == 0)
return (ERROR_NOT_ENOUGH_MEMORY);
- iterator = lmshare_open_iterator(LMSHRM_ALL);
- if (iterator == NULL)
- return (ERROR_NOT_ENOUGH_MEMORY);
+ lmshare_init_iterator(&iterator, LMSHRM_ALL);
se->se_n_read = 0;
- while ((si = lmshare_iterate(iterator)) != 0) {
+ while ((si = lmshare_iterate(&iterator)) != 0) {
if (se->se_n_skip > 0) {
--se->se_n_skip;
continue;
@@ -1503,7 +1495,6 @@ mlsvc_NetShareEnumLevel2(struct mlrpc_xaction *mxa,
++se->se_n_read;
}
- lmshare_close_iterator(iterator);
infonres->entriesread = se->se_n_read;
infonres->entries = info2;
return (ERROR_SUCCESS);
@@ -1517,7 +1508,7 @@ mlsvc_NetShareEnumLevel501(struct mlrpc_xaction *mxa,
struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
{
struct mslm_SHARE_INFO_501 *info501;
- lmshare_iterator_t *iterator;
+ lmshare_iterator_t iterator;
lmshare_info_t *si;
DWORD status;
@@ -1531,12 +1522,10 @@ mlsvc_NetShareEnumLevel501(struct mlrpc_xaction *mxa,
if (info501 == NULL)
return (ERROR_NOT_ENOUGH_MEMORY);
- iterator = lmshare_open_iterator(LMSHRM_ALL);
- if (iterator == NULL)
- return (ERROR_NOT_ENOUGH_MEMORY);
+ lmshare_init_iterator(&iterator, LMSHRM_ALL);
se->se_n_read = 0;
- while ((si = lmshare_iterate(iterator)) != 0) {
+ while ((si = lmshare_iterate(&iterator)) != 0) {
if (se->se_n_skip > 0) {
--se->se_n_skip;
continue;
@@ -1567,7 +1556,6 @@ mlsvc_NetShareEnumLevel501(struct mlrpc_xaction *mxa,
++se->se_n_read;
}
- lmshare_close_iterator(iterator);
infonres->entriesread = se->se_n_read;
infonres->entries = info501;
return (ERROR_SUCCESS);
@@ -1581,7 +1569,7 @@ mlsvc_NetShareEnumLevel502(struct mlrpc_xaction *mxa,
struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
{
struct mslm_SHARE_INFO_502 *info502;
- lmshare_iterator_t *iterator;
+ lmshare_iterator_t iterator;
lmshare_info_t *si;
DWORD status;
@@ -1595,12 +1583,10 @@ mlsvc_NetShareEnumLevel502(struct mlrpc_xaction *mxa,
if (info502 == NULL)
return (ERROR_NOT_ENOUGH_MEMORY);
- iterator = lmshare_open_iterator(LMSHRM_ALL);
- if (iterator == NULL)
- return (ERROR_NOT_ENOUGH_MEMORY);
+ lmshare_init_iterator(&iterator, LMSHRM_ALL);
se->se_n_read = 0;
- while ((si = lmshare_iterate(iterator)) != NULL) {
+ while ((si = lmshare_iterate(&iterator)) != NULL) {
if (se->se_n_skip > 0) {
--se->se_n_skip;
continue;
@@ -1631,7 +1617,6 @@ mlsvc_NetShareEnumLevel502(struct mlrpc_xaction *mxa,
++se->se_n_read;
}
- lmshare_close_iterator(iterator);
infonres->entriesread = se->se_n_read;
infonres->entries = info502;
return (ERROR_SUCCESS);
@@ -1791,7 +1776,7 @@ srvsvc_add_autohome(struct mlrpc_xaction *mxa, srvsvc_enum_t *se, void *infop)
if (lmshare_getinfo(username, &si) != NERR_Success)
return (B_FALSE);
- if (!(si.mode & LMSHRM_TRANS))
+ if ((si.mode & LMSHRM_AUTOHOME) == 0)
return (B_FALSE);
status = mlsvc_NetShareEnumCommon(mxa, se, &si, infop);
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c
index bc3f526046..0199489fac 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c
@@ -29,6 +29,8 @@
#include <stdlib.h>
#include <stdio.h>
#include <pwd.h>
+#include <assert.h>
+#include <strings.h>
#include <sys/stat.h>
#include <smbsrv/libsmb.h>
#include <smbsrv/libmlsvc.h>
@@ -53,6 +55,10 @@ static smb_autohome_info_t smb_ai;
static smb_autohome_t *smb_autohome_make_entry(smb_autohome_info_t *);
static char *smb_autohome_keysub(const char *, char *, int);
static smb_autohome_info_t *smb_autohome_getinfo(void);
+static smb_autohome_t *smb_autohome_lookup(const char *);
+static void smb_autohome_setent(void);
+static void smb_autohome_endent(void);
+static smb_autohome_t *smb_autohome_getent(const char *);
/*
* Add an autohome share. See smb_autohome(4) for details.
@@ -60,95 +66,65 @@ static smb_autohome_info_t *smb_autohome_getinfo(void);
* If share directory contains backslash path separators, they will
* be converted to forward slash to support NT/DOS path style for
* autohome shares.
- *
- * Returns 0 on success or -1 to indicate an error.
*/
-int
+void
smb_autohome_add(const char *username)
{
lmshare_info_t si;
- char *sharename;
smb_autohome_t *ai;
- if (username == NULL)
- return (-1);
+ assert(username);
- if ((sharename = strdup(username)) == NULL)
- return (-1);
-
- if ((ai = smb_autohome_lookup(sharename)) == NULL) {
- free(sharename);
- return (0);
- }
+ if ((ai = smb_autohome_lookup(username)) == NULL)
+ return;
- (void) memset(&si, 0, sizeof (lmshare_info_t));
+ bzero(&si, sizeof (lmshare_info_t));
(void) strlcpy(si.directory, ai->ah_path, MAXPATHLEN);
(void) strsubst(si.directory, '\\', '/');
(void) strlcpy(si.container, ai->ah_container, MAXPATHLEN);
- if (lmshare_is_dir(si.directory) == 0) {
- free(sharename);
- return (0);
- }
+ if (lmshare_is_dir(si.directory) == 0)
+ return;
- if (lmshare_exists(sharename) != 0) {
- (void) lmshare_getinfo(sharename, &si);
- if (!(si.mode & LMSHRM_TRANS)) {
- free(sharename);
- return (0);
- }
+ if (lmshare_getinfo((char *)username, &si) == NERR_Success) {
+ /*
+ * autohome shares will be added for each login attemp
+ * even if they already exist
+ */
+ if ((si.mode & LMSHRM_AUTOHOME) == 0)
+ return;
} else {
- (void) strcpy(si.share_name, sharename);
- si.mode = LMSHRM_TRANS;
+ (void) strlcpy(si.share_name, username, MAXNAMELEN);
+ si.mode = LMSHRM_TRANS | LMSHRM_AUTOHOME;
}
(void) lmshare_add(&si, 0);
- free(sharename);
- return (0);
}
/*
* Remove an autohome share.
- *
- * Returns 0 on success or -1 to indicate an error.
*/
-int
+void
smb_autohome_remove(const char *username)
{
lmshare_info_t si;
- char *sharename;
- if (username == NULL)
- return (-1);
+ assert(username);
- if ((sharename = strdup(username)) == NULL)
- return (-1);
-
- if (lmshare_getinfo(sharename, &si) == NERR_Success) {
- if (si.mode & LMSHRM_TRANS) {
- (void) lmshare_delete(sharename, 0);
+ if (lmshare_getinfo((char *)username, &si) == NERR_Success) {
+ if (si.mode & LMSHRM_AUTOHOME) {
+ (void) lmshare_delete((char *)username, 0);
}
}
-
- free(sharename);
- return (0);
}
/*
* Find out if a share is an autohome share.
- *
- * Returns 1 if the share is an autohome share.
- * Otherwise returns 0.
*/
-int
+boolean_t
smb_is_autohome(const lmshare_info_t *si)
{
- if (si && (si->mode & LMSHRM_TRANS) &&
- (lmshare_is_restricted((char *)si->share_name) == 0)) {
- return (1);
- }
-
- return (0);
+ return (si && (si->mode & LMSHRM_AUTOHOME));
}
/*
@@ -162,11 +138,11 @@ smb_is_autohome(const lmshare_info_t *si)
*
* Returns a pointer to the entry on success or null on failure.
*/
-smb_autohome_t *
+static smb_autohome_t *
smb_autohome_lookup(const char *name)
{
struct passwd *pw;
- smb_autohome_t *ah = 0;
+ smb_autohome_t *ah = NULL;
if (name == NULL)
return (NULL);
@@ -199,7 +175,7 @@ smb_autohome_lookup(const char *name)
if (strcasecmp("+nsswitch", ah->ah_name) != 0)
continue;
if ((pw = getpwnam(name)) == NULL) {
- ah = 0;
+ ah = NULL;
break;
}
@@ -220,7 +196,7 @@ smb_autohome_lookup(const char *name)
/*
* Open or rewind the autohome database.
*/
-void
+static void
smb_autohome_setent(void)
{
smb_autohome_info_t *si;
@@ -257,7 +233,7 @@ smb_autohome_setent(void)
* We can't zero the whole info structure because the application
* should still have access to the data after the file is closed.
*/
-void
+static void
smb_autohome_endent(void)
{
smb_autohome_info_t *si;
@@ -278,7 +254,7 @@ smb_autohome_endent(void)
* only used for key substitution, so that the caller sees the entry
* in expanded form.
*/
-smb_autohome_t *
+static smb_autohome_t *
smb_autohome_getent(const char *name)
{
smb_autohome_info_t *si;
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_share_util.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_share_util.c
index 8e5a7ca031..0da57bc6e3 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_share_util.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_share_util.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -32,16 +32,20 @@
#include <libshare.h>
#include <smbsrv/lmshare.h>
+#include <syslog.h>
+
static pthread_mutex_t smb_group_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Sharemanager shared API */
void
smb_build_lmshare_info(char *share_name, char *path,
- sa_optionset_t opts, lmshare_info_t *si)
+ sa_resource_t resource, lmshare_info_t *si)
{
sa_property_t prop;
char *val = NULL;
+ sa_optionset_t opts;
+ sa_share_t share;
bzero(si, sizeof (lmshare_info_t));
/* Share is read from SMF so it should be permanent */
@@ -50,6 +54,18 @@ smb_build_lmshare_info(char *share_name, char *path,
(void) strlcpy(si->directory, path, sizeof (si->directory));
(void) strlcpy(si->share_name, share_name, sizeof (si->share_name));
+ val = sa_get_resource_description(resource);
+ if (val == NULL) {
+ share = sa_get_resource_parent(resource);
+ val = sa_get_resource_description(share);
+ }
+
+ if (val != NULL) {
+ (void) strlcpy(si->comment, val, sizeof (si->comment));
+ sa_free_share_description(val);
+ }
+
+ opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
if (opts == NULL)
return;
@@ -61,14 +77,7 @@ smb_build_lmshare_info(char *share_name, char *path,
free(val);
}
}
-
- prop = (sa_property_t)sa_get_property(opts, "description");
- if (prop != NULL) {
- if ((val = sa_get_property_attr(prop, "value")) != NULL) {
- (void) strlcpy(si->comment, val, sizeof (si->comment));
- free(val);
- }
- }
+ sa_free_derived_optionset(opts);
}
/*
diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
index 36fb1b0192..3e0b8cc0c5 100644
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h
+++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
@@ -193,6 +193,8 @@ extern int smb_config_set_secmode(int);
extern int smb_config_set_idmap_domain(char *);
extern int smb_config_refresh_idmap(void);
+extern void smb_load_kconfig(smb_kmod_cfg_t *kcfg);
+
extern boolean_t smb_match_netlogon_seqnum(void);
extern int smb_setdomainprops(char *, char *, char *);
extern void smb_update_netlogon_seqnum(void);
diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
index 43469722ea..4cb2da2227 100644
--- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
@@ -142,7 +142,6 @@ SUNWprivate {
smb_dr_get_dword;
smb_dr_get_int32;
smb_dr_get_lmshare;
- smb_dr_get_lmshr_iterator;
smb_dr_get_lmshr_list;
smb_dr_get_opcode;
smb_dr_get_res_stat;
@@ -156,9 +155,7 @@ SUNWprivate {
smb_dr_put_buf;
smb_dr_put_dword;
smb_dr_put_int32;
- smb_dr_put_kconfig;
smb_dr_put_lmshare;
- smb_dr_put_lmshr_iterator;
smb_dr_put_lmshr_list;
smb_dr_put_short;
smb_dr_put_string;
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index a5944235c1..536e46a7ae 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -940,6 +940,7 @@ SMBSRV_OBJS += $(SMBSRV_SHARED_OBJS) \
smb_kdoor_ops.o \
smb_kdoor_clnt.o \
smb_kdoor_srv.o \
+ smb_kshare.o \
smb_lock_byte_range.o \
smb_lock_svc.o \
smb_locking_andx.o \
@@ -979,7 +980,6 @@ SMBSRV_OBJS += $(SMBSRV_SHARED_OBJS) \
smb_set_information.o \
smb_set_information2.o \
smb_signing.o \
- smb_share_kdoor_client.o \
smb_tree.o \
smb_trans2_create_directory.o \
smb_trans2_dfs.o \
@@ -1043,11 +1043,12 @@ NSMB_OBJS += smb_conn.o smb_crypt.o smb_dev.o smb_iod.o \
smb_rq.o smb_smb.o smb_tran.o smb_trantcp.o \
smb_usr.o smb_subrs.o subr_mchain.o smb_pass.o
-SMBFS_OBJS += smbfs_vfsops.o smbfs_vnops.o smbfs_node.o \
- smbfs_acl.o smbfs_client.o smbfs_io.o \
- smbfs_smb.o smbfs_subr.o smbfs_subr2.o \
+SMBFS_OBJS += smbfs_vfsops.o smbfs_vnops.o smbfs_node.o \
+ smbfs_acl.o smbfs_client.o smbfs_io.o \
+ smbfs_smb.o smbfs_subr.o smbfs_subr2.o \
smbfs_rwlock.o
+
#
# LVM modules
#
diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c
index e84f76011a..e010182dad 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c
@@ -34,10 +34,6 @@
#include <smbsrv/lmerr.h>
#include <smbsrv/nterror.h>
-#define MAX_SHARE_NAME_LEN 13
-#define SHARE_INFO_1_SIZE (MAX_SHARE_NAME_LEN + sizeof (char) + \
- sizeof (short) + sizeof (uint32_t))
-
/*
* count of bytes in server response packet
* except parameters and data. Note that setup
@@ -719,473 +715,39 @@ smb_trans_ready(struct smb_xa *xa)
return (rc);
}
-
-/*
- * smb_emit_SHARE_INFO_0
- *
- * This function will convert unicode chars to oem chars before
- * and store the result in a fixed length, MAX_SHARE_NAME_LEN, buffer. If the
- * length after conversion is longer than 12, -1 will be reported
- * to indicate an error. The fixed length is a limitation of the
- * smb protocol.
- */
-static int
-smb_emit_SHARE_INFO_0(struct mbuf_chain *output, unsigned char *name)
-{
- unsigned int cpid = oem_get_smb_cpid();
- unsigned int length;
- char name_buf[MAX_SHARE_NAME_LEN];
- mts_wchar_t *unibuf;
- char *tmpbuf;
- int rc = 0;
-
- tmpbuf = (name == NULL) ? "" : (char *)name;
- length = strlen(tmpbuf) + 1;
-
- unibuf = kmem_alloc(length * sizeof (mts_wchar_t), KM_SLEEP);
- (void) mts_mbstowcs(unibuf, tmpbuf, length);
-
- tmpbuf = kmem_alloc(length, KM_SLEEP);
- if (unicodestooems(tmpbuf, unibuf, length, cpid) == 0)
- (void) strcpy(tmpbuf, (char *)name);
-
- if (strlen(tmpbuf) + 1 <= MAX_SHARE_NAME_LEN) {
- bzero(name_buf, sizeof (name_buf));
- (void) strcpy(name_buf, tmpbuf);
- (void) smb_encode_mbc(output, "13c", name_buf);
- } else {
- rc = -1;
- }
-
- kmem_free(unibuf, length * sizeof (mts_wchar_t));
- kmem_free(tmpbuf, length);
-
- return (rc);
-}
-
-static int
-smb_emit_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text,
- unsigned char *name, uint16_t type,
- unsigned char *comment)
+static void
+smb_encode_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text,
+ char *oem_name, uint16_t type, char *comment)
{
- if (smb_emit_SHARE_INFO_0(output, name) < 0)
- return (-1);
+ (void) smb_encode_mbc(output, "13c.wl", oem_name,
+ type, MBC_LENGTH(text));
- (void) smb_encode_mbc(output, ".wl", type, MBC_LENGTH(text));
- (void) smb_encode_mbc(text, "s",
- (comment ? comment : (unsigned char *)"No comment"));
- return (0);
+ (void) smb_encode_mbc(text, "s", comment ? comment : "");
}
-static void /*ARGSUSED*/
-smb_emit_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text,
- struct smb_request *sr, unsigned char *name, uint16_t type,
- unsigned char *comment, uint16_t access, char *path, char *password)
+static void
+smb_encode_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text,
+ smb_request_t *sr, char *oem_name, uint16_t type,
+ char *comment, uint16_t access, char *path, char *password)
{
- unsigned char pword[9];
+ unsigned char pword[9];
- /*
- * XXX PGD. Is there a bug here? We zero pword, copy password
- * into pword then ignore it and use password for smb_encode_mbc?
- */
bzero(pword, sizeof (pword));
(void) strncpy((char *)pword, password, sizeof (pword));
- (void) smb_emit_SHARE_INFO_1(output, text, name, type, comment);
+ smb_encode_SHARE_INFO_1(output, text, oem_name, type, comment);
(void) smb_encode_mbc(output, "wwwl9c.",
access,
sr->sr_cfg->skc_maxconnections,
smb_server_get_session_count(),
MBC_LENGTH(text),
- password);
+ pword);
(void) smb_encode_mbc(text, "s", path);
}
-/*
- * is_long_sharename
- *
- * This function is extracted from smb_emit_SHARE_INFO_0 only for
- * finding shares that their names are longer than MAX_SHARE_NAME_LEN.
- *
- * The function returns 1 for long share names and 0 when the length
- * is Ok.
- */
-static boolean_t
-is_long_sharename(unsigned char *name)
-{
- unsigned int cpid = oem_get_smb_cpid();
- size_t length;
- mts_wchar_t *unibuf;
- char *tmpbuf;
- boolean_t islong;
-
- tmpbuf = (name == NULL) ? "" : (char *)name;
- length = strlen(tmpbuf) + 1;
-
- unibuf = kmem_alloc(length * sizeof (mts_wchar_t), KM_SLEEP);
- (void) mts_mbstowcs(unibuf, tmpbuf, length);
-
- tmpbuf = kmem_alloc(length, KM_SLEEP);
- if (unicodestooems(tmpbuf, unibuf, length, cpid) == 0)
- (void) strcpy(tmpbuf, (char *)name);
-
- islong = (strlen(tmpbuf) + 1 > MAX_SHARE_NAME_LEN);
-
- kmem_free(unibuf, length * sizeof (mts_wchar_t));
- kmem_free(tmpbuf, length);
-
- return (islong);
-}
-
-/*
- * This structure holds information about shares which will
- * fit in the specified client buffer size.
- *
- * sei_bufsize: Client specified buffer size
- * sei_count: Maximum number of shares that can be
- * sent in the buffer.
- *
- * The return data section consists of a number of SHARE_INFO_1 structures.
- * In case there are multiple SHARE_INFO_1 data structures to return this
- * function put all fixed length part of these structures in the return buffer
- * and then put all the variable length data (shares' comment) at the end of
- * buffer.
- *
- * sei_info_len: Size of fixed length part of SHARE_INFO_1
- * structures for sei_count shares
- * sei_cmnt_len: Size of comments for sei_count shares
- */
-typedef struct {
- uint16_t sei_bufsize;
- short sei_count;
- int sei_infolen;
- int sei_cmntlen;
-} smb_share_enum_t;
-
-/*
- * smb_share_update_info
- *
- * Check to see if the given buffer has enough
- * room to fit the information of the given share.
- * If there is enough room update the passed max_???
- * information.
- *
- * Return 1 if buffer is not full yet, 0 if it's full.
- */
-static int
-smb_share_update_info(door_handle_t dhdl, lmshare_info_t *si,
- smb_share_enum_t *shr_enum_info)
-{
- int cmnt_len;
- int new_info_len = shr_enum_info->sei_infolen;
- int new_cmnt_len = shr_enum_info->sei_cmntlen;
-
- if (lmshrd_is_special(dhdl, si->share_name))
- cmnt_len = 1;
- else
- cmnt_len = (strlen(si->comment) + 1);
-
- new_info_len += SHARE_INFO_1_SIZE;
- new_cmnt_len += cmnt_len;
-
- if ((new_info_len + new_cmnt_len) < shr_enum_info->sei_bufsize) {
- shr_enum_info->sei_count++;
- shr_enum_info->sei_infolen = new_info_len;
- shr_enum_info->sei_cmntlen = new_cmnt_len;
- return (1);
- }
-
- return (0);
-}
-
-/*
- * smb_share_skip_share
- *
- * Determines whether the given share should be enumerated
- * or not. The share will not be enumerated if its name is
- * long or it's autohome share.
- *
- * Return 1 if the share should be skipped; otherwise returns
- * 0
- */
-static int
-smb_share_skip_share(lmshare_info_t *si)
-{
- if (is_long_sharename((unsigned char *)si->share_name)) {
- return (1);
- }
-
- /* Skip autohome share if autohome filter is enabled */
- if (si->mode == LMSHRM_TRANS) {
- return (1);
- }
-
- return (0);
-}
-
-/*
- * smb_share_add_autohome
- *
- * Determines if an autohome share should be added to shares' list
- * for the given user.
- * Autohome will be add when all the following conditions are true:
- *
- * 1. Autohome feature is enabled
- * 2. A share with the same name as the given user exists
- * 3. The share is not a permanent share
- * 4. Share name is not longer than maximum allowed
- */
-static int
-smb_share_add_autohome(door_handle_t dhdl, char *username, lmshare_info_t *si)
-{
- int do_add = 0;
-
- do_add = (lmshrd_getinfo(dhdl, username, si) == NERR_Success) &&
- (si->mode & LMSHRM_TRANS) &&
- (!is_long_sharename((unsigned char *)(si->share_name)));
-
- return (do_add);
-}
-
-/*
- * smb_share_total_info
- *
- * This function calculates following informations
- * - Maximum number of shares that can be sent for clients
- * according to its buffer size (cli_bufsize)
- * - length of fixed information about above shares
- * - length of comments of above shares
- * - total number of shares that their names are no longer
- * than MAX_SHARE_NAME_LEN.
- *
- * Added SMB user object to the parameter list to filter out other
- * user autohome shares.
- */
-static void
-smb_share_total_info(door_handle_t dhdl, smb_share_enum_t *shr_enum_info,
- short *tot_shares_num, smb_user_t *user)
-{
- uint64_t iterator;
- lmshare_info_t *si;
- struct lmshare_info *auto_si;
- int more_room = 1;
-
- si = kmem_zalloc(sizeof (lmshare_info_t), KM_SLEEP);
- auto_si = kmem_zalloc(sizeof (struct lmshare_info), KM_SLEEP);
-
- *tot_shares_num = 0;
- shr_enum_info->sei_count = 0;
- shr_enum_info->sei_infolen = 0;
- shr_enum_info->sei_cmntlen = 0;
-
- if (smb_share_add_autohome(dhdl, user->u_name, auto_si)) {
- (*tot_shares_num)++;
- more_room = smb_share_update_info(dhdl, auto_si, shr_enum_info);
- }
-
- iterator = lmshrd_open_iterator(dhdl, LMSHRM_ALL);
- if (iterator == 0) {
- kmem_free(si, sizeof (lmshare_info_t));
- kmem_free(auto_si, sizeof (struct lmshare_info));
- return;
- }
-
- /* check for door errors */
- if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) {
- (void) lmshrd_close_iterator(dhdl, iterator);
- kmem_free(si, sizeof (lmshare_info_t));
- kmem_free(auto_si, sizeof (struct lmshare_info));
- return;
- }
-
- while (*si->share_name != 0) {
- if (smb_share_skip_share(si)) {
- /* check for door errors */
- if (lmshrd_iterate(dhdl, iterator, si) !=
- NERR_Success) {
- (void) lmshrd_close_iterator(dhdl, iterator);
- kmem_free(si, sizeof (lmshare_info_t));
- kmem_free(auto_si,
- sizeof (struct lmshare_info));
- return;
- }
- continue;
- }
-
- (*tot_shares_num)++;
-
- if (more_room) {
- more_room = smb_share_update_info(dhdl, si,
- shr_enum_info);
- }
-
- /* check for door errors */
- if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) {
- (void) lmshrd_close_iterator(dhdl, iterator);
- kmem_free(si, sizeof (lmshare_info_t));
- kmem_free(auto_si, sizeof (struct lmshare_info));
- return;
- }
- }
-
- (void) lmshrd_close_iterator(dhdl, iterator);
- kmem_free(si, sizeof (lmshare_info_t));
- kmem_free(auto_si, sizeof (struct lmshare_info));
-}
-
-/*
- * smb_encode_SHARE_INFO_1
- *
- * This function is extracted from smb_emit_SHARE_INFO_1 and only
- * encodes fixed part of SHARE_INFO_1 structure.
- *
- * The function returns -1 if encoding fails and 0 on success.
- */
-static int
-smb_encode_SHARE_INFO_1(struct mbuf_chain *output, unsigned char *name,
- uint16_t type, int cmnt_len)
-{
- if (smb_emit_SHARE_INFO_0(output, name) < 0)
- return (-1);
- (void) smb_encode_mbc(output, ".wl", type, cmnt_len);
- return (0);
-}
-
-/*
- * collect_shares_info
- *
- * This function encodes information of shares_num of shares
- * into data_mb and cmnt_str.
- *
- * Added SMB user object to the parameter list to filter out other
- * user autohome shares.
- *
- */
-static void
-collect_shares_info(door_handle_t dhdl, uint64_t iterator, int shares_num,
- struct mbuf_chain *data_mb, char *cmnt_str, int *cmnt_len, smb_user_t *user,
- int first_resp)
-{
- int i = 0;
- lmshare_info_t *si;
- struct lmshare_info *tsi;
- int is_special;
-
- si = kmem_zalloc(sizeof (lmshare_info_t), KM_SLEEP);
- tsi = kmem_zalloc(sizeof (struct lmshare_info), KM_SLEEP);
-
- if (first_resp && smb_share_add_autohome(dhdl, user->u_name, tsi)) {
- if (smb_encode_SHARE_INFO_1(data_mb,
- (unsigned char *)tsi->share_name,
- tsi->stype, *cmnt_len) == 0) {
- (void) memcpy(cmnt_str+(*cmnt_len),
- tsi->comment, strlen(tsi->comment)+1);
- (*cmnt_len) += (strlen(tsi->comment) + 1);
- i++;
- }
- }
-
- /* check for door errors */
- if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) {
- kmem_free(si, sizeof (lmshare_info_t));
- kmem_free(tsi, sizeof (struct lmshare_info));
- return;
- }
-
- while ((i < shares_num) && (*si->share_name != 0)) {
- if (smb_share_skip_share(si)) {
- goto next;
- }
-
-
- is_special = lmshrd_is_special(dhdl, si->share_name);
- /* check for door errors */
- if (is_special == NERR_InternalError) {
- kmem_free(si, sizeof (lmshare_info_t));
- kmem_free(tsi, sizeof (struct lmshare_info));
- return;
- }
-
- if (is_special) {
- si->stype |= STYPE_HIDDEN;
- if (smb_encode_SHARE_INFO_1(data_mb,
- (unsigned char *)si->share_name,
- si->stype, *cmnt_len) < 0) {
- goto next;
- }
- cmnt_str[*cmnt_len] = '\0';
- (*cmnt_len)++;
- } else {
- if (smb_encode_SHARE_INFO_1(data_mb,
- (unsigned char *)si->share_name, si->stype,
- *cmnt_len) < 0) {
- goto next;
- }
- (void) memcpy(cmnt_str+(*cmnt_len), si->comment,
- strlen(si->comment)+1);
- (*cmnt_len) += (strlen(si->comment) + 1);
- }
-
- next:
- /* check for door errors */
- if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) {
- kmem_free(si, sizeof (lmshare_info_t));
- kmem_free(tsi, sizeof (struct lmshare_info));
- return;
- }
- }
- kmem_free(si, sizeof (lmshare_info_t));
- kmem_free(tsi, sizeof (struct lmshare_info));
-}
-
int
smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
{
door_handle_t dhdl = sr->sr_server->sv_lmshrd;
- smb_share_enum_t shr_enum_info;
- short left_shares_cnt; /* Number of shares not sent yet */
-
- /*
- * Number of shares that should be sent
- * in the current response packet.
- * It can be a number between 0 and
- * max_share_scnt.
- */
- short shares_scnt;
-
- /*
- * Maximum number of shares that can be
- * sent in one response packet regarding
- * the maximum negotiated buffer size
- * for SMB messages.
- */
- short max_shares_per_packet;
-
- /*
- * Total number of shares on the server
- * that their name is not greater than
- * MAX_SHARE_NAME_LEN
- */
- short shares_tot_num;
-
- /*
- * Size of total data (info + cmnt)
- * that should be sent for client
- */
- int shares_tot_byte;
-
- /*
- * Maximum size of data that can be
- * sent in one SMB transaction response
- * according to the maximum negotiated
- * buffer size for SMB packets
- */
- int data_buf_limit;
-
- /*
- * Number of comment bytes that will
- * be sent in the current response
- */
- uint16_t cmnt_scnt;
/*
* Number of data bytes that will
@@ -1215,9 +777,6 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
/* data and parameter displacement */
uint16_t data_disp, param_disp;
- /* return status by the 1st reply */
- uint16_t ret_stat;
-
/* parameter and data offset and pad */
int param_off, param_pad, data_off, data_pad;
@@ -1227,19 +786,17 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
*/
int tot_packet_bytes;
- char first_resp;
- uint16_t opcode, level, cli_bufsize;
- unsigned char *r_fmt;
- char fmt[10];
- uint64_t iterator;
- char *cmnt_str, *cmnt_start;
- int cmnt_len;
+ boolean_t first_resp;
+
+ char fmt[16];
struct mbuf_chain reply;
- smb_user_t *user;
- size_t cmnt_size;
- user = sr->uid_user;
- ASSERT(user);
+ uint16_t level;
+ uint16_t pkt_bufsize;
+ smb_enumshare_info_t esi;
+ char *sent_buf;
+
+ ASSERT(sr->uid_user);
/*
* Initialize the mbuf chain of reply to zero. If it is not
@@ -1247,98 +804,62 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
*/
bzero(&reply, sizeof (struct mbuf_chain));
- if (smb_decode_mbc(&xa->req_param_mb, "%wss(lev)w(size)w", sr,
- &opcode, &r_fmt, &r_fmt, &level, &cli_bufsize) != 0)
+ if (smb_decode_mbc(&xa->req_param_mb, "ww", &level,
+ &esi.es_bufsize) != 0)
return (SDRC_NOT_IMPLEMENTED);
if (level != 1) {
+ /*
+ * Only level 1 is valid for NetShareEnum
+ * None of the error codes in the spec are meaningful
+ * here. This error code is returned by Windows.
+ */
(void) smb_encode_mbc(&xa->rep_param_mb, "wwww",
- NERR_BadTransactConfig, 0, 0, 0);
+ ERROR_INVALID_LEVEL, 0, 0, 0);
return (SDRC_SUCCESS);
}
- n_setup = 0; /* Setup count for NetShareEnum SMB is 0 */
- n_param = 8;
- data_buf_limit = sr->session->smb_msg_size -
- (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param);
+ esi.es_buf = kmem_zalloc(esi.es_bufsize, KM_SLEEP);
+ esi.es_username = sr->uid_user->u_name;
+ (void) smb_kshare_enum(dhdl, &esi);
- shr_enum_info.sei_bufsize = cli_bufsize;
- smb_share_total_info(dhdl, &shr_enum_info, &shares_tot_num, user);
-
- shares_tot_byte = shr_enum_info.sei_infolen + shr_enum_info.sei_cmntlen;
-
- /* Check buffer to have enough space */
- if (shares_tot_byte == 0) {
+ /* client buffer size is not big enough to hold any shares */
+ if (esi.es_nsent == 0) {
(void) smb_encode_mbc(&xa->rep_param_mb, "wwww",
- ERROR_NOT_ENOUGH_MEMORY, 0, 0, 0);
+ ERROR_MORE_DATA, 0, esi.es_nsent, esi.es_ntotal);
+ kmem_free(esi.es_buf, esi.es_bufsize);
return (SDRC_SUCCESS);
}
- max_shares_per_packet = data_buf_limit / SHARE_INFO_1_SIZE;
-
- shares_scnt = (shr_enum_info.sei_count > max_shares_per_packet)
- ? max_shares_per_packet : shr_enum_info.sei_count;
-
- cmnt_size = shr_enum_info.sei_cmntlen * sizeof (char);
- cmnt_str = kmem_alloc(cmnt_size, KM_SLEEP);
- cmnt_len = 0;
- /* save start of buffer to free it at the end of function */
- cmnt_start = cmnt_str;
-
- iterator = lmshrd_open_iterator(dhdl, LMSHRM_ALL);
-
- if (iterator == NULL) {
- kmem_free(cmnt_start, cmnt_size);
- return (SDRC_DROP_VC);
- }
-
/*
* The rep_setup_mb is already initialized in smb_trans_dispatch().
* Calling MBC_INIT() will initialized the structure and so the
* pointer to the mbuf chains will be lost. Therefore, we need
* to free the resources before calling MBC_INIT() again.
*/
+ n_setup = 0; /* Setup count for NetShareEnum SMB is 0 */
m_freem(xa->rep_setup_mb.chain);
MBC_INIT(&xa->rep_setup_mb, n_setup * 2);
- left_shares_cnt = shr_enum_info.sei_count;
+ n_param = 8;
+ pkt_bufsize = sr->session->smb_msg_size -
+ (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param);
+
tot_data_scnt = 0;
- cmnt_scnt = 0;
+ sent_buf = esi.es_buf;
+ first_resp = B_TRUE;
- first_resp = 1;
- while (tot_data_scnt < shares_tot_byte) {
- /*
- * Calling MBC_INIT() will initialized the structure and so the
- * pointer to the mbuf chains will be lost. Therefore, we need
- * to free the resources if any before calling MBC_INIT().
- */
+ while (tot_data_scnt < esi.es_datasize) {
+ data_scnt = esi.es_datasize - tot_data_scnt;
+ if (data_scnt > pkt_bufsize)
+ data_scnt = pkt_bufsize;
m_freem(xa->rep_data_mb.chain);
- MBC_INIT(&xa->rep_data_mb, data_buf_limit);
- collect_shares_info(dhdl, iterator,
- shares_scnt, &xa->rep_data_mb, cmnt_str, &cmnt_len, user,
- first_resp);
- data_scnt = shares_scnt * SHARE_INFO_1_SIZE;
- left_shares_cnt -= shares_scnt;
- if (left_shares_cnt < max_shares_per_packet)
- shares_scnt = left_shares_cnt;
- if (left_shares_cnt == 0) {
- /*
- * Now send comments.
- * Append comments to the end of share_info_1
- * structures.
- */
- cmnt_scnt = data_buf_limit -
- MBC_LENGTH(&xa->rep_data_mb);
- if (cmnt_scnt > shr_enum_info.sei_cmntlen) {
- /*LINTED E_ASSIGN_NARROW_CONV*/
- cmnt_scnt = shr_enum_info.sei_cmntlen;
- }
- (void) sprintf(fmt, "%dc", cmnt_scnt);
- (void) smb_encode_mbc(&xa->rep_data_mb, fmt, cmnt_str);
- cmnt_str += cmnt_scnt;
- shr_enum_info.sei_cmntlen -= cmnt_scnt;
- }
- data_scnt += cmnt_scnt;
+ MBC_INIT(&xa->rep_data_mb, data_scnt);
+
+ (void) sprintf(fmt, "%dc", data_scnt);
+ (void) smb_encode_mbc(&xa->rep_data_mb, fmt, sent_buf);
+
+ sent_buf += data_scnt;
tot_data_scnt += data_scnt;
/* Only the 1st response packet contains parameters */
@@ -1347,22 +868,15 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN;
param_disp = (first_resp) ? 0 : n_param;
- /*
- * Calling MBC_INIT() will initialized the structure and so the
- * pointer to the mbuf chains will be lost. Therefore, we need
- * to free the resources if any before calling MBC_INIT().
- */
m_freem(xa->rep_param_mb.chain);
MBC_INIT(&xa->rep_param_mb, param_scnt);
+
if (first_resp) {
- first_resp = 0;
- /* Prepare parameters for the 1st response packet */
- ret_stat = (shares_tot_num > shr_enum_info.sei_count)
- ? ERROR_MORE_DATA : 0;
+ first_resp = B_FALSE;
(void) smb_encode_mbc(&xa->rep_param_mb, "wwww",
- ret_stat, -shr_enum_info.sei_infolen,
- shr_enum_info.sei_count,
- shares_tot_num);
+ (esi.es_ntotal > esi.es_nsent)
+ ? ERROR_MORE_DATA : 0,
+ 0, esi.es_nsent, esi.es_ntotal);
}
data_pad = (param_off + n_param) & 1; /* Pad to short */
@@ -1380,10 +894,10 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
*/
m_freem(reply.chain);
MBC_INIT(&reply, SMB_HEADER_ED_LEN
- + sizeof (uchar_t) /* word parameters count */
- + 10*sizeof (ushort_t) /* word parameters */
- + n_setup*sizeof (ushort_t) /* setup parameters */
- + sizeof (ushort_t) /* total data byte count */
+ + sizeof (uint8_t) /* word parameters count */
+ + 10*sizeof (uint16_t) /* word parameters */
+ + n_setup*sizeof (uint16_t) /* setup parameters */
+ + sizeof (uint16_t) /* total data byte count */
+ tot_packet_bytes);
(void) smb_encode_mbc(&reply, SMB_HEADER_ED_FMT,
@@ -1404,7 +918,7 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
"b ww 2. www www b . C w #. C #. C",
10 + n_setup, /* wct */
n_param, /* Total Parameter Bytes */
- shares_tot_byte, /* Total Data Bytes */
+ esi.es_datasize, /* Total Data Bytes */
param_scnt, /* Total Parameter Bytes this buffer */
param_off, /* Param offset from header start */
param_disp, /* Param displacement */
@@ -1425,82 +939,61 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
(void) smb_session_send(sr->session, 0, &reply);
}
- (void) lmshrd_close_iterator(dhdl, iterator);
- kmem_free(cmnt_start, cmnt_size);
+ kmem_free(esi.es_buf, esi.es_bufsize);
return (SDRC_NO_REPLY);
}
int
-smb_trans_net_share_get_info(smb_request_t *sr, struct smb_xa *xa)
+smb_trans_net_share_getinfo(smb_request_t *sr, struct smb_xa *xa)
{
- uint16_t opcode, level, max_bytes, access;
- uint32_t type;
- unsigned char *req_fmt;
- unsigned char *rep_fmt;
+ uint16_t level, max_bytes, access;
struct mbuf_chain str_mb;
char *share;
- char *path;
char *password;
- char *comment;
lmshare_info_t si;
- int shr_found;
+ int rc;
- if (smb_decode_mbc(&xa->req_param_mb, "%wsss(lev)w(size)w", sr,
- &opcode, &req_fmt, &rep_fmt, &share, &level, &max_bytes) != 0)
+ if (smb_decode_mbc(&xa->req_param_mb, "%sww", sr,
+ &share, &level, &max_bytes) != 0)
return (SDRC_NOT_IMPLEMENTED);
(void) utf8_strlwr(share);
- shr_found = lmshrd_getinfo(sr->sr_server->sv_lmshrd, share, &si);
- if (strcmp(share, "ipc$") == 0) {
- type = STYPE_IPC;
- path = "";
- password = "";
- access = SHARE_ACCESS_ALL;
- } else if (shr_found) {
- path = si.directory;
- type = STYPE_DISKTREE;
- if (path[strlen(path)] == '$')
- type |= STYPE_HIDDEN;
- password = "";
- access = SHARE_ACCESS_ALL;
- } else {
- /* We have no idea what this share is... */
+ rc = smb_kshare_getinfo(sr->sr_server->sv_lmshrd, share, &si);
+ if ((rc != NERR_Success) || (si.mode & LMSHRM_LONGNAME)) {
(void) smb_encode_mbc(&xa->rep_param_mb, "www",
NERR_NetNameNotFound, 0, 0);
return (SDRC_SUCCESS);
}
- if (shr_found)
- comment = si.comment;
- else
- comment = "";
-
+ access = SHARE_ACCESS_ALL;
password = "";
MBC_INIT(&str_mb, max_bytes);
switch (level) {
case 0 :
- (void) smb_emit_SHARE_INFO_0(&xa->rep_data_mb,
- (unsigned char *)share);
+ (void) smb_encode_mbc(&xa->rep_data_mb, "13c", si.oem_name);
break;
case 1 :
- (void) smb_emit_SHARE_INFO_1(&xa->rep_data_mb, &str_mb,
- (unsigned char *)share, type,
- (unsigned char *)comment);
+ smb_encode_SHARE_INFO_1(&xa->rep_data_mb, &str_mb,
+ si.oem_name, si.stype, si.comment);
break;
case 2 :
- smb_emit_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr,
- (unsigned char *)share, type, (unsigned char *)comment,
- access, path, password);
+ smb_encode_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr,
+ si.oem_name, si.stype, si.comment, access, si.directory,
+ password);
+ break;
+
default:
+ (void) smb_encode_mbc(&xa->rep_param_mb, "www",
+ ERROR_INVALID_LEVEL, 0, 0);
m_freem(str_mb.chain);
return (SDRC_NOT_IMPLEMENTED);
}
- (void) smb_encode_mbc(&xa->rep_param_mb, "www", 0,
+ (void) smb_encode_mbc(&xa->rep_param_mb, "www", NERR_Success,
-MBC_LENGTH(&xa->rep_data_mb),
MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
(void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb);
@@ -1509,17 +1002,15 @@ smb_trans_net_share_get_info(smb_request_t *sr, struct smb_xa *xa)
}
int
-smb_trans_net_workstation_get_info(struct smb_request *sr, struct smb_xa *xa)
+smb_trans_net_workstation_getinfo(struct smb_request *sr, struct smb_xa *xa)
{
- uint16_t opcode, level, max_bytes;
- unsigned char *req_fmt;
- unsigned char *rep_fmt;
+ uint16_t level, max_bytes;
struct mbuf_chain str_mb;
char *domain;
char *hostname;
- if ((smb_decode_mbc(&xa->req_param_mb, "%wss(lev)w(size)w", sr,
- &opcode, &req_fmt, &rep_fmt, &level, &max_bytes) != 0) ||
+ if ((smb_decode_mbc(&xa->req_param_mb, "ww",
+ &level, &max_bytes) != 0) ||
(level != 10)) {
(void) smb_encode_mbc(&xa->rep_param_mb, "wwww",
NERR_BadTransactConfig, 0, 0, 0);
@@ -1554,18 +1045,13 @@ smb_trans_net_workstation_get_info(struct smb_request *sr, struct smb_xa *xa)
}
int
-smb_trans_net_user_get_info(struct smb_request *sr, struct smb_xa *xa)
+smb_trans_net_user_getinfo(struct smb_request *sr, struct smb_xa *xa)
{
- uint16_t opcode, level, max_bytes;
- unsigned char *req_fmt;
- unsigned char *rep_fmt;
+ uint16_t level, max_bytes;
unsigned char *user;
int rc;
- rc = smb_decode_mbc(&xa->req_param_mb, "%wssww", sr,
- &opcode,
- &req_fmt,
- &rep_fmt,
+ rc = smb_decode_mbc(&xa->req_param_mb, "%sww", sr,
&user,
&level,
&max_bytes);
@@ -1579,104 +1065,48 @@ smb_trans_net_user_get_info(struct smb_request *sr, struct smb_xa *xa)
}
smb_sdrc_t
-smb_trans_server_get_info(struct smb_request *sr, struct smb_xa *xa)
+smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa)
{
- uint16_t opcode, level, buf_size;
- char *req_fmt;
- char *rep_fmt;
+ uint16_t level, buf_size;
+ uint16_t avail_data, max_data;
char server_name[16];
struct mbuf_chain str_mb;
- char *hostname;
- char *comment;
- if (smb_decode_mbc(&xa->req_param_mb, "%wssww", sr,
- &opcode, &req_fmt, &rep_fmt, &level, &buf_size) != 0) {
+ if (smb_decode_mbc(&xa->req_param_mb, "ww", &level, &buf_size) != 0)
return (SDRC_ERROR);
- }
- comment = sr->sr_cfg->skc_system_comment;
- hostname = sr->sr_cfg->skc_hostname;
+ max_data = MBC_MAXBYTES(&xa->rep_data_mb);
MBC_INIT(&str_mb, buf_size);
bzero(server_name, sizeof (server_name));
- (void) strncpy(server_name, hostname, sizeof (server_name));
+ (void) strncpy(server_name, sr->sr_cfg->skc_hostname,
+ sizeof (server_name));
+ /* valid levels are 0 and 1 */
switch (level) {
case 0:
(void) smb_encode_mbc(&xa->rep_data_mb, "16c", server_name);
break;
+
case 1:
- (void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */
+ (void) smb_encode_mbc(&str_mb, "s",
+ sr->sr_cfg->skc_system_comment);
(void) smb_encode_mbc(&xa->rep_data_mb, "16cbbll", server_name,
SMB_VERSION_MAJOR, SMB_VERSION_MINOR,
- MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
- (void) smb_encode_mbc(&str_mb, "s", comment);
- break;
- case 2:
- /* B16BBDzDDDWWzWWWWWWWB21BzWWWWWWWWWWWWWWWWWWWWWWz */
- (void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */
- /* B16BBDz */
- (void) smb_encode_mbc(&xa->rep_data_mb, "16cbbll", server_name,
- SMB_VERSION_MAJOR,
- SMB_VERSION_MINOR, MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
- (void) smb_encode_mbc(&str_mb, "s", comment);
- (void) smb_encode_mbc(&xa->rep_data_mb, "lllwwl",
- (uint32_t)1,
- (uint32_t)2,
- (uint32_t)3,
- (uint16_t)4,
- (uint16_t)5,
- MBC_LENGTH(&str_mb));
- (void) smb_encode_mbc(&str_mb, "s", "str1");
- (void) smb_encode_mbc(&xa->rep_data_mb, "wwwwwww21cbl",
- (uint16_t)6,
- (uint16_t)7,
- (uint16_t)8,
- (uint16_t)9,
- (uint16_t)10,
- (uint16_t)11,
- (uint16_t)12,
- "21 byte comment ",
- (unsigned char)13,
- MBC_LENGTH(&str_mb));
- (void) smb_encode_mbc(&str_mb, "s", "str2");
- (void) smb_encode_mbc(&xa->rep_data_mb,
- "wwwwwwwwwwwwwwwwwwwwwwl",
- (uint16_t)14,
- (uint16_t)15,
- (uint16_t)16,
- (uint16_t)17,
- (uint16_t)18,
- (uint16_t)19,
- (uint16_t)20,
- (uint16_t)21,
- (uint16_t)22,
- (uint16_t)23,
- (uint16_t)24,
- (uint16_t)25,
- (uint16_t)26,
- (uint16_t)27,
- (uint16_t)28,
- (uint16_t)29,
- (uint16_t)20,
- (uint16_t)31,
- (uint16_t)32,
- (uint16_t)33,
- (uint16_t)34,
- (uint16_t)35,
- MBC_LENGTH(&str_mb));
- (void) smb_encode_mbc(&str_mb, "s", "str3");
+ MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb));
break;
+
default:
+ (void) smb_encode_mbc(&xa->rep_param_mb, "www",
+ ERROR_INVALID_LEVEL, 0, 0);
m_freem(str_mb.chain);
- return (SDRC_NOT_IMPLEMENTED);
+ return (SDRC_SUCCESS);
}
- (void) smb_encode_mbc(&xa->rep_param_mb, "www", 0,
- -MBC_LENGTH(&xa->rep_data_mb),
- (MBC_LENGTH(&xa->rep_data_mb)) +
- (MBC_LENGTH(&str_mb)));
+ avail_data = MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb);
+ (void) smb_encode_mbc(&xa->rep_param_mb, "www",
+ NERR_Success, max_data - avail_data, avail_data);
(void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb);
m_freem(str_mb.chain);
return (SDRC_SUCCESS);
@@ -2011,30 +1441,29 @@ smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa)
xa->xa_smb_trans_name, MAILSLOT_MSBROWSE) != 0))
goto trans_err_not_supported;
- if ((rc = smb_decode_mbc(&xa->req_param_mb, "%wss\b", sr,
+ if ((rc = smb_decode_mbc(&xa->req_param_mb, "%wss", sr,
&opcode, &req_fmt, &rep_fmt)) != 0)
goto trans_err_not_supported;
- /* for now, only respond to the */
switch (opcode) {
case API_WshareEnum:
rc = smb_trans_net_share_enum(sr, xa);
break;
case API_WshareGetInfo:
- rc = smb_trans_net_share_get_info(sr, xa);
+ rc = smb_trans_net_share_getinfo(sr, xa);
break;
case API_WserverGetInfo:
- rc = smb_trans_server_get_info(sr, xa);
+ rc = smb_trans_net_server_getinfo(sr, xa);
break;
case API_WUserGetInfo:
- rc = smb_trans_net_user_get_info(sr, xa);
+ rc = smb_trans_net_user_getinfo(sr, xa);
break;
case API_WWkstaGetInfo:
- rc = smb_trans_net_workstation_get_info(sr, xa);
+ rc = smb_trans_net_workstation_getinfo(sr, xa);
break;
case API_NetServerEnum2:
diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_tree.c b/usr/src/uts/common/fs/smbsrv/smb_common_tree.c
index 97fb7c7bcd..715b3b1213 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_tree.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_tree.c
@@ -186,7 +186,6 @@ smbsr_setup_share(struct smb_request *sr, char *sharename, int32_t stype,
smb_sid_t *sid;
fsvol_attr_t vol_attr;
smb_attr_t attr;
- int is_admin;
smb_user_t *user = sr->uid_user;
cred_t *u_cred;
@@ -233,18 +232,18 @@ smbsr_setup_share(struct smb_request *sr, char *sharename, int32_t stype,
return (ERRaccess);
}
+ if (smb_kshare_getinfo(sr->sr_server->sv_lmshrd, sharename, &si) !=
+ NERR_Success) {
+ (void) strlcpy(errmsg, "share not found", SMB_TREE_EMSZ);
+ return (ERRinvnetname);
+ }
+
/*
* Handle the default administration shares: C$, D$ etc.
* Only a user with admin rights is allowed to map these
* shares.
*/
- is_admin = lmshrd_is_admin(sr->sr_server->sv_lmshrd, sharename);
- if (is_admin == NERR_InternalError) {
- (void) strlcpy(errmsg, "internal error", SMB_TREE_EMSZ);
- return (ERRaccess);
- }
-
- if (is_admin) {
+ if (si.mode & LMSHRM_ADMIN) {
sid = smb_sid_fromstr(ADMINISTRATORS_SID);
if (sid) {
rc = smb_cred_is_member(u_cred, sid);
@@ -257,11 +256,6 @@ smbsr_setup_share(struct smb_request *sr, char *sharename, int32_t stype,
}
}
- if (lmshrd_getinfo(sr->sr_server->sv_lmshrd, sharename, &si) !=
- NERR_Success) {
- (void) strlcpy(errmsg, "share not found", SMB_TREE_EMSZ);
- return (ERRinvnetname);
- }
resource = si.directory;
sr->arg.tcon.service = "A:";
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
index cb92140574..d5a4a3e550 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
@@ -2594,6 +2594,27 @@ smb_fsop_frlock(smb_node_t *node, smb_lock_t *lock, boolean_t unlock,
flock64_t bf;
int flag = F_REMOTELOCK;
+ /*
+ * VOP_FRLOCK() will not be called if:
+ *
+ * 1) The lock has a range of zero bytes. The semantics of Windows and
+ * POSIX are different. In the case of POSIX it asks for the locking
+ * of all the bytes from the offset provided until the end of the
+ * file. In the case of Windows a range of zero locks nothing and
+ * doesn't conflict with any other lock.
+ *
+ * 2) The lock rolls over (start + lenght < start). Solaris will assert
+ * if such a request is submitted. This will not create
+ * incompatibilities between POSIX and Windows. In the Windows world,
+ * if a client submits such a lock, the server will not lock any
+ * bytes. Interestingly if the same lock (same offset and length) is
+ * resubmitted Windows will consider that there is an overlap and
+ * the granting rules will then apply.
+ */
+ if ((lock->l_length == 0) ||
+ ((lock->l_start + lock->l_length - 1) < lock->l_start))
+ return (0);
+
bzero(&bf, sizeof (bf));
if (unlock) {
diff --git a/usr/src/uts/common/fs/smbsrv/smb_kshare.c b/usr/src/uts/common/fs/smbsrv/smb_kshare.c
new file mode 100644
index 0000000000..c67886af17
--- /dev/null
+++ b/usr/src/uts/common/fs/smbsrv/smb_kshare.c
@@ -0,0 +1,311 @@
+/*
+ * 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 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Kernel door client for LanMan share management.
+ */
+
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/cmn_err.h>
+#include <sys/door.h>
+#include <smbsrv/lmshare.h>
+#include <smbsrv/lmerr.h>
+#include <smbsrv/smb_common_door.h>
+#include <smbsrv/lmshare_door.h>
+#include <smbsrv/smbinfo.h>
+
+static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *);
+
+/*
+ * smb_kshare_init
+ *
+ * This function is not MultiThread safe. The caller has to make sure only one
+ * thread calls this function.
+ */
+door_handle_t
+smb_kshare_init(int door_id)
+{
+ return (door_ki_lookup(door_id));
+}
+
+/*
+ * smb_kshare_fini
+ *
+ * This function is not MultiThread safe. The caller has to make sure only one
+ * thread calls this function.
+ */
+void
+smb_kshare_fini(door_handle_t dhdl)
+{
+ ASSERT(dhdl != NULL);
+ if (dhdl)
+ door_ki_rele(dhdl);
+}
+
+uint32_t
+smb_kshare_getinfo(door_handle_t dhdl, char *share_name, lmshare_info_t *si)
+{
+ door_arg_t arg;
+ char *buf;
+ unsigned int used;
+ smb_dr_ctx_t *dec_ctx;
+ smb_dr_ctx_t *enc_ctx;
+ int status;
+ uint32_t rc;
+ int opcode = LMSHR_DOOR_GETINFO;
+
+ buf = kmem_alloc(LMSHR_DOOR_SIZE, KM_SLEEP);
+
+ enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
+ smb_dr_put_uint32(enc_ctx, opcode);
+ smb_dr_put_string(enc_ctx, share_name);
+
+ if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
+ cmn_err(CE_WARN, "smb_kshare_getinfo: Encode error %d",
+ status);
+ kmem_free(buf, LMSHR_DOOR_SIZE);
+ return (NERR_InternalError);
+ }
+
+ arg.data_ptr = buf;
+ arg.data_size = used;
+ arg.desc_ptr = NULL;
+ arg.desc_num = 0;
+ arg.rbuf = buf;
+ arg.rsize = LMSHR_DOOR_SIZE;
+
+ if (door_ki_upcall(dhdl, &arg) != 0) {
+ cmn_err(CE_WARN, "smb_kshare_getinfo: Door call failed");
+ kmem_free(buf, LMSHR_DOOR_SIZE);
+ return (NERR_InternalError);
+ }
+
+ dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
+ if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) {
+ kmem_free(buf, LMSHR_DOOR_SIZE);
+ return (NERR_InternalError);
+ }
+
+ rc = smb_dr_get_uint32(dec_ctx);
+ smb_dr_get_lmshare(dec_ctx, si);
+ if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
+ cmn_err(CE_WARN, "smb_kshare_getinfo: Decode error %d",
+ status);
+ rc = NERR_InternalError;
+ }
+
+ kmem_free(buf, LMSHR_DOOR_SIZE);
+ return (rc);
+}
+
+uint32_t
+smb_kshare_enum(door_handle_t dhdl, smb_enumshare_info_t *enuminfo)
+{
+ door_arg_t arg;
+ char *door_buf;
+ int door_bufsz;
+ unsigned int used;
+ smb_dr_ctx_t *dec_ctx;
+ smb_dr_ctx_t *enc_ctx;
+ int status;
+ uint32_t rc;
+ int opcode = LMSHR_DOOR_ENUM;
+
+ enuminfo->es_ntotal = enuminfo->es_nsent = 0;
+
+ door_bufsz = enuminfo->es_bufsize + strlen(enuminfo->es_username)
+ + sizeof (smb_enumshare_info_t);
+ door_buf = kmem_alloc(door_bufsz, KM_SLEEP);
+
+ enc_ctx = smb_dr_encode_start(door_buf, door_bufsz);
+ smb_dr_put_uint32(enc_ctx, opcode);
+ smb_dr_put_ushort(enc_ctx, enuminfo->es_bufsize);
+ smb_dr_put_string(enc_ctx, enuminfo->es_username);
+
+ if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
+ cmn_err(CE_WARN, "smb_kshare_enum: Encode error %d", status);
+ kmem_free(door_buf, door_bufsz);
+ return (NERR_InternalError);
+ }
+
+ arg.data_ptr = door_buf;
+ arg.data_size = used;
+ arg.desc_ptr = NULL;
+ arg.desc_num = 0;
+ arg.rbuf = door_buf;
+ arg.rsize = door_bufsz;
+
+ if (door_ki_upcall(dhdl, &arg) != 0) {
+ cmn_err(CE_WARN, "smb_kshare_enum: Door call failed");
+ kmem_free(door_buf, door_bufsz);
+ return (NERR_InternalError);
+ }
+
+ dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
+ if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) {
+ kmem_free(door_buf, door_bufsz);
+ return (NERR_InternalError);
+ }
+
+ rc = smb_dr_get_uint32(dec_ctx);
+ if (rc == NERR_Success) {
+ enuminfo->es_ntotal = smb_dr_get_ushort(dec_ctx);
+ enuminfo->es_nsent = smb_dr_get_ushort(dec_ctx);
+ enuminfo->es_datasize = smb_dr_get_ushort(dec_ctx);
+ (void) smb_dr_get_buf(dec_ctx,
+ (unsigned char *)enuminfo->es_buf,
+ enuminfo->es_bufsize);
+ }
+
+ if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
+ cmn_err(CE_WARN, "smb_kshare_enum: Decode error %d", status);
+ rc = NERR_InternalError;
+ }
+
+ kmem_free(door_buf, door_bufsz);
+ return (rc);
+}
+
+/*
+ * This is a special interface that will be utilized by ZFS to cause
+ * a share to be added/removed
+ *
+ * arg is either a lmshare_info_t or share_name from userspace.
+ * It will need to be copied into the kernel. It is lmshare_info_t
+ * for add operations and share_name for delete operations.
+ */
+int
+smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share)
+{
+ door_arg_t doorarg = { 0 };
+ char *buf = NULL;
+ char *str = NULL;
+ int error;
+ int rc;
+ unsigned int used;
+ smb_dr_ctx_t *dec_ctx;
+ smb_dr_ctx_t *enc_ctx;
+ lmshare_info_t *lmshare = NULL;
+ int opcode;
+
+ opcode = add_share == B_TRUE ? LMSHR_DOOR_ADD : LMSHR_DOOR_DELETE;
+
+ buf = kmem_alloc(LMSHR_DOOR_SIZE, KM_SLEEP);
+ enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
+ smb_dr_put_uint32(enc_ctx, opcode);
+
+ switch (opcode) {
+ case LMSHR_DOOR_ADD:
+ lmshare = kmem_alloc(sizeof (lmshare_info_t), KM_SLEEP);
+ if (error = xcopyin(arg, lmshare, sizeof (lmshare_info_t))) {
+ kmem_free(lmshare, sizeof (lmshare_info_t));
+ kmem_free(buf, LMSHR_DOOR_SIZE);
+ return (error);
+ }
+ smb_dr_put_lmshare(enc_ctx, lmshare);
+ break;
+
+ case LMSHR_DOOR_DELETE:
+ str = kmem_alloc(MAXPATHLEN, KM_SLEEP);
+ if (error = copyinstr(arg, str, MAXPATHLEN, NULL)) {
+ kmem_free(str, MAXPATHLEN);
+ kmem_free(buf, LMSHR_DOOR_SIZE);
+ return (error);
+ }
+ smb_dr_put_string(enc_ctx, str);
+ kmem_free(str, MAXPATHLEN);
+ break;
+ }
+
+ if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
+ kmem_free(buf, LMSHR_DOOR_SIZE);
+ if (lmshare)
+ kmem_free(lmshare, sizeof (lmshare_info_t));
+ return (NERR_InternalError);
+ }
+
+ doorarg.data_ptr = buf;
+ doorarg.data_size = used;
+ doorarg.rbuf = buf;
+ doorarg.rsize = LMSHR_DOOR_SIZE;
+
+ error = door_ki_upcall(dhdl, &doorarg);
+
+ if (error) {
+ kmem_free(buf, LMSHR_DOOR_SIZE);
+ if (lmshare)
+ kmem_free(lmshare, sizeof (lmshare_info_t));
+ return (error);
+ }
+
+ dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size);
+ if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) {
+ kmem_free(buf, LMSHR_DOOR_SIZE);
+ if (lmshare)
+ kmem_free(lmshare, sizeof (lmshare_info_t));
+ return (NERR_InternalError);
+ }
+
+ rc = smb_dr_get_uint32(dec_ctx);
+ if (opcode == LMSHR_DOOR_ADD)
+ smb_dr_get_lmshare(dec_ctx, lmshare);
+
+ if (smb_dr_decode_finish(dec_ctx))
+ rc = NERR_InternalError;
+
+ kmem_free(buf, LMSHR_DOOR_SIZE);
+ if (lmshare)
+ kmem_free(lmshare, sizeof (lmshare_info_t));
+
+ return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc);
+}
+
+/*
+ * Return 0 upon success. Otherwise > 0
+ */
+static int
+smb_kshare_chk_dsrv_status(int opcode, smb_dr_ctx_t *dec_ctx)
+{
+ int status = smb_dr_get_int32(dec_ctx);
+ int err;
+
+ switch (status) {
+ case LMSHR_DOOR_SRV_SUCCESS:
+ return (0);
+
+ case LMSHR_DOOR_SRV_ERROR:
+ err = smb_dr_get_uint32(dec_ctx);
+ cmn_err(CE_WARN, "%d: Encountered door server error %d",
+ opcode, err);
+ (void) smb_dr_decode_finish(dec_ctx);
+ return (err);
+ }
+
+ ASSERT(0);
+ return (EINVAL);
+}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c
index d00dc52f46..fb144293a5 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c
@@ -450,6 +450,10 @@ smb_lock_range_overlap(struct smb_lock *lock, uint64_t start, uint64_t length)
if (length == 0 || lock->l_length == 0)
return (RANGE_NO_OVERLAP);
+ /* The following test is intended to catch roll over locks. */
+ if ((start == lock->l_start) && (length == lock->l_length))
+ return (RANGE_OVERLAP);
+
if (start < lock->l_start) {
if (start + length > lock->l_start)
return (RANGE_OVERLAP);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_mbuf_util.c b/usr/src/uts/common/fs/smbsrv/smb_mbuf_util.c
index 44716ac8f0..a94a003941 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_mbuf_util.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_mbuf_util.c
@@ -189,6 +189,12 @@ MBC_LENGTH(struct mbuf_chain *MBC)
return (used);
}
+int
+MBC_MAXBYTES(struct mbuf_chain *MBC)
+{
+ return (MBC->max_bytes);
+}
+
void
MBC_SETUP(struct mbuf_chain *MBC, uint32_t max_bytes)
{
diff --git a/usr/src/uts/common/fs/smbsrv/smb_node.c b/usr/src/uts/common/fs/smbsrv/smb_node.c
index 759c6a8dc9..10ecb02af4 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_node.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_node.c
@@ -864,7 +864,7 @@ smb_node_reset_delete_on_close(smb_node_t *node)
}
/*
- * smb_node_share_check
+ * smb_node_open_check
*
* check file sharing rules for current open request
* against all existing opens for a file.
@@ -886,100 +886,30 @@ smb_node_open_check(struct smb_node *node, cred_t *cr,
smb_llist_enter(&node->n_ofile_list, RW_READER);
of = smb_llist_head(&node->n_ofile_list);
while (of) {
- status = smb_node_share_check(node, cr, desired_access,
- share_access, of);
- if (status == NT_STATUS_SHARING_VIOLATION) {
+ status = smb_ofile_open_check(of, cr, desired_access,
+ share_access);
+
+ switch (status) {
+ case NT_STATUS_INVALID_HANDLE:
+ case NT_STATUS_SUCCESS:
+ of = smb_llist_next(&node->n_ofile_list, of);
+ break;
+ default:
+ ASSERT(status == NT_STATUS_SHARING_VIOLATION);
smb_llist_exit(&node->n_ofile_list);
return (status);
}
- of = smb_llist_next(&node->n_ofile_list, of);
}
- smb_llist_exit(&node->n_ofile_list);
+ smb_llist_exit(&node->n_ofile_list);
return (NT_STATUS_SUCCESS);
}
-/*
- * smb_open_share_check
- *
- * check file sharing rules for current open request
- * against the given existing open.
- *
- * Returns NT_STATUS_SHARING_VIOLATION if there is any
- * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
- */
uint32_t
-smb_node_share_check(
- struct smb_node *node,
- cred_t *cr,
- uint32_t desired_access,
- uint32_t share_access,
- smb_ofile_t *of)
-{
- /*
- * It appears that share modes are not relevant to
- * directories, but this check will remain as it is not
- * clear whether it was originally put here for a reason.
- */
- if (node->attr.sa_vattr.va_type == VDIR) {
- if (SMB_DENY_RW(of->f_share_access) &&
- (node->n_orig_uid != crgetuid(cr))) {
- return (NT_STATUS_SHARING_VIOLATION);
- }
-
- return (NT_STATUS_SUCCESS);
- }
-
- /* if it's just meta data */
- if ((of->f_granted_access & FILE_DATA_ALL) == 0)
- return (NT_STATUS_SUCCESS);
-
- /*
- * Check requested share access against the
- * open granted (desired) access
- */
- if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE))
- return (NT_STATUS_SHARING_VIOLATION);
-
- if (SMB_DENY_READ(share_access) &&
- (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE)))
- return (NT_STATUS_SHARING_VIOLATION);
-
- if (SMB_DENY_WRITE(share_access) &&
- (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
- return (NT_STATUS_SHARING_VIOLATION);
-
- /* check requested desired access against the open share access */
- if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE))
- return (NT_STATUS_SHARING_VIOLATION);
-
- if (SMB_DENY_READ(of->f_share_access) &&
- (desired_access & (FILE_READ_DATA | FILE_EXECUTE)))
- return (NT_STATUS_SHARING_VIOLATION);
-
- if (SMB_DENY_WRITE(of->f_share_access) &&
- (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
- return (NT_STATUS_SHARING_VIOLATION);
-
- return (NT_STATUS_SUCCESS);
-}
-
-/*
- * smb_rename_share_check
- *
- * An open file can be renamed if
- *
- * 1. isn't opened for data writing or deleting
- *
- * 2. Opened with "Deny Delete" share mode
- * But not opened for data reading or executing
- * (opened for accessing meta data)
- */
-
-DWORD
smb_node_rename_check(struct smb_node *node)
{
- struct smb_ofile *open;
+ struct smb_ofile *of;
+ uint32_t status;
ASSERT(node);
ASSERT(node->n_magic == SMB_NODE_MAGIC);
@@ -990,22 +920,20 @@ smb_node_rename_check(struct smb_node *node)
*/
smb_llist_enter(&node->n_ofile_list, RW_READER);
- open = smb_llist_head(&node->n_ofile_list);
- while (open) {
- if (open->f_granted_access &
- (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) {
- smb_llist_exit(&node->n_ofile_list);
- return (NT_STATUS_SHARING_VIOLATION);
- }
+ of = smb_llist_head(&node->n_ofile_list);
+ while (of) {
+ status = smb_ofile_rename_check(of);
- if ((open->f_share_access & FILE_SHARE_DELETE) == 0) {
- if (open->f_granted_access &
- (FILE_READ_DATA | FILE_EXECUTE)) {
- smb_llist_exit(&node->n_ofile_list);
- return (NT_STATUS_SHARING_VIOLATION);
- }
+ switch (status) {
+ case NT_STATUS_INVALID_HANDLE:
+ case NT_STATUS_SUCCESS:
+ of = smb_llist_next(&node->n_ofile_list, of);
+ break;
+ default:
+ ASSERT(status == NT_STATUS_SHARING_VIOLATION);
+ smb_llist_exit(&node->n_ofile_list);
+ return (status);
}
- open = smb_llist_next(&node->n_ofile_list, open);
}
smb_llist_exit(&node->n_ofile_list);
@@ -1019,27 +947,11 @@ smb_node_rename_check(struct smb_node *node)
return (NT_STATUS_SUCCESS);
}
-/*
- * smb_node_delete_check
- *
- * An open file can be deleted only if opened for
- * accessing meta data. Share modes aren't important
- * in this case.
- *
- * NOTE: there is another mechanism for deleting an
- * open file that NT clients usually use.
- * That's setting "Delete on close" flag for an open
- * file. In this way the file will be deleted after
- * last close. This flag can be set by SmbTrans2SetFileInfo
- * with FILE_DISPOSITION_INFO information level.
- * For setting this flag, the file should be opened by
- * DELETE access in the FID that is passed in the Trans2
- * request.
- */
-DWORD
+uint32_t
smb_node_delete_check(smb_node_t *node)
{
- smb_ofile_t *file;
+ smb_ofile_t *of;
+ uint32_t status;
ASSERT(node);
ASSERT(node->n_magic == SMB_NODE_MAGIC);
@@ -1053,19 +965,20 @@ smb_node_delete_check(smb_node_t *node)
*/
smb_llist_enter(&node->n_ofile_list, RW_READER);
- file = smb_llist_head(&node->n_ofile_list);
- while (file) {
- ASSERT(file->f_magic == SMB_OFILE_MAGIC);
- if (file->f_granted_access &
- (FILE_READ_DATA |
- FILE_WRITE_DATA |
- FILE_APPEND_DATA |
- FILE_EXECUTE |
- DELETE)) {
+ of = smb_llist_head(&node->n_ofile_list);
+ while (of) {
+ status = smb_ofile_delete_check(of);
+
+ switch (status) {
+ case NT_STATUS_INVALID_HANDLE:
+ case NT_STATUS_SUCCESS:
+ of = smb_llist_next(&node->n_ofile_list, of);
+ break;
+ default:
+ ASSERT(status == NT_STATUS_SHARING_VIOLATION);
smb_llist_exit(&node->n_ofile_list);
- return (NT_STATUS_SHARING_VIOLATION);
+ return (status);
}
- file = smb_llist_next(&node->n_ofile_list, file);
}
smb_llist_exit(&node->n_ofile_list);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c
index 5ee4fb0b56..cae9df9f8f 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c
@@ -746,3 +746,181 @@ smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access)
return (NT_STATUS_SUCCESS);
}
+
+
+/*
+ * smb_ofile_open_check
+ *
+ * check file sharing rules for current open request
+ * against existing open instances of the same file
+ *
+ * Returns NT_STATUS_SHARING_VIOLATION if there is any
+ * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
+ */
+uint32_t
+smb_ofile_open_check(
+ smb_ofile_t *of,
+ cred_t *cr,
+ uint32_t desired_access,
+ uint32_t share_access)
+{
+ smb_node_t *node;
+
+ ASSERT(of->f_magic == SMB_OFILE_MAGIC);
+
+ node = of->f_node;
+
+ mutex_enter(&of->f_mutex);
+
+ if (of->f_state != SMB_OFILE_STATE_OPEN) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_INVALID_HANDLE);
+ }
+
+ /*
+ * It appears that share modes are not relevant to
+ * directories, but this check will remain as it is not
+ * clear whether it was originally put here for a reason.
+ */
+ if (node->attr.sa_vattr.va_type == VDIR) {
+ if (SMB_DENY_RW(of->f_share_access) &&
+ (node->n_orig_uid != crgetuid(cr))) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SHARING_VIOLATION);
+ }
+
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SUCCESS);
+ }
+
+ /* if it's just meta data */
+ if ((of->f_granted_access & FILE_DATA_ALL) == 0) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SUCCESS);
+ }
+
+ /*
+ * Check requested share access against the
+ * open granted (desired) access
+ */
+ if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SHARING_VIOLATION);
+ }
+
+ if (SMB_DENY_READ(share_access) &&
+ (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SHARING_VIOLATION);
+ }
+
+ if (SMB_DENY_WRITE(share_access) &&
+ (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SHARING_VIOLATION);
+ }
+
+ /* check requested desired access against the open share access */
+ if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SHARING_VIOLATION);
+ }
+
+ if (SMB_DENY_READ(of->f_share_access) &&
+ (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SHARING_VIOLATION);
+ }
+
+ if (SMB_DENY_WRITE(of->f_share_access) &&
+ (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SHARING_VIOLATION);
+ }
+
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SUCCESS);
+}
+
+/*
+ * smb_ofile_rename_check
+ *
+ * An open file can be renamed if
+ *
+ * 1. isn't opened for data writing or deleting
+ *
+ * 2. Opened with "Deny Delete" share mode
+ * But not opened for data reading or executing
+ * (opened for accessing meta data)
+ */
+
+uint32_t
+smb_ofile_rename_check(smb_ofile_t *of)
+{
+ ASSERT(of->f_magic == SMB_OFILE_MAGIC);
+
+ mutex_enter(&of->f_mutex);
+
+ if (of->f_state != SMB_OFILE_STATE_OPEN) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_INVALID_HANDLE);
+ }
+
+ if (of->f_granted_access &
+ (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SHARING_VIOLATION);
+ }
+
+ if ((of->f_share_access & FILE_SHARE_DELETE) == 0) {
+ if (of->f_granted_access &
+ (FILE_READ_DATA | FILE_EXECUTE)) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SHARING_VIOLATION);
+ }
+ }
+
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SUCCESS);
+}
+
+/*
+ * smb_ofile_delete_check
+ *
+ * An open file can be deleted only if opened for
+ * accessing meta data. Share modes aren't important
+ * in this case.
+ *
+ * NOTE: there is another mechanism for deleting an
+ * open file that NT clients usually use.
+ * That's setting "Delete on close" flag for an open
+ * file. In this way the file will be deleted after
+ * last close. This flag can be set by SmbTrans2SetFileInfo
+ * with FILE_DISPOSITION_INFO information level.
+ * For setting this flag, the file should be opened by
+ * DELETE access in the FID that is passed in the Trans2
+ * request.
+ */
+
+uint32_t
+smb_ofile_delete_check(smb_ofile_t *of)
+{
+ ASSERT(of->f_magic == SMB_OFILE_MAGIC);
+
+ mutex_enter(&of->f_mutex);
+
+ if (of->f_state != SMB_OFILE_STATE_OPEN) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_INVALID_HANDLE);
+ }
+
+ if (of->f_granted_access &
+ (FILE_READ_DATA | FILE_WRITE_DATA |
+ FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) {
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SHARING_VIOLATION);
+ }
+
+ mutex_exit(&of->f_mutex);
+ return (NT_STATUS_SUCCESS);
+}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_server.c b/usr/src/uts/common/fs/smbsrv/smb_server.c
index 63846f7583..eaec0f8d39 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c
@@ -548,7 +548,7 @@ smb_server_start(struct smb_io_start *io_start)
if (rc = smb_server_fsop_start(sv))
break;
ASSERT(sv->sv_lmshrd == NULL);
- sv->sv_lmshrd = lmshrd_kclient_init(io_start->lmshrd);
+ sv->sv_lmshrd = smb_kshare_init(io_start->lmshrd);
if (sv->sv_lmshrd == NULL)
break;
if (rc = smb_kdoor_clnt_start(io_start->udoor))
@@ -1023,7 +1023,7 @@ smb_server_share(void *arg, boolean_t add_share)
mutex_enter(&sv->sv_mutex);
if (sv->sv_state == SMB_SERVER_STATE_RUNNING) {
mutex_exit(&sv->sv_mutex);
- rc = lmshrd_share_upcall(sv->sv_lmshrd, arg, add_share);
+ rc = smb_kshare_upcall(sv->sv_lmshrd, arg, add_share);
} else {
mutex_exit(&sv->sv_mutex);
rc = EPERM;
@@ -1172,7 +1172,7 @@ smb_server_stop(smb_server_t *sv)
smb_winpipe_close();
smb_thread_stop(&sv->si_thread_timers);
smb_kdoor_clnt_stop();
- lmshrd_kclient_fini(sv->sv_lmshrd);
+ smb_kshare_fini(sv->sv_lmshrd);
smb_server_fsop_stop(sv);
if (sv->sv_session) {
smb_session_delete(sv->sv_session);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_share_kdoor_client.c b/usr/src/uts/common/fs/smbsrv/smb_share_kdoor_client.c
deleted file mode 100644
index 23635d0561..0000000000
--- a/usr/src/uts/common/fs/smbsrv/smb_share_kdoor_client.c
+++ /dev/null
@@ -1,604 +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 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Kernel door client for LanMan share management.
- */
-
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/cmn_err.h>
-#include <sys/door.h>
-#include <smbsrv/lmshare.h>
-#include <smbsrv/lmerr.h>
-#include <smbsrv/smb_common_door.h>
-#include <smbsrv/lmshare_door.h>
-#include <smbsrv/alloc.h>
-#include <smbsrv/smbinfo.h>
-
-const char *lmshrd_desc[] = {
- "",
- "LmshrkOpenIter",
- "LmshrkCloseIter",
- "LmshrkIterate",
- "LmshrkNumShares",
- "",
- "",
- "LmshrkGetinfo",
- "",
- "",
- "LmshrkExists",
- "LmshrkIsSpecial",
- "LmshrkIsRestricted",
- "LmshrkIsAdmin",
- "LmshrkIsValid",
- "LmshrkIsDir",
- "LmshrkList",
- "LmshrkListTrans",
- "LmshrkNumTrans",
- "SmbGetKConfig",
- NULL
-};
-
-static int lmshrd_door_check_srv_status(int, smb_dr_ctx_t *);
-
-/*
- * lmshrd_kclient_init
- *
- * This function is not MultiThread safe. The caller has to make sure only one
- * thread calls this function.
- */
-door_handle_t
-lmshrd_kclient_init(int door_id)
-{
- return (door_ki_lookup(door_id));
-}
-
-/*
- * lmshrd_kclient_fini
- *
- * This function is not MultiThread safe. The caller has to make sure only one
- * thread calls this function.
- */
-void
-lmshrd_kclient_fini(door_handle_t dhdl)
-{
- ASSERT(dhdl != NULL);
- if (dhdl)
- door_ki_rele(dhdl);
-}
-
-uint64_t
-lmshrd_open_iterator(door_handle_t dhdl, int mode)
-{
- door_arg_t arg;
- char *buf;
- unsigned int used;
- smb_dr_ctx_t *dec_ctx;
- smb_dr_ctx_t *enc_ctx;
- unsigned int status = 0;
- uint64_t lmshr_iter = 0;
-
- int opcode = LMSHR_DOOR_OPEN_ITERATOR;
-
- buf = MEM_MALLOC("lmshrd_kclient", LMSHR_DOOR_SIZE);
- if (!buf)
- return (lmshr_iter);
-
- enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
- smb_dr_put_uint32(enc_ctx, opcode);
- smb_dr_put_int32(enc_ctx, mode);
- if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
- cmn_err(CE_WARN, "%s: Encode error %d",
- lmshrd_desc[opcode], status);
- MEM_FREE("lmshrd_kclient", buf);
- return (lmshr_iter);
- }
-
- arg.data_ptr = buf;
- arg.data_size = used;
- arg.desc_ptr = NULL;
- arg.desc_num = 0;
- arg.rbuf = buf;
- arg.rsize = LMSHR_DOOR_SIZE;
-
- if (door_ki_upcall(dhdl, &arg) != 0) {
- cmn_err(CE_WARN, "%s: Door call failed", lmshrd_desc[opcode]);
- MEM_FREE("lmshrd_kclient", buf);
- return (lmshr_iter);
- }
-
- dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
- if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
- MEM_FREE("lmshrd_kclient", buf);
- return (lmshr_iter);
- }
-
- lmshr_iter = smb_dr_get_lmshr_iterator(dec_ctx);
- if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
- cmn_err(CE_WARN, "%s: Decode error %d",
- lmshrd_desc[opcode], status);
- MEM_FREE("lmshrd_kclient", buf);
- return (lmshr_iter);
- }
-
- MEM_FREE("lmshrd_kclient", buf);
- return (lmshr_iter);
-}
-
-uint32_t
-lmshrd_close_iterator(door_handle_t dhdl, uint64_t iterator)
-{
- door_arg_t arg;
- char *buf;
- unsigned int used;
- smb_dr_ctx_t *dec_ctx;
- smb_dr_ctx_t *enc_ctx;
- unsigned int status = 0;
- int opcode = LMSHR_DOOR_CLOSE_ITERATOR;
-
- buf = MEM_MALLOC("lmshrd_kclient", LMSHR_DOOR_SIZE);
- if (!buf)
- return (NERR_InternalError);
-
- enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
- smb_dr_put_uint32(enc_ctx, opcode);
- smb_dr_put_lmshr_iterator(enc_ctx, iterator);
- if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
- cmn_err(CE_WARN, "%s: Encode error %d",
- lmshrd_desc[opcode], status);
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- arg.data_ptr = buf;
- arg.data_size = used;
- arg.desc_ptr = NULL;
- arg.desc_num = 0;
- arg.rbuf = buf;
- arg.rsize = LMSHR_DOOR_SIZE;
-
- if (door_ki_upcall(dhdl, &arg) != 0) {
- cmn_err(CE_WARN, "%s: Door call failed", lmshrd_desc[opcode]);
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
- if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
- cmn_err(CE_WARN, "%s: Decode error %d",
- lmshrd_desc[opcode], status);
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_Success);
-}
-
-uint32_t
-lmshrd_iterate(door_handle_t dhdl, uint64_t iterator, lmshare_info_t *si)
-{
- door_arg_t arg;
- char *buf;
- unsigned int used;
- smb_dr_ctx_t *dec_ctx;
- smb_dr_ctx_t *enc_ctx;
- unsigned int status = 0;
- int opcode = LMSHR_DOOR_ITERATE;
-
- buf = MEM_MALLOC("lmshrd_kclient", LMSHR_DOOR_SIZE);
- if (!buf)
- return (NERR_InternalError);
-
- bzero(si, sizeof (lmshare_info_t));
- enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
- smb_dr_put_uint32(enc_ctx, opcode);
- smb_dr_put_lmshr_iterator(enc_ctx, iterator);
- if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
- cmn_err(CE_WARN, "%s: Encode error %d",
- lmshrd_desc[opcode], status);
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- arg.data_ptr = buf;
- arg.data_size = used;
- arg.desc_ptr = NULL;
- arg.desc_num = 0;
- arg.rbuf = buf;
- arg.rsize = LMSHR_DOOR_SIZE;
-
- if (door_ki_upcall(dhdl, &arg) != 0) {
- cmn_err(CE_WARN, "%s: Door call failed", lmshrd_desc[opcode]);
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
- if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- smb_dr_get_lmshare(dec_ctx, si);
- if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
- cmn_err(CE_WARN, "%s: Decode error %d",
- lmshrd_desc[opcode], status);
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_Success);
-}
-
-int
-lmshrd_num_shares(door_handle_t dhdl)
-{
- door_arg_t arg;
- char *buf;
- unsigned int used;
- smb_dr_ctx_t *dec_ctx;
- smb_dr_ctx_t *enc_ctx;
- unsigned int status = 0;
- uint32_t num_shares;
- int opcode = LMSHR_DOOR_NUM_SHARES;
-
- buf = MEM_MALLOC("lmshrd_kclient", LMSHR_DOOR_SIZE);
- if (!buf)
- return (-1);
-
- enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
- smb_dr_put_uint32(enc_ctx, opcode);
- if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
- cmn_err(CE_WARN, "%s: Encode error %d",
- lmshrd_desc[opcode], status);
- MEM_FREE("lmshrd_kclient", buf);
- return (-1);
- }
-
- arg.data_ptr = buf;
- arg.data_size = used;
- arg.desc_ptr = NULL;
- arg.desc_num = 0;
- arg.rbuf = buf;
- arg.rsize = LMSHR_DOOR_SIZE;
-
- if (door_ki_upcall(dhdl, &arg) != 0) {
- cmn_err(CE_WARN, "%s: Door call failed", lmshrd_desc[opcode]);
- MEM_FREE("lmshrd_kclient", buf);
- return (-1);
- }
-
- dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
- if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
- MEM_FREE("lmshrd_kclient", buf);
- return (-1);
- }
-
- num_shares = smb_dr_get_uint32(dec_ctx);
- if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
- cmn_err(CE_WARN, "%s: Decode error %d",
- lmshrd_desc[opcode], status);
- MEM_FREE("lmshrd_kclient", buf);
- return (-1);
- }
-
- MEM_FREE("lmshrd_kclient", buf);
- return (num_shares);
-}
-
-uint32_t
-lmshrd_getinfo(door_handle_t dhdl, char *share_name, lmshare_info_t *si)
-{
- door_arg_t arg;
- char *buf;
- unsigned int used;
- smb_dr_ctx_t *dec_ctx;
- smb_dr_ctx_t *enc_ctx;
- int status;
- uint32_t rc;
- int opcode = LMSHR_DOOR_GETINFO;
-
- buf = MEM_MALLOC("lmshrd_kclient", LMSHR_DOOR_SIZE);
- if (!buf)
- return (NERR_InternalError);
-
- enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
- smb_dr_put_uint32(enc_ctx, opcode);
- smb_dr_put_string(enc_ctx, share_name);
-
- if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
- cmn_err(CE_WARN, "%s: Encode error %d",
- lmshrd_desc[opcode], status);
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- arg.data_ptr = buf;
- arg.data_size = used;
- arg.desc_ptr = NULL;
- arg.desc_num = 0;
- arg.rbuf = buf;
- arg.rsize = LMSHR_DOOR_SIZE;
-
- if (door_ki_upcall(dhdl, &arg) != 0) {
- cmn_err(CE_WARN, "%s: Door call failed", lmshrd_desc[opcode]);
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
- if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- rc = smb_dr_get_uint32(dec_ctx);
- smb_dr_get_lmshare(dec_ctx, si);
- if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
- cmn_err(CE_WARN, "%s: Decode error %d",
- lmshrd_desc[opcode], status);
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- MEM_FREE("lmshrd_kclient", buf);
- return (rc);
-}
-
-int
-lmshrd_check(door_handle_t dhdl, char *share_name, int opcode)
-{
- door_arg_t arg;
- char *buf;
- unsigned int used;
- smb_dr_ctx_t *dec_ctx;
- smb_dr_ctx_t *enc_ctx;
- int status, rc;
-
- buf = MEM_MALLOC("lmshrd_kclient", LMSHR_DOOR_SIZE);
- if (!buf)
- return (NERR_InternalError);
-
- enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
- smb_dr_put_uint32(enc_ctx, opcode);
- smb_dr_put_string(enc_ctx, share_name);
-
- if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
- cmn_err(CE_WARN, "%s: Encode error %d",
- lmshrd_desc[opcode], status);
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- arg.data_ptr = buf;
- arg.data_size = used;
- arg.desc_ptr = NULL;
- arg.desc_num = 0;
- arg.rbuf = buf;
- arg.rsize = LMSHR_DOOR_SIZE;
-
- if (door_ki_upcall(dhdl, &arg) != 0) {
- cmn_err(CE_WARN, "%s: Door call failed", lmshrd_desc[opcode]);
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
- if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- rc = smb_dr_get_int32(dec_ctx);
- if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
- cmn_err(CE_WARN, "%s: Decode error %d",
- lmshrd_desc[opcode], status);
- MEM_FREE("lmshrd_kclient", buf);
- return (NERR_InternalError);
- }
-
- MEM_FREE("lmshrd_kclient", buf);
- return (rc);
-}
-
-int
-lmshrd_exists(door_handle_t dhdl, char *share_name)
-{
- return (lmshrd_check(dhdl, share_name, LMSHR_DOOR_EXISTS));
-}
-
-int
-lmshrd_is_special(door_handle_t dhdl, char *share_name)
-{
- return (lmshrd_check(dhdl, share_name, LMSHR_DOOR_IS_SPECIAL));
-}
-
-int
-lmshrd_is_restricted(door_handle_t dhdl, char *share_name)
-{
- return (lmshrd_check(dhdl, share_name, LMSHR_DOOR_IS_RESTRICTED));
-}
-
-int
-lmshrd_is_admin(door_handle_t dhdl, char *share_name)
-{
- return (lmshrd_check(dhdl, share_name, LMSHR_DOOR_IS_ADMIN));
-}
-
-int
-lmshrd_is_valid(door_handle_t dhdl, char *share_name)
-{
- return (lmshrd_check(dhdl, share_name, LMSHR_DOOR_IS_VALID));
-}
-
-int
-lmshrd_is_dir(door_handle_t dhdl, char *path)
-{
- return (lmshrd_check(dhdl, path, LMSHR_DOOR_IS_DIR));
-}
-
-/*
- * This is a special interface that will be utilized by ZFS to cause
- * a share to be added/removed
- *
- * arg is either a lmshare_info_t or share_name from userspace.
- * It will need to be copied into the kernel. It is lmshare_info_t
- * for add operations and share_name for delete operations.
- */
-int
-lmshrd_share_upcall(door_handle_t dhdl, void *arg, boolean_t add_share)
-{
- door_arg_t doorarg = { 0 };
- char *buf = NULL;
- char *str = NULL;
- int error;
- int rc;
- unsigned int used;
- smb_dr_ctx_t *dec_ctx;
- smb_dr_ctx_t *enc_ctx;
- lmshare_info_t *lmshare = NULL;
- int opcode;
-
- opcode = add_share == B_TRUE ? LMSHR_DOOR_ADD : LMSHR_DOOR_DELETE;
-
- buf = MEM_MALLOC("lmshrd_share_upcall", LMSHR_DOOR_SIZE);
- enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
- smb_dr_put_uint32(enc_ctx, opcode);
-
- switch (opcode) {
- case LMSHR_DOOR_ADD:
- lmshare = MEM_MALLOC("lmshrd_share_upcall",
- sizeof (lmshare_info_t));
-
- if (error = xcopyin(arg, lmshare, sizeof (lmshare_info_t))) {
- MEM_FREE("lmshrd_share_upcall", lmshare);
- MEM_FREE("lmshrd_share_upcall", buf);
- return (error);
- }
- smb_dr_put_lmshare(enc_ctx, lmshare);
- break;
-
- case LMSHR_DOOR_DELETE:
- str = MEM_MALLOC("lmshrd_share_upcall", MAXPATHLEN);
- if (error = copyinstr(arg, str, MAXPATHLEN, NULL)) {
- MEM_FREE("lmshrd_share_upcall", buf);
- MEM_FREE("lmshrd_share_upcall", str);
- return (error);
- }
- smb_dr_put_string(enc_ctx, str);
- MEM_FREE("lmshrd_share_upcall", str);
- break;
- }
-
- if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
- MEM_FREE("lmshrd_share_upcall", buf);
- if (lmshare)
- MEM_FREE("lmshrd_share_upcall", lmshare);
- return (NERR_InternalError);
- }
-
- doorarg.data_ptr = buf;
- doorarg.data_size = used;
- doorarg.rbuf = buf;
- doorarg.rsize = LMSHR_DOOR_SIZE;
-
- error = door_ki_upcall(dhdl, &doorarg);
-
- if (error) {
- MEM_FREE("lmshrd_share_upcall", buf);
- if (lmshare)
- MEM_FREE("lmshrd_share_upcall", lmshare);
- return (error);
- }
-
- dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size);
- if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
- MEM_FREE("lmshrd_share_upcall", buf);
- if (lmshare)
- MEM_FREE("lmshrd_share_upcall", lmshare);
- return (NERR_InternalError);
- }
-
- rc = smb_dr_get_uint32(dec_ctx);
- if (opcode == LMSHR_DOOR_ADD)
- smb_dr_get_lmshare(dec_ctx, lmshare);
-
- if (smb_dr_decode_finish(dec_ctx)) {
- MEM_FREE("lmshrd_share_upcall", buf);
- if (lmshare)
- MEM_FREE("lmshrd_share_upcall", lmshare);
- return (NERR_InternalError);
- }
-
- MEM_FREE("lmshrd_share_upcall", buf);
- if (lmshare)
- MEM_FREE("lmshrd_share_upcall", lmshare);
- return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc);
-}
-
-/*
- * Return 0 upon success. Otherwise, -1.
- */
-static int
-lmshrd_door_check_srv_status(int opcode, smb_dr_ctx_t *dec_ctx)
-{
- int status = smb_dr_get_int32(dec_ctx);
- int err;
- int rc = -1;
-
- switch (status) {
- case LMSHR_DOOR_SRV_SUCCESS:
- rc = 0;
- break;
-
- case LMSHR_DOOR_SRV_ERROR:
- err = smb_dr_get_uint32(dec_ctx);
- cmn_err(CE_WARN, "%s: Encountered door server error %d",
- lmshrd_desc[opcode], err);
- break;
-
- default:
- cmn_err(CE_WARN, "%s: Unknown door server status",
- lmshrd_desc[opcode]);
- }
-
- if (rc != 0) {
- if ((err = smb_dr_decode_finish(dec_ctx)) != 0)
- cmn_err(CE_WARN, "%s: Decode error %d",
- lmshrd_desc[opcode], err);
- }
-
- return (rc);
-}
diff --git a/usr/src/uts/common/smbsrv/lmshare.h b/usr/src/uts/common/smbsrv/lmshare.h
index 75a1a9e275..6f90d1b7e8 100644
--- a/usr/src/uts/common/smbsrv/lmshare.h
+++ b/usr/src/uts/common/smbsrv/lmshare.h
@@ -59,19 +59,41 @@ extern "C" {
* Despite the fact that the MAXNAMELEN is 256, we only
* support a maximum share name length of 15 characters.
*/
+
+#define LMSHR_OEM_NAME_MAX 13
#define LMSHR_VALID_NAME_MAX 15
#define LMSHR_VALID_NAME_BUFSIZ 16
#define LMSHR_COMMENT_MAX (64 * MTS_MB_CHAR_MAX)
/*
+ * struct SHARE_INFO_1 {
+ * char shi1_netname[13]
+ * char shi1_pad;
+ * unsigned short shi1_type
+ * char *shi1_remark;
+ * }
+ */
+#define SHARE_INFO_1_SIZE (LMSHR_OEM_NAME_MAX + 1 + 2 + 4)
+
+/*
* Mode should be renamed to flags.
*
* LMSHRM_TRANS Transient share
* LMSHRM_PERM Permanent share
+ * LMSHRM_AUTOHOME Autohome share.
+ * LMSHRM_LONGNAME Share name in OEM is longer than 13 chars
+ * LMSHRM_ADMIN Admin share
+ *
+ * All autohome shares are transient but not all transient shares are autohome.
+ * IPC$ and drive letter shares (e.g. d$, e$, etc) are transient but
+ * not autohome.
*/
-#define LMSHRM_TRANS 0x0001
-#define LMSHRM_PERM 0x0002
-#define LMSHRM_ALL (LMSHRM_TRANS | LMSHRM_PERM)
+#define LMSHRM_TRANS 0x0001
+#define LMSHRM_PERM 0x0002
+#define LMSHRM_AUTOHOME 0x0004
+#define LMSHRM_LONGNAME 0x0008
+#define LMSHRM_ADMIN 0x0010
+#define LMSHRM_ALL (LMSHRM_TRANS | LMSHRM_PERM)
#define LMSHR_PUBLISH 0
#define LMSHR_UNPUBLISH 1
@@ -86,20 +108,21 @@ extern "C" {
* one is disconnected
*/
typedef struct lmshare_info {
- char share_name[MAXNAMELEN];
- char directory[MAXPATHLEN];
- char comment[LMSHR_COMMENT_MAX];
- char container[MAXPATHLEN];
- int mode;
- int stype;
- int refcnt;
+ char share_name[MAXNAMELEN];
+ char directory[MAXPATHLEN];
+ char comment[LMSHR_COMMENT_MAX];
+ char container[MAXPATHLEN];
+ char oem_name[LMSHR_OEM_NAME_MAX];
+ uint32_t mode;
+ uint32_t stype;
+ uint32_t refcnt;
} lmshare_info_t;
typedef struct lmshare_iterator {
lmshare_info_t si;
- HT_ITERATOR *iterator;
- unsigned int iteration;
- int mode;
+ HT_ITERATOR iterator;
+ uint32_t iteration;
+ uint32_t mode;
} lmshare_iterator_t;
#define LMSHARES_PER_REQUEST 10
@@ -109,6 +132,29 @@ typedef struct lmshare_list {
} lmshare_list_t;
/*
+ * This structure is a helper for building NetShareEnum response
+ * in user space and send it back down to kernel.
+ *
+ * es_username name of the user requesting the shares list which
+ * is used to detect if the user has any autohome
+ * es_bufsize size of the response buffer
+ * es_buf pointer to the response buffer
+ * es_ntotal total number of shares exported by server which
+ * their OEM names is less then 13 chars
+ * es_nsent number of shares that can fit in the specified buffer
+ * es_datasize actual data size (share's data) which was encoded
+ * in the response buffer
+ */
+typedef struct smb_enumshare_info {
+ char *es_username;
+ uint16_t es_bufsize;
+ char *es_buf;
+ uint16_t es_ntotal;
+ uint16_t es_nsent;
+ uint16_t es_datasize;
+} smb_enumshare_info_t;
+
+/*
* LanMan share API (for both SMB kernel module and GUI/CLI sub-system)
*
* NOTE: If any error is encounted by either the door server or client,
@@ -124,11 +170,10 @@ typedef struct lmshare_list {
*/
int lmshare_start(void);
void lmshare_stop(void);
-lmshare_iterator_t *lmshare_open_iterator(int mode);
-void lmshare_close_iterator(lmshare_iterator_t *);
+void lmshare_init_iterator(lmshare_iterator_t *, uint32_t);
lmshare_info_t *lmshare_iterate(lmshare_iterator_t *iterator);
-DWORD lmshare_list(int offset, lmshare_list_t *list);
+void lmshare_list(int offset, lmshare_list_t *list);
DWORD lmshare_list_transient(int offset, lmshare_list_t *list);
int lmshare_num_transient(void);
@@ -147,17 +192,12 @@ int lmshare_is_restricted(char *share_name);
int lmshare_is_admin(char *share_name);
int lmshare_is_valid(char *share_name);
int lmshare_is_dir(char *path);
-/* XXX Move these 2 functions in mlsvc_util.h, after the libmlsvc cleanup */
-sa_group_t smb_get_smb_share_group(sa_handle_t handle);
-void smb_build_lmshare_info(char *share_name, char *path,
- sa_optionset_t opts, lmshare_info_t *si);
-/* The following 3 functions are called by FSD user-space library */
DWORD lmshare_add_adminshare(char *volname, unsigned char drive);
-uint64_t lmshrd_open_iterator(int);
-DWORD lmshrd_close_iterator(uint64_t);
-DWORD lmshrd_iterate(uint64_t iterator, lmshare_info_t *si);
+sa_group_t smb_get_smb_share_group(sa_handle_t);
+void smb_build_lmshare_info(char *, char *, sa_resource_t, lmshare_info_t *);
+
DWORD lmshrd_list(int offset, lmshare_list_t *list);
DWORD lmshrd_list_transient(int offset, lmshare_list_t *list);
DWORD lmshrd_num_transient(void);
@@ -176,21 +216,11 @@ DWORD lmshrd_setinfo(lmshare_info_t *);
#else
-door_handle_t lmshrd_kclient_init(int);
-void lmshrd_kclient_fini(door_handle_t);
-uint64_t lmshrd_open_iterator(door_handle_t, int);
-uint32_t lmshrd_close_iterator(door_handle_t, uint64_t);
-uint32_t lmshrd_iterate(door_handle_t, uint64_t, lmshare_info_t *);
-int lmshrd_num_shares(door_handle_t);
-uint32_t lmshrd_getinfo(door_handle_t, char *, lmshare_info_t *);
-int lmshrd_check(door_handle_t, char *, int);
-int lmshrd_exists(door_handle_t, char *);
-int lmshrd_is_special(door_handle_t, char *);
-int lmshrd_is_restricted(door_handle_t, char *);
-int lmshrd_is_admin(door_handle_t, char *);
-int lmshrd_is_valid(door_handle_t, char *);
-int lmshrd_is_dir(door_handle_t, char *);
-int lmshrd_share_upcall(door_handle_t, void *, boolean_t);
+door_handle_t smb_kshare_init(int);
+void smb_kshare_fini(door_handle_t);
+uint32_t smb_kshare_getinfo(door_handle_t, char *, lmshare_info_t *);
+int smb_kshare_upcall(door_handle_t, void *, boolean_t);
+uint32_t smb_kshare_enum(door_handle_t, smb_enumshare_info_t *);
#endif
diff --git a/usr/src/uts/common/smbsrv/lmshare_door.h b/usr/src/uts/common/smbsrv/lmshare_door.h
index 4e4413bc9a..96f3110b1e 100644
--- a/usr/src/uts/common/smbsrv/lmshare_door.h
+++ b/usr/src/uts/common/smbsrv/lmshare_door.h
@@ -44,35 +44,27 @@ extern "C" {
#define LMSHR_DOOR_VERSION 1
#define LMSHR_DOOR_COOKIE ((void*)(0xdeadbeef^LMSHR_DOOR_VERSION))
-#define LMSHR_DOOR_SIZE (sizeof (lmshare_list_t) + 32)
+#define LMSHR_DOOR_SIZE (65 * 1024)
/*
* Door interface
*
* Define door operations
*/
-#define LMSHR_DOOR_OPEN_ITERATOR 1
-#define LMSHR_DOOR_CLOSE_ITERATOR 2
-#define LMSHR_DOOR_ITERATE 3
-#define LMSHR_DOOR_NUM_SHARES 4
-#define LMSHR_DOOR_DELETE 5
-#define LMSHR_DOOR_RENAME 6
-#define LMSHR_DOOR_GETINFO 7
-#define LMSHR_DOOR_ADD 8
-#define LMSHR_DOOR_SETINFO 9
-#define LMSHR_DOOR_EXISTS 10
-#define LMSHR_DOOR_IS_SPECIAL 11
-#define LMSHR_DOOR_IS_RESTRICTED 12
-#define LMSHR_DOOR_IS_ADMIN 13
-#define LMSHR_DOOR_IS_VALID 14
-#define LMSHR_DOOR_IS_DIR 15
-#define LMSHR_DOOR_LIST 16
-
-#define SMB_GET_KCONFIG 17
-
-void smb_load_kconfig(smb_kmod_cfg_t *);
-void smb_dr_get_kconfig(smb_dr_ctx_t *, smb_kmod_cfg_t *);
-void smb_dr_put_kconfig(smb_dr_ctx_t *, smb_kmod_cfg_t *);
+#define LMSHR_DOOR_NUM_SHARES 1
+#define LMSHR_DOOR_DELETE 2
+#define LMSHR_DOOR_RENAME 3
+#define LMSHR_DOOR_GETINFO 4
+#define LMSHR_DOOR_ADD 5
+#define LMSHR_DOOR_SETINFO 6
+#define LMSHR_DOOR_EXISTS 7
+#define LMSHR_DOOR_IS_SPECIAL 8
+#define LMSHR_DOOR_IS_RESTRICTED 9
+#define LMSHR_DOOR_IS_ADMIN 10
+#define LMSHR_DOOR_IS_VALID 11
+#define LMSHR_DOOR_IS_DIR 12
+#define LMSHR_DOOR_LIST 13
+#define LMSHR_DOOR_ENUM 14
/*
* Door server status
@@ -100,9 +92,6 @@ void smb_dr_put_kconfig(smb_dr_ctx_t *, smb_kmod_cfg_t *);
void smb_dr_get_lmshare(smb_dr_ctx_t *, lmshare_info_t *);
void smb_dr_put_lmshare(smb_dr_ctx_t *, lmshare_info_t *);
-uint64_t smb_dr_get_lmshr_iterator(smb_dr_ctx_t *);
-void smb_dr_put_lmshr_iterator(smb_dr_ctx_t *, uint64_t);
-void smb_dr_free_lmshr_iterator(smb_dr_ctx_t *);
void smb_dr_get_lmshr_list(smb_dr_ctx_t *, lmshare_list_t *);
void smb_dr_put_lmshr_list(smb_dr_ctx_t *, lmshare_list_t *);
diff --git a/usr/src/uts/common/smbsrv/smb_common_door.h b/usr/src/uts/common/smbsrv/smb_common_door.h
index 07ff2f1dd4..2b5ec20c1c 100644
--- a/usr/src/uts/common/smbsrv/smb_common_door.h
+++ b/usr/src/uts/common/smbsrv/smb_common_door.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -103,12 +103,14 @@ extern DWORD smb_dr_get_dword(smb_dr_ctx_t *ctx);
extern uint32_t smb_dr_get_uint32(smb_dr_ctx_t *ctx);
extern int64_t smb_dr_get_int64(smb_dr_ctx_t *ctx);
extern uint64_t smb_dr_get_uint64(smb_dr_ctx_t *ctx);
+extern unsigned short smb_dr_get_ushort(smb_dr_ctx_t *ctx);
extern void smb_dr_put_int32(smb_dr_ctx_t *ctx, int32_t num);
extern void smb_dr_put_dword(smb_dr_ctx_t *ctx, DWORD num);
extern void smb_dr_put_uint32(smb_dr_ctx_t *ctx, uint32_t num);
extern void smb_dr_put_int64(smb_dr_ctx_t *ctx, int64_t num);
extern void smb_dr_put_uint64(smb_dr_ctx_t *ctx, uint64_t num);
+extern void smb_dr_put_ushort(smb_dr_ctx_t *ctx, unsigned short num);
extern char *smb_dr_get_string(smb_dr_ctx_t *ctx);
extern void smb_dr_put_string(smb_dr_ctx_t *ctx, char *buf);
diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h
index 8f40e24590..bb675ca115 100644
--- a/usr/src/uts/common/smbsrv/smb_kproto.h
+++ b/usr/src/uts/common/smbsrv/smb_kproto.h
@@ -385,8 +385,6 @@ int smb_node_in_crit(smb_node_t *node);
uint32_t smb_node_open_check(smb_node_t *, cred_t *,
uint32_t, uint32_t);
-uint32_t smb_node_share_check(smb_node_t *, cred_t *,
- uint32_t, uint32_t, smb_ofile_t *);
DWORD smb_node_rename_check(smb_node_t *);
DWORD smb_node_delete_check(smb_node_t *);
@@ -532,6 +530,11 @@ void smb_ofile_close_all_by_pid(smb_tree_t *tree, uint16_t pid);
void smb_ofile_set_flags(smb_ofile_t *of, uint32_t flags);
void smb_ofile_close_timestamp_update(smb_ofile_t *of, uint32_t last_wtime);
boolean_t smb_ofile_is_open(smb_ofile_t *of);
+uint32_t smb_ofile_open_check(smb_ofile_t *, cred_t *,
+ uint32_t, uint32_t);
+uint32_t smb_ofile_rename_check(smb_ofile_t *);
+uint32_t smb_ofile_delete_check(smb_ofile_t *);
+
#define smb_ofile_granted_access(_of_) ((_of_)->f_granted_access)
diff --git a/usr/src/uts/common/smbsrv/smb_ktypes.h b/usr/src/uts/common/smbsrv/smb_ktypes.h
index 99748042d1..89691295d7 100644
--- a/usr/src/uts/common/smbsrv/smb_ktypes.h
+++ b/usr/src/uts/common/smbsrv/smb_ktypes.h
@@ -375,6 +375,7 @@ typedef struct {
} smb_xprt_t;
int MBC_LENGTH(struct mbuf_chain *);
+int MBC_MAXBYTES(struct mbuf_chain *);
void MBC_SETUP(struct mbuf_chain *, uint32_t);
void MBC_INIT(struct mbuf_chain *, uint32_t);
void MBC_FLUSH(struct mbuf_chain *);
diff --git a/usr/src/uts/common/smbsrv/smb_winpipe.h b/usr/src/uts/common/smbsrv/smb_winpipe.h
index 4e4f383543..906979a63e 100755
--- a/usr/src/uts/common/smbsrv/smb_winpipe.h
+++ b/usr/src/uts/common/smbsrv/smb_winpipe.h
@@ -58,6 +58,9 @@ extern "C" {
#define SMB_RPC_WRITE 3
#define SMB_RPC_FLUSH 4
+#define SMB_WINPIPE_MIN_REQ_SIZE (sizeof (uint64_t) + \
+ (2 * sizeof (uint32_t)) + (2 * sizeof (uint16_t)))
+
typedef struct {
uint64_t md_tid; /* caller's thread id */
uint16_t md_version; /* version number, start with 1 */