Print this page
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-4538 SMB1 create file should support extended_response format (2)
NEX-6116 Failures in smbtorture raw.open
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Include this commit if upstreaming/backporting any of:
NEX-4540 SMB server declines EA support incorrectly
NEX-4239 smbtorture create failures re. allocation size
(illumos) 6398 SMB should support path names longer than 1024
NEX-4538 SMB1 create file should support extended_response format
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-50 User-mode SMB server
Includes work by these authors:
Thomas Keiser <thomas.keiser@nexenta.com>
Albert Lee <trisk@nexenta.com>
SMB-63 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
re #11974 CIFS Share - Tree connect fails from Windows 7 Clients
re #14152 Race between ipmi_submit_driver_request() and kcs_loop() (sync with illumos fix 3902)
SMB-46 File handle leaks exposed by mtime fixes (rm 7815)
re #7815 SMB server delivers old modification time...
*** 18,28 ****
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
! * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
* This command is used to create or open a file or directory, when EAs
* or an SD must be applied to the file. The functionality is similar
--- 18,28 ----
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
! * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
*/
/*
* This command is used to create or open a file or directory, when EAs
* or an SD must be applied to the file. The functionality is similar
*** 34,43 ****
--- 34,45 ----
*/
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_fsops.h>
+ extern int smb_nt_create_enable_extended_response;
+
/*
* smb_nt_transact_create
*
* This command is used to create or open a file or directory, when EAs
* or an SD must be applied to the file. The request parameter block
*** 81,93 ****
&SecurityFlags);
if (rc == 0) {
if (NameLength == 0) {
op->fqi.fq_path.pn_path = "\\";
! } else if (NameLength >= MAXPATHLEN) {
! smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND,
! ERRDOS, ERROR_PATH_NOT_FOUND);
rc = -1;
} else {
rc = smb_mbc_decodef(&xa->req_param_mb, "%#u",
sr, NameLength, &op->fqi.fq_path.pn_path);
}
--- 83,95 ----
&SecurityFlags);
if (rc == 0) {
if (NameLength == 0) {
op->fqi.fq_path.pn_path = "\\";
! } else if (NameLength >= SMB_MAXPATHLEN) {
! smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
! ERRDOS, ERROR_INVALID_NAME);
rc = -1;
} else {
rc = smb_mbc_decodef(&xa->req_param_mb, "%#u",
sr, NameLength, &op->fqi.fq_path.pn_path);
}
*** 111,153 ****
*op->sd = sd;
} else {
op->sd = NULL;
}
! DTRACE_SMB_2(op__NtTransactCreate__start, smb_request_t *, sr,
! struct open_param *, op);
return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
void
smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
{
smb_sd_t *sd = sr->arg.open.sd;
! DTRACE_SMB_2(op__NtTransactCreate__done, smb_request_t *, sr,
! smb_xa_t *, xa);
if (sd) {
smb_sd_term(sd);
kmem_free(sd, sizeof (smb_sd_t));
}
! if (sr->arg.open.dir != NULL)
smb_ofile_release(sr->arg.open.dir);
}
smb_sdrc_t
smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
{
struct open_param *op = &sr->arg.open;
! uint8_t DirFlag;
! smb_attr_t attr;
smb_ofile_t *of;
- uint32_t status;
int rc;
if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
!(op->desired_access & DELETE)) {
smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
ERRDOS, ERRbadaccess);
return (SDRC_ERROR);
--- 113,171 ----
*op->sd = sd;
} else {
op->sd = NULL;
}
! DTRACE_SMB_START(op__NtTransactCreate, smb_request_t *, sr);
return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
void
smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
{
smb_sd_t *sd = sr->arg.open.sd;
+ _NOTE(ARGUNUSED(xa))
! DTRACE_SMB_DONE(op__NtTransactCreate, smb_request_t *, sr);
if (sd) {
smb_sd_term(sd);
kmem_free(sd, sizeof (smb_sd_t));
}
! if (sr->arg.open.dir != NULL) {
smb_ofile_release(sr->arg.open.dir);
+ sr->arg.open.dir = NULL;
+ }
}
+ /*
+ * A lot like smb_com_nt_create_andx
+ */
smb_sdrc_t
smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
{
struct open_param *op = &sr->arg.open;
! smb_attr_t *ap = &op->fqi.fq_fattr;
smb_ofile_t *of;
int rc;
+ uint8_t DirFlag;
+ uint32_t status;
+ if (op->create_options & ~SMB_NTCREATE_VALID_OPTIONS) {
+ smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
+ ERRDOS, ERROR_INVALID_PARAMETER);
+ return (SDRC_ERROR);
+ }
+
+ if (op->create_options & FILE_OPEN_BY_FILE_ID) {
+ smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
+ ERRDOS, ERROR_NOT_SUPPORTED);
+ return (SDRC_ERROR);
+ }
+
if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
!(op->desired_access & DELETE)) {
smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
ERRDOS, ERRbadaccess);
return (SDRC_ERROR);
*** 181,197 ****
return (SDRC_ERROR);
}
op->fqi.fq_dnode = op->dir->f_node;
}
- op->op_oplock_levelII = B_TRUE;
-
status = smb_common_open(sr);
if (status != NT_STATUS_SUCCESS) {
smbsr_status(sr, status, 0, 0);
return (SDRC_ERROR);
}
/*
* NB: after the above smb_common_open() success,
* we have a handle allocated (sr->fid_ofile).
* If we don't return success, we must close it.
--- 199,217 ----
return (SDRC_ERROR);
}
op->fqi.fq_dnode = op->dir->f_node;
}
status = smb_common_open(sr);
if (status != NT_STATUS_SUCCESS) {
smbsr_status(sr, status, 0, 0);
return (SDRC_ERROR);
}
+ if (op->op_oplock_level != SMB_OPLOCK_NONE) {
+ /* Oplock req. in op->op_oplock_level etc. */
+ smb1_oplock_acquire(sr, B_TRUE);
+ }
/*
* NB: after the above smb_common_open() success,
* we have a handle allocated (sr->fid_ofile).
* If we don't return success, we must close it.
*** 200,261 ****
switch (sr->tid_tree->t_res_type & STYPE_MASK) {
case STYPE_DISKTREE:
case STYPE_PRINTQ:
if (op->create_options & FILE_DELETE_ON_CLOSE)
! smb_ofile_set_delete_on_close(of);
!
DirFlag = smb_node_is_dir(of->f_node) ? 1 : 0;
- bzero(&attr, sizeof (attr));
- attr.sa_mask = SMB_AT_ALL;
- rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr);
- if (rc != 0) {
- smbsr_errno(sr, rc);
- goto errout;
- }
-
- rc = smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb",
- op->op_oplock_level,
- sr->smb_fid,
- op->action_taken,
- 0, /* EaErrorOffset */
- &attr.sa_crtime,
- &attr.sa_vattr.va_atime,
- &attr.sa_vattr.va_mtime,
- &attr.sa_vattr.va_ctime,
- op->dattr & FILE_ATTRIBUTE_MASK,
- attr.sa_allocsz,
- attr.sa_vattr.va_size,
- op->ftype,
- op->devstate,
- DirFlag);
break;
case STYPE_IPC:
! bzero(&attr, sizeof (smb_attr_t));
! rc = smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb",
! 0,
! sr->smb_fid,
! op->action_taken,
! 0, /* EaErrorOffset */
! &attr.sa_crtime,
! &attr.sa_vattr.va_atime,
! &attr.sa_vattr.va_mtime,
! &attr.sa_vattr.va_ctime,
! op->dattr,
! 0x1000LL,
! 0LL,
! op->ftype,
! op->devstate,
! 0);
break;
default:
smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
ERRDOS, ERROR_INVALID_FUNCTION);
goto errout;
}
return (SDRC_SUCCESS);
errout:
smb_ofile_close(of, 0);
return (SDRC_ERROR);
--- 220,293 ----
switch (sr->tid_tree->t_res_type & STYPE_MASK) {
case STYPE_DISKTREE:
case STYPE_PRINTQ:
if (op->create_options & FILE_DELETE_ON_CLOSE)
! smb_ofile_set_delete_on_close(sr, of);
DirFlag = smb_node_is_dir(of->f_node) ? 1 : 0;
break;
case STYPE_IPC:
! DirFlag = 0;
break;
default:
smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
ERRDOS, ERROR_INVALID_FUNCTION);
goto errout;
}
+
+ if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 &&
+ smb_nt_create_enable_extended_response != 0) {
+ uint32_t MaxAccess = 0;
+ if (of->f_node != NULL) {
+ smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess);
+ }
+ MaxAccess |= of->f_granted_access;
+
+ rc = smb_mbc_encodef(
+ &xa->rep_param_mb, "bbwllTTTTlqqwwb16.qll",
+ op->op_oplock_level, /* (b) */
+ 1, /* ResponseType (b) */
+ sr->smb_fid, /* (w) */
+ op->action_taken, /* (l) */
+ 0, /* EaErrorOffset (l) */
+ &ap->sa_crtime, /* (T) */
+ &ap->sa_vattr.va_atime, /* (T) */
+ &ap->sa_vattr.va_mtime, /* (T) */
+ &ap->sa_vattr.va_ctime, /* (T) */
+ op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */
+ ap->sa_allocsz, /* (q) */
+ ap->sa_vattr.va_size, /* (q) */
+ op->ftype, /* (w) */
+ op->devstate, /* (w) */
+ DirFlag, /* (b) */
+ /* volume guid (16.) */
+ op->fileid, /* (q) */
+ MaxAccess, /* (l) */
+ 0); /* guest access (l) */
+ } else {
+ rc = smb_mbc_encodef(
+ &xa->rep_param_mb, "bbwllTTTTlqqwwb",
+ op->op_oplock_level, /* (b) */
+ 0, /* ResponseType (b) */
+ sr->smb_fid, /* (w) */
+ op->action_taken, /* (l) */
+ 0, /* EaErrorOffset (l) */
+ &ap->sa_crtime, /* (T) */
+ &ap->sa_vattr.va_atime, /* (T) */
+ &ap->sa_vattr.va_mtime, /* (T) */
+ &ap->sa_vattr.va_ctime, /* (T) */
+ op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */
+ ap->sa_allocsz, /* (q) */
+ ap->sa_vattr.va_size, /* (q) */
+ op->ftype, /* (w) */
+ op->devstate, /* (w) */
+ DirFlag); /* (b) */
+ }
+
+ if (rc == 0)
return (SDRC_SUCCESS);
errout:
smb_ofile_close(of, 0);
return (SDRC_ERROR);