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,11 +18,11 @@
  *
  * CDDL HEADER END
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc.  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,10 +34,12 @@
  */
 
 #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,13 +83,13 @@
             &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);
+                } 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,43 +113,59 @@
                 *op->sd = sd;
         } else {
                 op->sd = NULL;
         }
 
-        DTRACE_SMB_2(op__NtTransactCreate__start, smb_request_t *, sr,
-            struct open_param *, op);
+        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_2(op__NtTransactCreate__done, smb_request_t *, sr,
-            smb_xa_t *, 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)
+        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;
-        uint8_t                 DirFlag;
-        smb_attr_t              attr;
+        smb_attr_t              *ap = &op->fqi.fq_fattr;
         smb_ofile_t             *of;
-        uint32_t                status;
         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,17 +199,19 @@
                         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);
         }
+        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,62 +220,74 @@
 
         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);
-
+                        smb_ofile_set_delete_on_close(sr, 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);
+                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);