1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 22cb174861Sjoyce mcintosh * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23*93bc28dbSGordon Ross * Copyright 2017 Nexenta Systems, Inc. All rights reserved. 24da6c28aaSamw */ 25da6c28aaSamw 26bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h> 27da6c28aaSamw #include <smbsrv/smb_fsops.h> 28da6c28aaSamw 292c2961f8Sjose borrego /* 302c2961f8Sjose borrego * The maximum number of bytes to return from SMB Core 312c2961f8Sjose borrego * SmbRead or SmbLockAndRead. 322c2961f8Sjose borrego */ 332c2961f8Sjose borrego #define SMB_CORE_READ_MAX 4432 342c2961f8Sjose borrego 352c2961f8Sjose borrego /* 362c2961f8Sjose borrego * The limit in bytes for SmbReadX. 372c2961f8Sjose borrego */ 382c2961f8Sjose borrego #define SMB_READX_MAX 0x10000 39da6c28aaSamw 402c2961f8Sjose borrego int smb_common_read(smb_request_t *, smb_rw_param_t *); 41da6c28aaSamw 42da6c28aaSamw /* 43da6c28aaSamw * Read bytes from a file or named pipe (SMB Core). 44da6c28aaSamw * 45da6c28aaSamw * The requested count specifies the number of bytes desired. Offset 46da6c28aaSamw * is limited to 32 bits, so this client request is inappropriate for 47da6c28aaSamw * files with 64 bit offsets. 48da6c28aaSamw * 49da6c28aaSamw * On return, count is the number of bytes actually being returned, which 50da6c28aaSamw * may be less than the count requested only if a read specifies bytes 51da6c28aaSamw * beyond the current file size. In this case only the bytes that exist 52da6c28aaSamw * are returned. A read completely beyond the end of file results in a 53da6c28aaSamw * response of length zero. This is the only circumstance when a zero 54da6c28aaSamw * length response is generated. A count returned which is less than the 55da6c28aaSamw * count requested is the end of file indicator. 56da6c28aaSamw */ 577b59d02dSjb smb_sdrc_t 58faa1795aSjb smb_pre_read(smb_request_t *sr) 59da6c28aaSamw { 60faa1795aSjb smb_rw_param_t *param; 61da6c28aaSamw uint32_t off_low; 622c2961f8Sjose borrego uint16_t count; 63da6c28aaSamw uint16_t remcnt; 64da6c28aaSamw int rc; 65da6c28aaSamw 66faa1795aSjb param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 67faa1795aSjb sr->arg.rw = param; 68faa1795aSjb 69da6c28aaSamw rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 702c2961f8Sjose borrego &count, &off_low, &remcnt); 71faa1795aSjb 72faa1795aSjb param->rw_offset = (uint64_t)off_low; 732c2961f8Sjose borrego param->rw_count = (uint32_t)count; 74faa1795aSjb param->rw_mincnt = 0; 75faa1795aSjb 76*93bc28dbSGordon Ross DTRACE_SMB_START(op__Read, smb_request_t *, sr); /* arg.rw */ 77faa1795aSjb 78faa1795aSjb return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 79faa1795aSjb } 80faa1795aSjb 81faa1795aSjb void 82faa1795aSjb smb_post_read(smb_request_t *sr) 83faa1795aSjb { 84*93bc28dbSGordon Ross DTRACE_SMB_DONE(op__Read, smb_request_t *, sr); /* arg.rw */ 85da6c28aaSamw 86faa1795aSjb kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 87faa1795aSjb } 88faa1795aSjb 89faa1795aSjb smb_sdrc_t 90faa1795aSjb smb_com_read(smb_request_t *sr) 91faa1795aSjb { 92faa1795aSjb smb_rw_param_t *param = sr->arg.rw; 932c2961f8Sjose borrego uint16_t count; 94faa1795aSjb int rc; 95da6c28aaSamw 962c2961f8Sjose borrego smbsr_lookup_file(sr); 97da6c28aaSamw if (sr->fid_ofile == NULL) { 98dc20a302Sas smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 99faa1795aSjb return (SDRC_ERROR); 100da6c28aaSamw } 101da6c28aaSamw 102b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 103b89a8333Snatalie li - Sun Microsystems - Irvine United States 1042c2961f8Sjose borrego if (param->rw_count > SMB_CORE_READ_MAX) 1052c2961f8Sjose borrego param->rw_count = SMB_CORE_READ_MAX; 1062c2961f8Sjose borrego 107faa1795aSjb if ((rc = smb_common_read(sr, param)) != 0) { 108dc20a302Sas smbsr_errno(sr, rc); 109faa1795aSjb return (SDRC_ERROR); 110da6c28aaSamw } 111da6c28aaSamw 1122c2961f8Sjose borrego count = (uint16_t)param->rw_count; 1137b59d02dSjb rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 1142c2961f8Sjose borrego 5, count, VAR_BCC, 0x01, count, &sr->raw_data); 115da6c28aaSamw 116faa1795aSjb return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 117da6c28aaSamw } 118da6c28aaSamw 119da6c28aaSamw /* 120da6c28aaSamw * Lock and read bytes from a file (SMB Core Plus). The SmbLockAndRead/ 121da6c28aaSamw * SmbLockAndWrite sub-dialect is only valid on disk files: reject any 122da6c28aaSamw * attempt to use it on non-disk shares. 123da6c28aaSamw * 124da6c28aaSamw * The requested count specifies the number of bytes desired. Offset 125da6c28aaSamw * specifies the offset in the file of the first byte to be locked then 126da6c28aaSamw * read. Note that offset is limited to 32 bits, so this client request 127da6c28aaSamw * is inappropriate for files with 64 bit offsets. 128da6c28aaSamw * 129da6c28aaSamw * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted 130da6c28aaSamw * immediately an error should be returned to the client. If an error 131da6c28aaSamw * occurs on the lock, the bytes should not be read. 132da6c28aaSamw * 133da6c28aaSamw * On return, count is the number of bytes actually being returned, which 134da6c28aaSamw * may be less than the count requested only if a read specifies bytes 135da6c28aaSamw * beyond the current file size. In this case only the bytes that exist 136da6c28aaSamw * are returned. A read completely beyond the end of file results in a 137da6c28aaSamw * response of length zero. This is the only circumstance when a zero 138da6c28aaSamw * length response is generated. A count returned which is less than the 139da6c28aaSamw * count requested is the end of file indicator. 140da6c28aaSamw */ 1417b59d02dSjb smb_sdrc_t 142faa1795aSjb smb_pre_lock_and_read(smb_request_t *sr) 143da6c28aaSamw { 144faa1795aSjb smb_rw_param_t *param; 145da6c28aaSamw uint32_t off_low; 1462c2961f8Sjose borrego uint16_t count; 1472c2961f8Sjose borrego uint16_t remcnt; 148da6c28aaSamw int rc; 149da6c28aaSamw 150faa1795aSjb param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 151faa1795aSjb sr->arg.rw = param; 152da6c28aaSamw 153da6c28aaSamw rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 1542c2961f8Sjose borrego &count, &off_low, &remcnt); 155faa1795aSjb 156faa1795aSjb param->rw_offset = (uint64_t)off_low; 1572c2961f8Sjose borrego param->rw_count = (uint32_t)count; 158faa1795aSjb param->rw_mincnt = 0; 159faa1795aSjb 160*93bc28dbSGordon Ross DTRACE_SMB_START(op__LockAndRead, smb_request_t *, sr); /* arg.rw */ 161faa1795aSjb 162faa1795aSjb return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 163faa1795aSjb } 164faa1795aSjb 165faa1795aSjb void 166faa1795aSjb smb_post_lock_and_read(smb_request_t *sr) 167faa1795aSjb { 168*93bc28dbSGordon Ross DTRACE_SMB_DONE(op__LockAndRead, smb_request_t *, sr); /* arg.rw */ 169faa1795aSjb 170faa1795aSjb kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 171faa1795aSjb } 172da6c28aaSamw 173faa1795aSjb smb_sdrc_t 174faa1795aSjb smb_com_lock_and_read(smb_request_t *sr) 175faa1795aSjb { 176faa1795aSjb smb_rw_param_t *param = sr->arg.rw; 177faa1795aSjb DWORD status; 1780897f7fbSGordon Ross uint32_t lk_pid; 1792c2961f8Sjose borrego uint16_t count; 180faa1795aSjb int rc; 181faa1795aSjb 182faa1795aSjb if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { 183faa1795aSjb smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); 184faa1795aSjb return (SDRC_ERROR); 185faa1795aSjb } 186da6c28aaSamw 1872c2961f8Sjose borrego smbsr_lookup_file(sr); 188da6c28aaSamw if (sr->fid_ofile == NULL) { 189dc20a302Sas smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 190faa1795aSjb return (SDRC_ERROR); 191da6c28aaSamw } 192da6c28aaSamw 193b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 194b89a8333Snatalie li - Sun Microsystems - Irvine United States 1950897f7fbSGordon Ross /* Note: SMB1 locking uses 16-bit PIDs. */ 1960897f7fbSGordon Ross lk_pid = sr->smb_pid & 0xFFFF; 1970897f7fbSGordon Ross 1986537f381Sas status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count, 1990897f7fbSGordon Ross lk_pid, SMB_LOCK_TYPE_READWRITE, 0); 2002c2961f8Sjose borrego 201faa1795aSjb if (status != NT_STATUS_SUCCESS) { 202faa1795aSjb smb_lock_range_error(sr, status); 203faa1795aSjb return (SDRC_ERROR); 204da6c28aaSamw } 205da6c28aaSamw 2062c2961f8Sjose borrego if (param->rw_count > SMB_CORE_READ_MAX) 2072c2961f8Sjose borrego param->rw_count = SMB_CORE_READ_MAX; 2082c2961f8Sjose borrego 209faa1795aSjb if ((rc = smb_common_read(sr, param)) != 0) { 210dc20a302Sas smbsr_errno(sr, rc); 211faa1795aSjb return (SDRC_ERROR); 212da6c28aaSamw } 213da6c28aaSamw 2142c2961f8Sjose borrego count = (uint16_t)param->rw_count; 2157b59d02dSjb rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 2162c2961f8Sjose borrego 5, count, VAR_BCC, 0x1, count, &sr->raw_data); 217da6c28aaSamw 218faa1795aSjb return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 219da6c28aaSamw } 220da6c28aaSamw 221*93bc28dbSGordon Ross /* 222*93bc28dbSGordon Ross * The SMB_COM_READ_RAW protocol was a negotiated option introduced in 223*93bc28dbSGordon Ross * SMB Core Plus to maximize performance when reading a large block 224*93bc28dbSGordon Ross * of data from a server. It's obsolete and no longer supported. 225*93bc28dbSGordon Ross * 226*93bc28dbSGordon Ross * We keep a handler for it so the dtrace provider can see if 227*93bc28dbSGordon Ross * the client tried to use this command. 228*93bc28dbSGordon Ross */ 229*93bc28dbSGordon Ross smb_sdrc_t 230*93bc28dbSGordon Ross smb_pre_read_raw(smb_request_t *sr) 231*93bc28dbSGordon Ross { 232*93bc28dbSGordon Ross DTRACE_SMB_START(op__ReadRaw, smb_request_t *, sr); 233*93bc28dbSGordon Ross return (SDRC_SUCCESS); 234*93bc28dbSGordon Ross } 235*93bc28dbSGordon Ross 236*93bc28dbSGordon Ross void 237*93bc28dbSGordon Ross smb_post_read_raw(smb_request_t *sr) 238*93bc28dbSGordon Ross { 239*93bc28dbSGordon Ross DTRACE_SMB_DONE(op__ReadRaw, smb_request_t *, sr); 240*93bc28dbSGordon Ross } 241*93bc28dbSGordon Ross 242*93bc28dbSGordon Ross smb_sdrc_t 243*93bc28dbSGordon Ross smb_com_read_raw(smb_request_t *sr) 244*93bc28dbSGordon Ross { 245*93bc28dbSGordon Ross smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, ERRDOS, 246*93bc28dbSGordon Ross ERROR_NOT_SUPPORTED); 247*93bc28dbSGordon Ross return (SDRC_ERROR); 248*93bc28dbSGordon Ross } 249*93bc28dbSGordon Ross 250da6c28aaSamw /* 251da6c28aaSamw * Read bytes from a file (SMB Core). This request was extended in 252da6c28aaSamw * LM 0.12 to support 64-bit offsets, indicated by sending a wct of 253da6c28aaSamw * 12 and including additional offset information. 2542c2961f8Sjose borrego * 2552c2961f8Sjose borrego * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4: 2562c2961f8Sjose borrego * If wct is 12 and CAP_LARGE_READX is set, the count may be larger 2572c2961f8Sjose borrego * than the negotiated buffer size. If maxcnt_high is 0xFF, it must 2582c2961f8Sjose borrego * be ignored. Otherwise, maxcnt_high represents the upper 16 bits 2592c2961f8Sjose borrego * of rw_count. 260da6c28aaSamw */ 2617b59d02dSjb smb_sdrc_t 262faa1795aSjb smb_pre_read_andx(smb_request_t *sr) 263da6c28aaSamw { 264faa1795aSjb smb_rw_param_t *param; 265da6c28aaSamw uint32_t off_low; 266da6c28aaSamw uint32_t off_high; 2672c2961f8Sjose borrego uint32_t maxcnt_high; 2682c2961f8Sjose borrego uint16_t maxcnt_low; 2692c2961f8Sjose borrego uint16_t mincnt; 270da6c28aaSamw uint16_t remcnt; 271da6c28aaSamw int rc; 272da6c28aaSamw 273faa1795aSjb param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 274faa1795aSjb sr->arg.rw = param; 275faa1795aSjb 276da6c28aaSamw if (sr->smb_wct == 12) { 2772c2961f8Sjose borrego rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", ¶m->rw_andx, 2782c2961f8Sjose borrego &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 2792c2961f8Sjose borrego &remcnt, &off_high); 2802c2961f8Sjose borrego 2812c2961f8Sjose borrego param->rw_offset = ((uint64_t)off_high << 32) | 2822c2961f8Sjose borrego (uint64_t)off_low; 283da6c28aaSamw 2842c2961f8Sjose borrego param->rw_count = (uint32_t)maxcnt_low; 2853a6c5f83SAlan Wright 2863a6c5f83SAlan Wright if ((sr->session->capabilities & CAP_LARGE_READX) && 2873a6c5f83SAlan Wright (maxcnt_high < 0xFF)) 2882c2961f8Sjose borrego param->rw_count |= maxcnt_high << 16; 289da6c28aaSamw } else { 2902c2961f8Sjose borrego rc = smbsr_decode_vwv(sr, "b3.wlwwlw", ¶m->rw_andx, 2912c2961f8Sjose borrego &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 2922c2961f8Sjose borrego &remcnt); 293da6c28aaSamw 294faa1795aSjb param->rw_offset = (uint64_t)off_low; 2952c2961f8Sjose borrego param->rw_count = (uint32_t)maxcnt_low; 296da6c28aaSamw } 297da6c28aaSamw 298faa1795aSjb param->rw_mincnt = 0; 299faa1795aSjb 300*93bc28dbSGordon Ross DTRACE_SMB_START(op__ReadX, smb_request_t *, sr); /* arg.rw */ 301faa1795aSjb 302faa1795aSjb return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 303faa1795aSjb } 304da6c28aaSamw 305faa1795aSjb void 306faa1795aSjb smb_post_read_andx(smb_request_t *sr) 307faa1795aSjb { 308*93bc28dbSGordon Ross DTRACE_SMB_DONE(op__ReadX, smb_request_t *, sr); /* arg.rw */ 309faa1795aSjb 310faa1795aSjb kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 311faa1795aSjb } 312faa1795aSjb 313faa1795aSjb smb_sdrc_t 314faa1795aSjb smb_com_read_andx(smb_request_t *sr) 315faa1795aSjb { 316faa1795aSjb smb_rw_param_t *param = sr->arg.rw; 3172c2961f8Sjose borrego uint16_t datalen_high; 3182c2961f8Sjose borrego uint16_t datalen_low; 3192c2961f8Sjose borrego uint16_t data_offset; 320faa1795aSjb uint16_t offset2; 321faa1795aSjb int rc; 322da6c28aaSamw 3232c2961f8Sjose borrego smbsr_lookup_file(sr); 324da6c28aaSamw if (sr->fid_ofile == NULL) { 325dc20a302Sas smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 326faa1795aSjb return (SDRC_ERROR); 327da6c28aaSamw } 328da6c28aaSamw 329b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 330b89a8333Snatalie li - Sun Microsystems - Irvine United States 3312c2961f8Sjose borrego if (param->rw_count >= SMB_READX_MAX) 3322c2961f8Sjose borrego param->rw_count = 0; 3332c2961f8Sjose borrego 334faa1795aSjb if ((rc = smb_common_read(sr, param)) != 0) { 335dc20a302Sas smbsr_errno(sr, rc); 336faa1795aSjb return (SDRC_ERROR); 337da6c28aaSamw } 338da6c28aaSamw 3392c2961f8Sjose borrego datalen_low = param->rw_count & 0xFFFF; 3402c2961f8Sjose borrego datalen_high = (param->rw_count >> 16) & 0xFF; 341da6c28aaSamw 342da6c28aaSamw /* 3432c2961f8Sjose borrego * If this is a secondary command, the data offset 3442c2961f8Sjose borrego * includes the previous wct + sizeof(wct). 345da6c28aaSamw */ 3462c2961f8Sjose borrego data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1; 3472c2961f8Sjose borrego 348da6c28aaSamw if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { 3492c2961f8Sjose borrego data_offset += 60; 3502c2961f8Sjose borrego offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60; 3512c2961f8Sjose borrego 3522c2961f8Sjose borrego rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC", 353da6c28aaSamw 12, /* wct */ 3542c2961f8Sjose borrego param->rw_andx, /* secondary andx command */ 3552c2961f8Sjose borrego offset2, /* offset to next command */ 3562c2961f8Sjose borrego 0, /* set to 0 for named pipes */ 3572c2961f8Sjose borrego datalen_low, /* data byte count */ 3582c2961f8Sjose borrego data_offset, /* offset from start to data */ 3592c2961f8Sjose borrego datalen_high, /* data byte count */ 360da6c28aaSamw VAR_BCC, /* BCC marker */ 3612c2961f8Sjose borrego 0x00, /* padding */ 362da6c28aaSamw &sr->raw_data); 363da6c28aaSamw } else { 3642c2961f8Sjose borrego data_offset += 59; 3652c2961f8Sjose borrego offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59; 3662c2961f8Sjose borrego 3672c2961f8Sjose borrego rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC", 368da6c28aaSamw 12, /* wct */ 3692c2961f8Sjose borrego param->rw_andx, /* secondary andx command */ 3702c2961f8Sjose borrego offset2, /* offset to next command */ 3712c2961f8Sjose borrego -1, /* must be -1 for regular files */ 3722c2961f8Sjose borrego datalen_low, /* data byte count */ 3732c2961f8Sjose borrego data_offset, /* offset from start to data */ 3742c2961f8Sjose borrego datalen_high, /* data byte count */ 375da6c28aaSamw VAR_BCC, /* BCC marker */ 376da6c28aaSamw &sr->raw_data); 377da6c28aaSamw } 378da6c28aaSamw 379faa1795aSjb return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 380da6c28aaSamw } 381da6c28aaSamw 382da6c28aaSamw /* 383da6c28aaSamw * Common function for reading files or IPC/MSRPC named pipes. All 384da6c28aaSamw * protocol read functions should lookup the fid before calling this 385da6c28aaSamw * function. We can't move the fid lookup here because lock-and-read 386da6c28aaSamw * requires the fid to do locking before attempting the read. 387da6c28aaSamw * 388cb174861Sjoyce mcintosh * Reading from a file should break oplocks on the file to LEVEL_II. 389cb174861Sjoyce mcintosh * A call to smb_oplock_break(SMB_OPLOCK_BREAK_TO_LEVEL_II) is not 390cb174861Sjoyce mcintosh * required as it is a no-op. If there's anything greater than a 391cb174861Sjoyce mcintosh * LEVEL_II oplock on the file, the oplock MUST be owned by the ofile 392cb174861Sjoyce mcintosh * on which the read is occuring and therefore would not be broken. 393cb174861Sjoyce mcintosh * 394da6c28aaSamw * Returns errno values. 395da6c28aaSamw */ 396da6c28aaSamw int 397faa1795aSjb smb_common_read(smb_request_t *sr, smb_rw_param_t *param) 398da6c28aaSamw { 399da6c28aaSamw smb_ofile_t *ofile = sr->fid_ofile; 400da6c28aaSamw smb_node_t *node; 401faa1795aSjb smb_vdb_t *vdb = ¶m->rw_vdb; 402da6c28aaSamw struct mbuf *top; 403da6c28aaSamw int rc; 404da6c28aaSamw 4052c2961f8Sjose borrego vdb->vdb_tag = 0; 4062c2961f8Sjose borrego vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0]; 4072c2961f8Sjose borrego vdb->vdb_uio.uio_iovcnt = MAX_IOVEC; 4082c2961f8Sjose borrego vdb->vdb_uio.uio_resid = param->rw_count; 4092c2961f8Sjose borrego vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset; 4102c2961f8Sjose borrego vdb->vdb_uio.uio_segflg = UIO_SYSSPACE; 411f96bd5c8SAlan Wright vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT; 412da6c28aaSamw 413da6c28aaSamw switch (sr->tid_tree->t_res_type & STYPE_MASK) { 414da6c28aaSamw case STYPE_DISKTREE: 415da6c28aaSamw node = ofile->f_node; 416da6c28aaSamw 417037cac00Sjoyce mcintosh if (!smb_node_is_dir(node)) { 418faa1795aSjb rc = smb_lock_range_access(sr, node, param->rw_offset, 419faa1795aSjb param->rw_count, B_FALSE); 420da6c28aaSamw if (rc != NT_STATUS_SUCCESS) { 421da6c28aaSamw rc = ERANGE; 422da6c28aaSamw break; 423da6c28aaSamw } 424da6c28aaSamw } 425da6c28aaSamw 4262c2961f8Sjose borrego if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) && 4279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) { 4282c2961f8Sjose borrego /* 4299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only 4309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * reads. 4312c2961f8Sjose borrego * 4322c2961f8Sjose borrego * Reject request if the file has been opened 4339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not 4349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * set. 4352c2961f8Sjose borrego */ 4362c2961f8Sjose borrego rc = EACCES; 4372c2961f8Sjose borrego break; 4382c2961f8Sjose borrego } 4392c2961f8Sjose borrego 4402c2961f8Sjose borrego sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid; 4412c2961f8Sjose borrego top = smb_mbuf_allocate(&vdb->vdb_uio); 442da6c28aaSamw 443037cac00Sjoyce mcintosh rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->vdb_uio); 444da6c28aaSamw 4452c2961f8Sjose borrego sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid; 446da6c28aaSamw smb_mbuf_trim(top, sr->raw_data.max_bytes); 447da6c28aaSamw MBC_ATTACH_MBUF(&sr->raw_data, top); 448da6c28aaSamw break; 449da6c28aaSamw 450da6c28aaSamw case STYPE_IPC: 45168b2bbf2SGordon Ross sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid; 45268b2bbf2SGordon Ross top = smb_mbuf_allocate(&vdb->vdb_uio); 45368b2bbf2SGordon Ross 4542c2961f8Sjose borrego rc = smb_opipe_read(sr, &vdb->vdb_uio); 45568b2bbf2SGordon Ross 45668b2bbf2SGordon Ross sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid; 45768b2bbf2SGordon Ross smb_mbuf_trim(top, sr->raw_data.max_bytes); 45868b2bbf2SGordon Ross MBC_ATTACH_MBUF(&sr->raw_data, top); 459da6c28aaSamw break; 460da6c28aaSamw 461da6c28aaSamw default: 462da6c28aaSamw rc = EACCES; 463da6c28aaSamw break; 464da6c28aaSamw } 465da6c28aaSamw 4662c2961f8Sjose borrego param->rw_count -= vdb->vdb_uio.uio_resid; 467da6c28aaSamw 468da6c28aaSamw if (rc != 0) 469da6c28aaSamw return (rc); 470da6c28aaSamw 471faa1795aSjb if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) { 472da6c28aaSamw /* 473da6c28aaSamw * mincnt is only used by read-raw and is typically 474da6c28aaSamw * zero. If mincnt is greater than zero and the 475da6c28aaSamw * number of bytes read is less than mincnt, tell 476da6c28aaSamw * the client that we read nothing. 477da6c28aaSamw */ 478faa1795aSjb param->rw_count = 0; 479da6c28aaSamw } 480da6c28aaSamw 481faa1795aSjb param->rw_offset += param->rw_count; 482da6c28aaSamw mutex_enter(&sr->fid_ofile->f_mutex); 483faa1795aSjb ofile->f_seek_pos = param->rw_offset; 484da6c28aaSamw mutex_exit(&sr->fid_ofile->f_mutex); 485da6c28aaSamw return (rc); 486da6c28aaSamw } 487