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-5311 SMB1 Create_Temp should return an untagged ASCII string
Reviewed by: Gordon Ross <gwr@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)


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <smbsrv/smb_kproto.h>
  27 
  28 #define SMB_CREATE_NAMEBUF_SZ   16
  29 
  30 /*
  31  * Create a new file, or truncate an existing file to zero length,
  32  * open the file and return a fid.  The file is specified using a
  33  * fully qualified name relative to the tree.
  34  */
  35 smb_sdrc_t
  36 smb_pre_create(smb_request_t *sr)
  37 {
  38         struct open_param *op = &sr->arg.open;
  39         int rc;
  40 
  41         bzero(op, sizeof (sr->arg.open));
  42 
  43         rc = smbsr_decode_vwv(sr, "wl", &op->dattr, &op->mtime.tv_sec);
  44         if (rc == 0)
  45                 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);
  46 
  47         op->create_disposition = FILE_OVERWRITE_IF;
  48         op->create_options = FILE_NON_DIRECTORY_FILE;
  49 
  50         DTRACE_SMB_2(op__Create__start, smb_request_t *, sr,
  51             struct open_param *, op);
  52 
  53         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
  54 }
  55 
  56 void
  57 smb_post_create(smb_request_t *sr)
  58 {
  59         DTRACE_SMB_1(op__Create__done, smb_request_t *, sr);
  60 }
  61 
  62 smb_sdrc_t
  63 smb_com_create(smb_request_t *sr)
  64 {
  65         if (smb_common_create(sr) != NT_STATUS_SUCCESS)
  66                 return (SDRC_ERROR);
  67 
  68         if (smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0))
  69                 return (SDRC_ERROR);
  70 
  71         return (SDRC_SUCCESS);
  72 }
  73 
  74 /*
  75  * Create a new file and return a fid.  The file is specified using
  76  * a fully qualified name relative to the tree.
  77  */
  78 smb_sdrc_t
  79 smb_pre_create_new(smb_request_t *sr)
  80 {
  81         struct open_param *op = &sr->arg.open;
  82         int rc;
  83 
  84         bzero(op, sizeof (sr->arg.open));
  85 
  86         rc = smbsr_decode_vwv(sr, "wl", &op->dattr, &op->mtime.tv_sec);
  87         if (rc == 0)
  88                 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);
  89 
  90         op->create_disposition = FILE_CREATE;
  91 
  92         DTRACE_SMB_2(op__CreateNew__start, smb_request_t *, sr,
  93             struct open_param *, op);
  94 
  95         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
  96 }
  97 
  98 void
  99 smb_post_create_new(smb_request_t *sr)
 100 {
 101         DTRACE_SMB_1(op__CreateNew__done, smb_request_t *, sr);
 102 }
 103 
 104 smb_sdrc_t
 105 smb_com_create_new(smb_request_t *sr)
 106 {
 107         if (smb_common_create(sr) != NT_STATUS_SUCCESS)
 108                 return (SDRC_ERROR);
 109 
 110         if (smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0))
 111                 return (SDRC_ERROR);
 112 
 113         return (SDRC_SUCCESS);
 114 }
 115 
 116 /*
 117  * Create a unique file in the specified directory relative to the
 118  * current tree.  No attributes are specified.
 119  */
 120 smb_sdrc_t
 121 smb_pre_create_temporary(smb_request_t *sr)
 122 {
 123         struct open_param *op = &sr->arg.open;
 124         uint16_t reserved;
 125         int rc;
 126 
 127         bzero(op, sizeof (sr->arg.open));
 128 
 129         rc = smbsr_decode_vwv(sr, "wl", &reserved, &op->mtime.tv_sec);
 130         if (rc == 0)
 131                 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);
 132 
 133         op->create_disposition = FILE_CREATE;
 134 
 135         DTRACE_SMB_2(op__CreateTemporary__start, smb_request_t *, sr,
 136             struct open_param *, op);
 137 
 138         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 139 }
 140 
 141 void
 142 smb_post_create_temporary(smb_request_t *sr)
 143 {
 144         DTRACE_SMB_1(op__CreateTemporary__done, smb_request_t *, sr);
 145 }
 146 
 147 smb_sdrc_t
 148 smb_com_create_temporary(smb_request_t *sr)
 149 {
 150         static uint16_t tmp_id = 10000;
 151         struct open_param *op = &sr->arg.open;
 152         char name[SMB_CREATE_NAMEBUF_SZ];
 153         char *buf;
 154         uint16_t bcc;
 155 
 156         ++tmp_id;
 157         bcc = 1; /* null terminator */
 158         bcc += snprintf(name, SMB_CREATE_NAMEBUF_SZ, "tt%05d.tmp", tmp_id);
 159 
 160         buf = smb_srm_zalloc(sr, MAXPATHLEN);
 161         (void) snprintf(buf, MAXPATHLEN, "%s\\%s",
 162             op->fqi.fq_path.pn_path, name);
 163         op->fqi.fq_path.pn_path = buf;
 164 
 165         if (smb_common_create(sr) != NT_STATUS_SUCCESS)
 166                 return (SDRC_ERROR);
 167 
 168         if (smbsr_encode_result(sr, 1, VAR_BCC, "bww%S", 1, sr->smb_fid,
 169             VAR_BCC, sr, name))
 170                 return (SDRC_ERROR);
 171 
 172         return (SDRC_SUCCESS);
 173 }
 174 
 175 /*
 176  * Common create file function.  The file is opened in compatibility
 177  * mode with read/write access.
 178  */
 179 uint32_t
 180 smb_common_create(smb_request_t *sr)
 181 {
 182         struct open_param *op = &sr->arg.open;
 183         uint32_t status;
 184 
 185         if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX))
 186                 op->mtime.tv_sec = smb_time_local_to_gmt(sr, op->mtime.tv_sec);
 187         op->mtime.tv_nsec = 0;
 188         op->dsize = 0;
 189         op->omode = SMB_DA_ACCESS_READ_WRITE | SMB_DA_SHARE_COMPATIBILITY;
 190         op->desired_access = smb_omode_to_amask(op->omode);
 191         op->share_access = smb_denymode_to_sharemode(op->omode,
 192             op->fqi.fq_path.pn_path);
 193 
 194         if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
 195                 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
 196                         op->op_oplock_level = SMB_OPLOCK_BATCH;
 197                 else
 198                         op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
 199         } else {
 200                 op->op_oplock_level = SMB_OPLOCK_NONE;
 201         }
 202         op->op_oplock_levelII = B_FALSE;
 203 
 204         status = smb_common_open(sr);




 205 
 206         if (op->op_oplock_level == SMB_OPLOCK_NONE) {
 207                 sr->smb_flg &=
 208                     ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY);
 209         }
 210 
 211         if (status)
 212                 smbsr_status(sr, status, 0, 0);
 213 
 214         return (status);
 215 }


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <smbsrv/smb_kproto.h>
  27 
  28 #define SMB_CREATE_NAMEBUF_SZ   16
  29 
  30 /*
  31  * Create a new file, or truncate an existing file to zero length,
  32  * open the file and return a fid.  The file is specified using a
  33  * fully qualified name relative to the tree.
  34  */
  35 smb_sdrc_t
  36 smb_pre_create(smb_request_t *sr)
  37 {
  38         struct open_param *op = &sr->arg.open;
  39         int rc;
  40 
  41         bzero(op, sizeof (sr->arg.open));
  42 
  43         rc = smbsr_decode_vwv(sr, "wl", &op->dattr, &op->mtime.tv_sec);
  44         if (rc == 0)
  45                 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);
  46 
  47         op->create_disposition = FILE_OVERWRITE_IF;
  48         op->create_options = FILE_NON_DIRECTORY_FILE;
  49 
  50         DTRACE_SMB_START(op__Create, smb_request_t *, sr); /* arg.open */

  51 
  52         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
  53 }
  54 
  55 void
  56 smb_post_create(smb_request_t *sr)
  57 {
  58         DTRACE_SMB_DONE(op__Create, smb_request_t *, sr);
  59 }
  60 
  61 smb_sdrc_t
  62 smb_com_create(smb_request_t *sr)
  63 {
  64         if (smb_common_create(sr) != NT_STATUS_SUCCESS)
  65                 return (SDRC_ERROR);
  66 
  67         if (smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0))
  68                 return (SDRC_ERROR);
  69 
  70         return (SDRC_SUCCESS);
  71 }
  72 
  73 /*
  74  * Create a new file and return a fid.  The file is specified using
  75  * a fully qualified name relative to the tree.
  76  */
  77 smb_sdrc_t
  78 smb_pre_create_new(smb_request_t *sr)
  79 {
  80         struct open_param *op = &sr->arg.open;
  81         int rc;
  82 
  83         bzero(op, sizeof (sr->arg.open));
  84 
  85         rc = smbsr_decode_vwv(sr, "wl", &op->dattr, &op->mtime.tv_sec);
  86         if (rc == 0)
  87                 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);
  88 
  89         op->create_disposition = FILE_CREATE;
  90 
  91         DTRACE_SMB_START(op__CreateNew, smb_request_t *, sr); /* arg.open */

  92 
  93         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
  94 }
  95 
  96 void
  97 smb_post_create_new(smb_request_t *sr)
  98 {
  99         DTRACE_SMB_DONE(op__CreateNew, smb_request_t *, sr);
 100 }
 101 
 102 smb_sdrc_t
 103 smb_com_create_new(smb_request_t *sr)
 104 {
 105         if (smb_common_create(sr) != NT_STATUS_SUCCESS)
 106                 return (SDRC_ERROR);
 107 
 108         if (smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0))
 109                 return (SDRC_ERROR);
 110 
 111         return (SDRC_SUCCESS);
 112 }
 113 
 114 /*
 115  * Create a unique file in the specified directory relative to the
 116  * current tree.  No attributes are specified.
 117  */
 118 smb_sdrc_t
 119 smb_pre_create_temporary(smb_request_t *sr)
 120 {
 121         struct open_param *op = &sr->arg.open;
 122         uint16_t reserved;
 123         int rc;
 124 
 125         bzero(op, sizeof (sr->arg.open));
 126 
 127         rc = smbsr_decode_vwv(sr, "wl", &reserved, &op->mtime.tv_sec);
 128         if (rc == 0)
 129                 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);
 130 
 131         op->create_disposition = FILE_CREATE;
 132 
 133         DTRACE_SMB_START(op__CreateTemporary, smb_request_t *, sr);

 134 
 135         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 136 }
 137 
 138 void
 139 smb_post_create_temporary(smb_request_t *sr)
 140 {
 141         DTRACE_SMB_DONE(op__CreateTemporary, smb_request_t *, sr);
 142 }
 143 
 144 smb_sdrc_t
 145 smb_com_create_temporary(smb_request_t *sr)
 146 {
 147         static uint16_t tmp_id = 10000;
 148         struct open_param *op = &sr->arg.open;
 149         char name[SMB_CREATE_NAMEBUF_SZ];
 150         char *buf;
 151         uint16_t bcc;
 152 
 153         ++tmp_id;
 154         bcc = 1; /* null terminator */
 155         bcc += snprintf(name, SMB_CREATE_NAMEBUF_SZ, "tt%05d.tmp", tmp_id);
 156 
 157         buf = smb_srm_zalloc(sr, MAXPATHLEN);
 158         (void) snprintf(buf, MAXPATHLEN, "%s\\%s",
 159             op->fqi.fq_path.pn_path, name);
 160         op->fqi.fq_path.pn_path = buf;
 161 
 162         if (smb_common_create(sr) != NT_STATUS_SUCCESS)
 163                 return (SDRC_ERROR);
 164 
 165         if (smbsr_encode_result(sr, 1, VAR_BCC, "bww%s", 1, sr->smb_fid,
 166             VAR_BCC, sr, name))
 167                 return (SDRC_ERROR);
 168 
 169         return (SDRC_SUCCESS);
 170 }
 171 
 172 /*
 173  * Common create file function.  The file is opened in compatibility
 174  * mode with read/write access.
 175  */
 176 uint32_t
 177 smb_common_create(smb_request_t *sr)
 178 {
 179         struct open_param *op = &sr->arg.open;
 180         uint32_t status;
 181 
 182         if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX))
 183                 op->mtime.tv_sec = smb_time_local_to_gmt(sr, op->mtime.tv_sec);
 184         op->mtime.tv_nsec = 0;
 185         op->dsize = 0;
 186         op->omode = SMB_DA_ACCESS_READ_WRITE | SMB_DA_SHARE_COMPATIBILITY;
 187         op->desired_access = smb_omode_to_amask(op->omode);
 188         op->share_access = smb_denymode_to_sharemode(op->omode,
 189             op->fqi.fq_path.pn_path);
 190 
 191         if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
 192                 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
 193                         op->op_oplock_level = SMB_OPLOCK_BATCH;
 194                 else
 195                         op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
 196         } else {
 197                 op->op_oplock_level = SMB_OPLOCK_NONE;
 198         }

 199 
 200         status = smb_common_open(sr);
 201         if (status == 0 && op->op_oplock_level != SMB_OPLOCK_NONE) {
 202                 /* Oplock req. in op->op_oplock_level etc. */
 203                 smb1_oplock_acquire(sr, B_FALSE);
 204         }
 205 
 206         if (op->op_oplock_level == SMB_OPLOCK_NONE) {
 207                 sr->smb_flg &=
 208                     ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY);
 209         }
 210 
 211         if (status)
 212                 smbsr_status(sr, status, 0, 0);
 213 
 214         return (status);
 215 }