Print this page
NEX-17289 Minimal SMB 3.0.2 support
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@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-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-5844 want SMB2 ioctl FSCTL_SRV_COPYCHUNK
NEX-6124 smb_fsop_read/write should allow file != sr->fid_ofile
NEX-6125 smbtorture invalid response with smb2.ioctl
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-6041 Should pass the smbtorture lock tests
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-3662 Backport illumos 1501: taskq_create_proc ... TQ_DYNAMIC puts tasks in p0 (take 2)
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
NEX-3576 RPC error when displaying open files via Windows MMC
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-2188 Browsing top level share produces RPC error 1728
SMB-69 read-raw, write-raw are dead code
SMB-39 Use AF_UNIX pipes for RPC


   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 2015 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <smbsrv/smb_kproto.h>
  27 #include <smbsrv/smb_fsops.h>
  28 
  29 /*
  30  * The maximum number of bytes to return from SMB Core
  31  * SmbRead or SmbLockAndRead.
  32  */
  33 #define SMB_CORE_READ_MAX       4432
  34 
  35 /*
  36  * The limit in bytes for SmbReadX.
  37  */
  38 #define SMB_READX_MAX           0x10000
  39 
  40 int smb_common_read(smb_request_t *, smb_rw_param_t *);
  41 
  42 /*
  43  * Read bytes from a file or named pipe (SMB Core).


  56  */
  57 smb_sdrc_t
  58 smb_pre_read(smb_request_t *sr)
  59 {
  60         smb_rw_param_t *param;
  61         uint32_t off_low;
  62         uint16_t count;
  63         uint16_t remcnt;
  64         int rc;
  65 
  66         param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
  67         sr->arg.rw = param;
  68 
  69         rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
  70             &count, &off_low, &remcnt);
  71 
  72         param->rw_offset = (uint64_t)off_low;
  73         param->rw_count = (uint32_t)count;
  74         param->rw_mincnt = 0;
  75 
  76         DTRACE_SMB_2(op__Read__start, smb_request_t *, sr,
  77             smb_rw_param_t *, param);
  78 
  79         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
  80 }
  81 
  82 void
  83 smb_post_read(smb_request_t *sr)
  84 {
  85         DTRACE_SMB_2(op__Read__done, smb_request_t *, sr,
  86             smb_rw_param_t *, sr->arg.rw);
  87 
  88         kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
  89 }
  90 
  91 smb_sdrc_t
  92 smb_com_read(smb_request_t *sr)
  93 {
  94         smb_rw_param_t *param = sr->arg.rw;
  95         uint16_t count;
  96         int rc;
  97 
  98         smbsr_lookup_file(sr);
  99         if (sr->fid_ofile == NULL) {
 100                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
 101                 return (SDRC_ERROR);
 102         }
 103 
 104         sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
 105 
 106         if (param->rw_count > SMB_CORE_READ_MAX)


 142  */
 143 smb_sdrc_t
 144 smb_pre_lock_and_read(smb_request_t *sr)
 145 {
 146         smb_rw_param_t *param;
 147         uint32_t off_low;
 148         uint16_t count;
 149         uint16_t remcnt;
 150         int rc;
 151 
 152         param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
 153         sr->arg.rw = param;
 154 
 155         rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
 156             &count, &off_low, &remcnt);
 157 
 158         param->rw_offset = (uint64_t)off_low;
 159         param->rw_count = (uint32_t)count;
 160         param->rw_mincnt = 0;
 161 
 162         DTRACE_SMB_2(op__LockAndRead__start, smb_request_t *, sr,
 163             smb_rw_param_t *, param);
 164 
 165         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 166 }
 167 
 168 void
 169 smb_post_lock_and_read(smb_request_t *sr)
 170 {
 171         DTRACE_SMB_2(op__LockAndRead__done, smb_request_t *, sr,
 172             smb_rw_param_t *, sr->arg.rw);
 173 
 174         kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
 175 }
 176 
 177 smb_sdrc_t
 178 smb_com_lock_and_read(smb_request_t *sr)
 179 {
 180         smb_rw_param_t *param = sr->arg.rw;
 181         DWORD status;

 182         uint16_t count;
 183         int rc;
 184 
 185         if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
 186                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
 187                 return (SDRC_ERROR);
 188         }
 189 
 190         smbsr_lookup_file(sr);
 191         if (sr->fid_ofile == NULL) {
 192                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
 193                 return (SDRC_ERROR);
 194         }
 195 
 196         sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
 197 



 198         status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count,
 199             0, SMB_LOCK_TYPE_READWRITE);
 200 
 201         if (status != NT_STATUS_SUCCESS) {
 202                 smb_lock_range_error(sr, status);
 203                 return (SDRC_ERROR);
 204         }
 205 
 206         if (param->rw_count > SMB_CORE_READ_MAX)
 207                 param->rw_count = SMB_CORE_READ_MAX;
 208 
 209         if ((rc = smb_common_read(sr, param)) != 0) {
 210                 smbsr_errno(sr, rc);
 211                 return (SDRC_ERROR);
 212         }
 213 
 214         count = (uint16_t)param->rw_count;
 215         rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
 216             5, count, VAR_BCC, 0x1, count, &sr->raw_data);
 217 
 218         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 219 }
 220 
 221 /*





























 222  * Read bytes from a file (SMB Core).  This request was extended in
 223  * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
 224  * 12 and including additional offset information.
 225  *
 226  * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4:
 227  * If wct is 12 and CAP_LARGE_READX is set, the count may be larger
 228  * than the negotiated buffer size.  If maxcnt_high is 0xFF, it must
 229  * be ignored.  Otherwise, maxcnt_high represents the upper 16 bits
 230  * of rw_count.
 231  */
 232 smb_sdrc_t
 233 smb_pre_read_andx(smb_request_t *sr)
 234 {
 235         smb_rw_param_t *param;
 236         uint32_t off_low;
 237         uint32_t off_high;
 238         uint32_t maxcnt_high;
 239         uint16_t maxcnt_low;
 240         uint16_t mincnt;
 241         uint16_t remcnt;


 251 
 252                 param->rw_offset = ((uint64_t)off_high << 32) |
 253                     (uint64_t)off_low;
 254 
 255                 param->rw_count = (uint32_t)maxcnt_low;
 256 
 257                 if ((sr->session->capabilities & CAP_LARGE_READX) &&
 258                     (maxcnt_high < 0xFF))
 259                         param->rw_count |= maxcnt_high << 16;
 260         } else {
 261                 rc = smbsr_decode_vwv(sr, "b3.wlwwlw", &param->rw_andx,
 262                     &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
 263                     &remcnt);
 264 
 265                 param->rw_offset = (uint64_t)off_low;
 266                 param->rw_count = (uint32_t)maxcnt_low;
 267         }
 268 
 269         param->rw_mincnt = 0;
 270 
 271         DTRACE_SMB_2(op__ReadX__start, smb_request_t *, sr,
 272             smb_rw_param_t *, param);
 273 
 274         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 275 }
 276 
 277 void
 278 smb_post_read_andx(smb_request_t *sr)
 279 {
 280         DTRACE_SMB_2(op__ReadX__done, smb_request_t *, sr,
 281             smb_rw_param_t *, sr->arg.rw);
 282 
 283         kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
 284 }
 285 
 286 smb_sdrc_t
 287 smb_com_read_andx(smb_request_t *sr)
 288 {
 289         smb_rw_param_t *param = sr->arg.rw;
 290         uint16_t datalen_high;
 291         uint16_t datalen_low;
 292         uint16_t data_offset;
 293         uint16_t offset2;
 294         int rc;
 295 
 296         smbsr_lookup_file(sr);
 297         if (sr->fid_ofile == NULL) {
 298                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
 299                 return (SDRC_ERROR);
 300         }
 301 


 341                     12,                 /* wct */
 342                     param->rw_andx,  /* secondary andx command */
 343                     offset2,            /* offset to next command */
 344                     -1,                 /* must be -1 for regular files */
 345                     datalen_low,        /* data byte count */
 346                     data_offset,        /* offset from start to data */
 347                     datalen_high,       /* data byte count */
 348                     VAR_BCC,            /* BCC marker */
 349                     &sr->raw_data);
 350         }
 351 
 352         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 353 }
 354 
 355 /*
 356  * Common function for reading files or IPC/MSRPC named pipes.  All
 357  * protocol read functions should lookup the fid before calling this
 358  * function.  We can't move the fid lookup here because lock-and-read
 359  * requires the fid to do locking before attempting the read.
 360  *
 361  * Reading from a file should break oplocks on the file to LEVEL_II.
 362  * A call to smb_oplock_break(SMB_OPLOCK_BREAK_TO_LEVEL_II) is not
 363  * required as it is a no-op. If there's anything greater than a
 364  * LEVEL_II oplock on the file, the oplock MUST be owned by the ofile
 365  * on which the read is occuring and therefore would not be broken.
 366  *
 367  * Returns errno values.
 368  */
 369 int
 370 smb_common_read(smb_request_t *sr, smb_rw_param_t *param)
 371 {
 372         smb_ofile_t *ofile = sr->fid_ofile;
 373         smb_node_t *node;
 374         smb_vdb_t *vdb = &param->rw_vdb;
 375         struct mbuf *top;
 376         int rc;
 377 
 378         vdb->vdb_tag = 0;
 379         vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
 380         vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
 381         vdb->vdb_uio.uio_resid = param->rw_count;
 382         vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset;
 383         vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
 384         vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
 385 


 396                         }
 397                 }
 398 
 399                 if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) &&
 400                     !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) {
 401                         /*
 402                          * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only
 403                          * reads.
 404                          *
 405                          * Reject request if the file has been opened
 406                          * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not
 407                          * set.
 408                          */
 409                         rc = EACCES;
 410                         break;
 411                 }
 412 
 413                 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
 414                 top = smb_mbuf_allocate(&vdb->vdb_uio);
 415 
 416                 rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->vdb_uio);

 417 
 418                 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
 419                 smb_mbuf_trim(top, sr->raw_data.max_bytes);
 420                 MBC_ATTACH_MBUF(&sr->raw_data, top);
 421                 break;
 422 
 423         case STYPE_IPC:
 424                 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
 425                 top = smb_mbuf_allocate(&vdb->vdb_uio);
 426 
 427                 rc = smb_opipe_read(sr, &vdb->vdb_uio);
 428 
 429                 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
 430                 smb_mbuf_trim(top, sr->raw_data.max_bytes);
 431                 MBC_ATTACH_MBUF(&sr->raw_data, top);
 432                 break;
 433 
 434         default:
 435                 rc = EACCES;
 436                 break;




   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 2018 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <smbsrv/smb_kproto.h>
  27 #include <smbsrv/smb_fsops.h>
  28 
  29 /*
  30  * The maximum number of bytes to return from SMB Core
  31  * SmbRead or SmbLockAndRead.
  32  */
  33 #define SMB_CORE_READ_MAX       4432
  34 
  35 /*
  36  * The limit in bytes for SmbReadX.
  37  */
  38 #define SMB_READX_MAX           0x10000
  39 
  40 int smb_common_read(smb_request_t *, smb_rw_param_t *);
  41 
  42 /*
  43  * Read bytes from a file or named pipe (SMB Core).


  56  */
  57 smb_sdrc_t
  58 smb_pre_read(smb_request_t *sr)
  59 {
  60         smb_rw_param_t *param;
  61         uint32_t off_low;
  62         uint16_t count;
  63         uint16_t remcnt;
  64         int rc;
  65 
  66         param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
  67         sr->arg.rw = param;
  68 
  69         rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
  70             &count, &off_low, &remcnt);
  71 
  72         param->rw_offset = (uint64_t)off_low;
  73         param->rw_count = (uint32_t)count;
  74         param->rw_mincnt = 0;
  75 
  76         DTRACE_SMB_START(op__Read, smb_request_t *, sr); /* arg.rw */

  77 
  78         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
  79 }
  80 
  81 void
  82 smb_post_read(smb_request_t *sr)
  83 {
  84         DTRACE_SMB_DONE(op__Read, smb_request_t *, sr); /* arg.rw */

  85 
  86         kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
  87 }
  88 
  89 smb_sdrc_t
  90 smb_com_read(smb_request_t *sr)
  91 {
  92         smb_rw_param_t *param = sr->arg.rw;
  93         uint16_t count;
  94         int rc;
  95 
  96         smbsr_lookup_file(sr);
  97         if (sr->fid_ofile == NULL) {
  98                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
  99                 return (SDRC_ERROR);
 100         }
 101 
 102         sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
 103 
 104         if (param->rw_count > SMB_CORE_READ_MAX)


 140  */
 141 smb_sdrc_t
 142 smb_pre_lock_and_read(smb_request_t *sr)
 143 {
 144         smb_rw_param_t *param;
 145         uint32_t off_low;
 146         uint16_t count;
 147         uint16_t remcnt;
 148         int rc;
 149 
 150         param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
 151         sr->arg.rw = param;
 152 
 153         rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
 154             &count, &off_low, &remcnt);
 155 
 156         param->rw_offset = (uint64_t)off_low;
 157         param->rw_count = (uint32_t)count;
 158         param->rw_mincnt = 0;
 159 
 160         DTRACE_SMB_START(op__LockAndRead, smb_request_t *, sr); /* arg.rw */

 161 
 162         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 163 }
 164 
 165 void
 166 smb_post_lock_and_read(smb_request_t *sr)
 167 {
 168         DTRACE_SMB_DONE(op__LockAndRead, smb_request_t *, sr); /* arg.rw */

 169 
 170         kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
 171 }
 172 
 173 smb_sdrc_t
 174 smb_com_lock_and_read(smb_request_t *sr)
 175 {
 176         smb_rw_param_t *param = sr->arg.rw;
 177         DWORD status;
 178         uint32_t lk_pid;
 179         uint16_t count;
 180         int rc;
 181 
 182         if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
 183                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
 184                 return (SDRC_ERROR);
 185         }
 186 
 187         smbsr_lookup_file(sr);
 188         if (sr->fid_ofile == NULL) {
 189                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
 190                 return (SDRC_ERROR);
 191         }
 192 
 193         sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
 194 
 195         /* Note: SMB1 locking uses 16-bit PIDs. */
 196         lk_pid = sr->smb_pid & 0xFFFF;
 197 
 198         status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count,
 199             lk_pid, SMB_LOCK_TYPE_READWRITE, 0);
 200 
 201         if (status != NT_STATUS_SUCCESS) {
 202                 smb_lock_range_error(sr, status);
 203                 return (SDRC_ERROR);
 204         }
 205 
 206         if (param->rw_count > SMB_CORE_READ_MAX)
 207                 param->rw_count = SMB_CORE_READ_MAX;
 208 
 209         if ((rc = smb_common_read(sr, param)) != 0) {
 210                 smbsr_errno(sr, rc);
 211                 return (SDRC_ERROR);
 212         }
 213 
 214         count = (uint16_t)param->rw_count;
 215         rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
 216             5, count, VAR_BCC, 0x1, count, &sr->raw_data);
 217 
 218         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 219 }
 220 
 221 /*
 222  * The SMB_COM_READ_RAW protocol was a negotiated option introduced in
 223  * SMB Core Plus to maximize performance when reading a large block
 224  * of data from a server.  It's obsolete and no longer supported.
 225  *
 226  * We keep a handler for it so the dtrace provider can see if
 227  * the client tried to use this command.
 228  */
 229 smb_sdrc_t
 230 smb_pre_read_raw(smb_request_t *sr)
 231 {
 232         DTRACE_SMB_START(op__ReadRaw, smb_request_t *, sr);
 233         return (SDRC_SUCCESS);
 234 }
 235 
 236 void
 237 smb_post_read_raw(smb_request_t *sr)
 238 {
 239         DTRACE_SMB_DONE(op__ReadRaw, smb_request_t *, sr);
 240 }
 241 
 242 smb_sdrc_t
 243 smb_com_read_raw(smb_request_t *sr)
 244 {
 245         smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, ERRDOS,
 246             ERROR_NOT_SUPPORTED);
 247         return (SDRC_ERROR);
 248 }
 249 
 250 /*
 251  * Read bytes from a file (SMB Core).  This request was extended in
 252  * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
 253  * 12 and including additional offset information.
 254  *
 255  * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4:
 256  * If wct is 12 and CAP_LARGE_READX is set, the count may be larger
 257  * than the negotiated buffer size.  If maxcnt_high is 0xFF, it must
 258  * be ignored.  Otherwise, maxcnt_high represents the upper 16 bits
 259  * of rw_count.
 260  */
 261 smb_sdrc_t
 262 smb_pre_read_andx(smb_request_t *sr)
 263 {
 264         smb_rw_param_t *param;
 265         uint32_t off_low;
 266         uint32_t off_high;
 267         uint32_t maxcnt_high;
 268         uint16_t maxcnt_low;
 269         uint16_t mincnt;
 270         uint16_t remcnt;


 280 
 281                 param->rw_offset = ((uint64_t)off_high << 32) |
 282                     (uint64_t)off_low;
 283 
 284                 param->rw_count = (uint32_t)maxcnt_low;
 285 
 286                 if ((sr->session->capabilities & CAP_LARGE_READX) &&
 287                     (maxcnt_high < 0xFF))
 288                         param->rw_count |= maxcnt_high << 16;
 289         } else {
 290                 rc = smbsr_decode_vwv(sr, "b3.wlwwlw", &param->rw_andx,
 291                     &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
 292                     &remcnt);
 293 
 294                 param->rw_offset = (uint64_t)off_low;
 295                 param->rw_count = (uint32_t)maxcnt_low;
 296         }
 297 
 298         param->rw_mincnt = 0;
 299 
 300         DTRACE_SMB_START(op__ReadX, smb_request_t *, sr); /* arg.rw */

 301 
 302         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 303 }
 304 
 305 void
 306 smb_post_read_andx(smb_request_t *sr)
 307 {
 308         DTRACE_SMB_DONE(op__ReadX, smb_request_t *, sr); /* arg.rw */

 309 
 310         kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
 311 }
 312 
 313 smb_sdrc_t
 314 smb_com_read_andx(smb_request_t *sr)
 315 {
 316         smb_rw_param_t *param = sr->arg.rw;
 317         uint16_t datalen_high;
 318         uint16_t datalen_low;
 319         uint16_t data_offset;
 320         uint16_t offset2;
 321         int rc;
 322 
 323         smbsr_lookup_file(sr);
 324         if (sr->fid_ofile == NULL) {
 325                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
 326                 return (SDRC_ERROR);
 327         }
 328 


 368                     12,                 /* wct */
 369                     param->rw_andx,  /* secondary andx command */
 370                     offset2,            /* offset to next command */
 371                     -1,                 /* must be -1 for regular files */
 372                     datalen_low,        /* data byte count */
 373                     data_offset,        /* offset from start to data */
 374                     datalen_high,       /* data byte count */
 375                     VAR_BCC,            /* BCC marker */
 376                     &sr->raw_data);
 377         }
 378 
 379         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 380 }
 381 
 382 /*
 383  * Common function for reading files or IPC/MSRPC named pipes.  All
 384  * protocol read functions should lookup the fid before calling this
 385  * function.  We can't move the fid lookup here because lock-and-read
 386  * requires the fid to do locking before attempting the read.
 387  *
 388  * Reading from a file does not break oplocks because any need for
 389  * breaking before read is handled in open.



 390  *
 391  * Returns errno values.
 392  */
 393 int
 394 smb_common_read(smb_request_t *sr, smb_rw_param_t *param)
 395 {
 396         smb_ofile_t *ofile = sr->fid_ofile;
 397         smb_node_t *node;
 398         smb_vdb_t *vdb = &param->rw_vdb;
 399         struct mbuf *top;
 400         int rc;
 401 
 402         vdb->vdb_tag = 0;
 403         vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
 404         vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
 405         vdb->vdb_uio.uio_resid = param->rw_count;
 406         vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset;
 407         vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
 408         vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
 409 


 420                         }
 421                 }
 422 
 423                 if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) &&
 424                     !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) {
 425                         /*
 426                          * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only
 427                          * reads.
 428                          *
 429                          * Reject request if the file has been opened
 430                          * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not
 431                          * set.
 432                          */
 433                         rc = EACCES;
 434                         break;
 435                 }
 436 
 437                 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
 438                 top = smb_mbuf_allocate(&vdb->vdb_uio);
 439 
 440                 rc = smb_fsop_read(sr, sr->user_cr, node, ofile,
 441                     &vdb->vdb_uio, 0);
 442 
 443                 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
 444                 smb_mbuf_trim(top, sr->raw_data.max_bytes);
 445                 MBC_ATTACH_MBUF(&sr->raw_data, top);
 446                 break;
 447 
 448         case STYPE_IPC:
 449                 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
 450                 top = smb_mbuf_allocate(&vdb->vdb_uio);
 451 
 452                 rc = smb_opipe_read(sr, &vdb->vdb_uio);
 453 
 454                 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
 455                 smb_mbuf_trim(top, sr->raw_data.max_bytes);
 456                 MBC_ATTACH_MBUF(&sr->raw_data, top);
 457                 break;
 458 
 459         default:
 460                 rc = EACCES;
 461                 break;