15331Samw /* 25331Samw * CDDL HEADER START 35331Samw * 45331Samw * The contents of this file are subject to the terms of the 55331Samw * Common Development and Distribution License (the "License"). 65331Samw * You may not use this file except in compliance with the License. 75331Samw * 85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95331Samw * or http://www.opensolaris.org/os/licensing. 105331Samw * See the License for the specific language governing permissions 115331Samw * and limitations under the License. 125331Samw * 135331Samw * When distributing Covered Code, include this CDDL HEADER in each 145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155331Samw * If applicable, add the following below this CDDL HEADER, with the 165331Samw * fields enclosed by brackets "[]" replaced with your own identifying 175331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 185331Samw * 195331Samw * CDDL HEADER END 205331Samw */ 215331Samw /* 22*8934SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw #include <smbsrv/smb_incl.h> 275331Samw #include <smbsrv/smb_fsops.h> 285331Samw 295331Samw 30*8934SJose.Borrego@Sun.COM /* 31*8934SJose.Borrego@Sun.COM * The maximum number of bytes to return from SMB Core 32*8934SJose.Borrego@Sun.COM * SmbRead or SmbLockAndRead. 33*8934SJose.Borrego@Sun.COM */ 34*8934SJose.Borrego@Sun.COM #define SMB_CORE_READ_MAX 4432 35*8934SJose.Borrego@Sun.COM 36*8934SJose.Borrego@Sun.COM /* 37*8934SJose.Borrego@Sun.COM * The limit in bytes for SmbReadX. 38*8934SJose.Borrego@Sun.COM */ 39*8934SJose.Borrego@Sun.COM #define SMB_READX_MAX 0x10000 40*8934SJose.Borrego@Sun.COM 416139Sjb150015 int smb_common_read(smb_request_t *, smb_rw_param_t *); 425331Samw 435331Samw /* 445331Samw * Read bytes from a file or named pipe (SMB Core). 455331Samw * 465331Samw * The requested count specifies the number of bytes desired. Offset 475331Samw * is limited to 32 bits, so this client request is inappropriate for 485331Samw * files with 64 bit offsets. 495331Samw * 505331Samw * On return, count is the number of bytes actually being returned, which 515331Samw * may be less than the count requested only if a read specifies bytes 525331Samw * beyond the current file size. In this case only the bytes that exist 535331Samw * are returned. A read completely beyond the end of file results in a 545331Samw * response of length zero. This is the only circumstance when a zero 555331Samw * length response is generated. A count returned which is less than the 565331Samw * count requested is the end of file indicator. 575331Samw */ 586030Sjb150015 smb_sdrc_t 596139Sjb150015 smb_pre_read(smb_request_t *sr) 605331Samw { 616139Sjb150015 smb_rw_param_t *param; 625331Samw uint32_t off_low; 63*8934SJose.Borrego@Sun.COM uint16_t count; 645331Samw uint16_t remcnt; 655331Samw int rc; 665331Samw 676139Sjb150015 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 686139Sjb150015 sr->arg.rw = param; 696139Sjb150015 705331Samw rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 71*8934SJose.Borrego@Sun.COM &count, &off_low, &remcnt); 726139Sjb150015 736139Sjb150015 param->rw_offset = (uint64_t)off_low; 74*8934SJose.Borrego@Sun.COM param->rw_count = (uint32_t)count; 756139Sjb150015 param->rw_mincnt = 0; 766139Sjb150015 776139Sjb150015 DTRACE_SMB_2(op__Read__start, smb_request_t *, sr, 786139Sjb150015 smb_rw_param_t *, param); 796139Sjb150015 806139Sjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 816139Sjb150015 } 825331Samw 836139Sjb150015 void 846139Sjb150015 smb_post_read(smb_request_t *sr) 856139Sjb150015 { 866139Sjb150015 DTRACE_SMB_2(op__Read__done, smb_request_t *, sr, 876139Sjb150015 smb_rw_param_t *, sr->arg.rw); 886139Sjb150015 896139Sjb150015 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 906139Sjb150015 } 916139Sjb150015 926139Sjb150015 smb_sdrc_t 936139Sjb150015 smb_com_read(smb_request_t *sr) 946139Sjb150015 { 956139Sjb150015 smb_rw_param_t *param = sr->arg.rw; 96*8934SJose.Borrego@Sun.COM uint16_t count; 976139Sjb150015 int rc; 985331Samw 99*8934SJose.Borrego@Sun.COM smbsr_lookup_file(sr); 1005331Samw if (sr->fid_ofile == NULL) { 1015772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 1026139Sjb150015 return (SDRC_ERROR); 1035331Samw } 1045331Samw 1057961SNatalie.Li@Sun.COM sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 1067961SNatalie.Li@Sun.COM 107*8934SJose.Borrego@Sun.COM if (param->rw_count > SMB_CORE_READ_MAX) 108*8934SJose.Borrego@Sun.COM param->rw_count = SMB_CORE_READ_MAX; 109*8934SJose.Borrego@Sun.COM 1106139Sjb150015 if ((rc = smb_common_read(sr, param)) != 0) { 1115772Sas200622 smbsr_errno(sr, rc); 1126139Sjb150015 return (SDRC_ERROR); 1135331Samw } 1145331Samw 115*8934SJose.Borrego@Sun.COM count = (uint16_t)param->rw_count; 1166030Sjb150015 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 117*8934SJose.Borrego@Sun.COM 5, count, VAR_BCC, 0x01, count, &sr->raw_data); 1185331Samw 1196139Sjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1205331Samw } 1215331Samw 1225331Samw /* 1235331Samw * Lock and read bytes from a file (SMB Core Plus). The SmbLockAndRead/ 1245331Samw * SmbLockAndWrite sub-dialect is only valid on disk files: reject any 1255331Samw * attempt to use it on non-disk shares. 1265331Samw * 1275331Samw * The requested count specifies the number of bytes desired. Offset 1285331Samw * specifies the offset in the file of the first byte to be locked then 1295331Samw * read. Note that offset is limited to 32 bits, so this client request 1305331Samw * is inappropriate for files with 64 bit offsets. 1315331Samw * 1325331Samw * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted 1335331Samw * immediately an error should be returned to the client. If an error 1345331Samw * occurs on the lock, the bytes should not be read. 1355331Samw * 1365331Samw * On return, count is the number of bytes actually being returned, which 1375331Samw * may be less than the count requested only if a read specifies bytes 1385331Samw * beyond the current file size. In this case only the bytes that exist 1395331Samw * are returned. A read completely beyond the end of file results in a 1405331Samw * response of length zero. This is the only circumstance when a zero 1415331Samw * length response is generated. A count returned which is less than the 1425331Samw * count requested is the end of file indicator. 1435331Samw */ 1446030Sjb150015 smb_sdrc_t 1456139Sjb150015 smb_pre_lock_and_read(smb_request_t *sr) 1465331Samw { 1476139Sjb150015 smb_rw_param_t *param; 148*8934SJose.Borrego@Sun.COM uint32_t off_low; 149*8934SJose.Borrego@Sun.COM uint16_t count; 1505331Samw uint16_t remcnt; 1516139Sjb150015 int rc; 1526139Sjb150015 1536139Sjb150015 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 1546139Sjb150015 sr->arg.rw = param; 1556139Sjb150015 1566139Sjb150015 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 157*8934SJose.Borrego@Sun.COM &count, &off_low, &remcnt); 1586139Sjb150015 1596139Sjb150015 param->rw_offset = (uint64_t)off_low; 160*8934SJose.Borrego@Sun.COM param->rw_count = (uint32_t)count; 1616139Sjb150015 param->rw_mincnt = 0; 1626139Sjb150015 1636139Sjb150015 DTRACE_SMB_2(op__LockAndRead__start, smb_request_t *, sr, 1646139Sjb150015 smb_rw_param_t *, param); 1656139Sjb150015 1666139Sjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1676139Sjb150015 } 1686139Sjb150015 1696139Sjb150015 void 1706139Sjb150015 smb_post_lock_and_read(smb_request_t *sr) 1716139Sjb150015 { 1726139Sjb150015 DTRACE_SMB_2(op__LockAndRead__done, smb_request_t *, sr, 1736139Sjb150015 smb_rw_param_t *, sr->arg.rw); 1746139Sjb150015 1756139Sjb150015 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 1766139Sjb150015 } 1776139Sjb150015 1786139Sjb150015 smb_sdrc_t 1796139Sjb150015 smb_com_lock_and_read(smb_request_t *sr) 1806139Sjb150015 { 1816139Sjb150015 smb_rw_param_t *param = sr->arg.rw; 1826139Sjb150015 DWORD status; 183*8934SJose.Borrego@Sun.COM uint16_t count; 1845331Samw int rc; 1855331Samw 1865331Samw if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { 1875772Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); 1886139Sjb150015 return (SDRC_ERROR); 1895331Samw } 1905331Samw 191*8934SJose.Borrego@Sun.COM smbsr_lookup_file(sr); 1925331Samw if (sr->fid_ofile == NULL) { 1935772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 1946139Sjb150015 return (SDRC_ERROR); 1955331Samw } 1965331Samw 1977961SNatalie.Li@Sun.COM sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 1987961SNatalie.Li@Sun.COM 1996432Sas200622 status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count, 200*8934SJose.Borrego@Sun.COM 0, SMB_LOCK_TYPE_READWRITE); 201*8934SJose.Borrego@Sun.COM 2026139Sjb150015 if (status != NT_STATUS_SUCCESS) { 2036139Sjb150015 smb_lock_range_error(sr, status); 2046139Sjb150015 return (SDRC_ERROR); 2055331Samw } 2065331Samw 207*8934SJose.Borrego@Sun.COM if (param->rw_count > SMB_CORE_READ_MAX) 208*8934SJose.Borrego@Sun.COM param->rw_count = SMB_CORE_READ_MAX; 209*8934SJose.Borrego@Sun.COM 2106139Sjb150015 if ((rc = smb_common_read(sr, param)) != 0) { 2115772Sas200622 smbsr_errno(sr, rc); 2126139Sjb150015 return (SDRC_ERROR); 2135331Samw } 2145331Samw 215*8934SJose.Borrego@Sun.COM count = (uint16_t)param->rw_count; 2166030Sjb150015 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 217*8934SJose.Borrego@Sun.COM 5, count, VAR_BCC, 0x1, count, &sr->raw_data); 2185331Samw 2196139Sjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 2205331Samw } 2215331Samw 2225331Samw /* 2235331Samw * The SMB_COM_READ_RAW protocol is a negotiated option introduced in 2245331Samw * SMB Core Plus to maximize performance when reading a large block 2255331Samw * of data from a server. This request was extended in LM 0.12 to 2265331Samw * support 64-bit offsets; the server can indicate support by setting 2275331Samw * CAP_LARGE_FILES in the negotiated capabilities. 2285331Samw * 2295331Samw * The client must guarantee that there is (and will be) no other request 2305331Samw * to the server for the duration of the SMB_COM_READ_RAW, since the 2315331Samw * server response has no header or trailer. To help ensure that there 2325331Samw * are no interruptions, we block all I/O for the session during read raw. 2335331Samw * 2345331Samw * If this is the first SMB request received since we sent an oplock break 2355331Samw * to this client, we don't know if it's safe to send the raw data because 2365331Samw * the requests may have crossed on the wire and the client may have 2375331Samw * interpreted the oplock break as part of the raw data. To avoid problems, 2385331Samw * we send a zero length session packet, which will force the client to 2395331Samw * retry the read. 2405331Samw * 241*8934SJose.Borrego@Sun.COM * Do not return errors from SmbReadRaw. 2425331Samw * Read errors are handled by sending a zero length response. 2435331Samw */ 2446030Sjb150015 smb_sdrc_t 2456139Sjb150015 smb_pre_read_raw(smb_request_t *sr) 2465331Samw { 2476139Sjb150015 smb_rw_param_t *param; 2486139Sjb150015 uint32_t off_low; 2496139Sjb150015 uint32_t off_high; 2506139Sjb150015 uint32_t timeout; 251*8934SJose.Borrego@Sun.COM uint16_t count; 2526139Sjb150015 int rc; 2536139Sjb150015 2546139Sjb150015 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 2556139Sjb150015 sr->arg.rw = param; 2566139Sjb150015 2576139Sjb150015 if (sr->smb_wct == 8) { 2586139Sjb150015 rc = smbsr_decode_vwv(sr, "wlwwl2.", &sr->smb_fid, 259*8934SJose.Borrego@Sun.COM &off_low, &count, ¶m->rw_mincnt, &timeout); 260*8934SJose.Borrego@Sun.COM if (rc == 0) { 261*8934SJose.Borrego@Sun.COM param->rw_offset = (uint64_t)off_low; 262*8934SJose.Borrego@Sun.COM param->rw_count = (uint32_t)count; 263*8934SJose.Borrego@Sun.COM } 2646139Sjb150015 } else { 2656139Sjb150015 rc = smbsr_decode_vwv(sr, "wlwwl2.l", &sr->smb_fid, 266*8934SJose.Borrego@Sun.COM &off_low, &count, ¶m->rw_mincnt, &timeout, &off_high); 267*8934SJose.Borrego@Sun.COM if (rc == 0) { 268*8934SJose.Borrego@Sun.COM param->rw_offset = ((uint64_t)off_high << 32) | off_low; 269*8934SJose.Borrego@Sun.COM param->rw_count = (uint32_t)count; 270*8934SJose.Borrego@Sun.COM } 2716139Sjb150015 } 2726139Sjb150015 2736139Sjb150015 DTRACE_SMB_2(op__ReadRaw__start, smb_request_t *, sr, 2746139Sjb150015 smb_rw_param_t *, param); 2756139Sjb150015 276*8934SJose.Borrego@Sun.COM return (SDRC_SUCCESS); 2776139Sjb150015 } 2786139Sjb150015 2796139Sjb150015 void 2806139Sjb150015 smb_post_read_raw(smb_request_t *sr) 2816139Sjb150015 { 282*8934SJose.Borrego@Sun.COM mbuf_chain_t *mbc; 283*8934SJose.Borrego@Sun.COM 284*8934SJose.Borrego@Sun.COM if (sr->session->s_state == SMB_SESSION_STATE_READ_RAW_ACTIVE) { 285*8934SJose.Borrego@Sun.COM sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; 286*8934SJose.Borrego@Sun.COM 287*8934SJose.Borrego@Sun.COM while ((mbc = list_head(&sr->session->s_oplock_brkreqs)) != 288*8934SJose.Borrego@Sun.COM NULL) { 289*8934SJose.Borrego@Sun.COM SMB_MBC_VALID(mbc); 290*8934SJose.Borrego@Sun.COM list_remove(&sr->session->s_oplock_brkreqs, mbc); 291*8934SJose.Borrego@Sun.COM (void) smb_session_send(sr->session, 0, mbc); 292*8934SJose.Borrego@Sun.COM smb_mbc_free(mbc); 293*8934SJose.Borrego@Sun.COM } 294*8934SJose.Borrego@Sun.COM } 295*8934SJose.Borrego@Sun.COM 2966139Sjb150015 DTRACE_SMB_2(op__ReadRaw__done, smb_request_t *, sr, 2976139Sjb150015 smb_rw_param_t *, sr->arg.rw); 2986139Sjb150015 2996139Sjb150015 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 3006139Sjb150015 } 3016139Sjb150015 3026139Sjb150015 smb_sdrc_t 3036139Sjb150015 smb_com_read_raw(smb_request_t *sr) 3046139Sjb150015 { 3056139Sjb150015 smb_rw_param_t *param = sr->arg.rw; 3065331Samw 3075331Samw switch (sr->session->s_state) { 3085331Samw case SMB_SESSION_STATE_NEGOTIATED: 309*8934SJose.Borrego@Sun.COM sr->session->s_state = SMB_SESSION_STATE_READ_RAW_ACTIVE; 3106139Sjb150015 break; 3115331Samw 3125331Samw case SMB_SESSION_STATE_OPLOCK_BREAKING: 3135331Samw (void) smb_session_send(sr->session, 0, NULL); 3145331Samw return (SDRC_NO_REPLY); 3155331Samw 3165331Samw case SMB_SESSION_STATE_TERMINATED: 3175331Samw case SMB_SESSION_STATE_DISCONNECTED: 3185331Samw return (SDRC_NO_REPLY); 3195331Samw 320*8934SJose.Borrego@Sun.COM case SMB_SESSION_STATE_READ_RAW_ACTIVE: 321*8934SJose.Borrego@Sun.COM sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; 322*8934SJose.Borrego@Sun.COM return (SDRC_DROP_VC); 323*8934SJose.Borrego@Sun.COM 3246139Sjb150015 case SMB_SESSION_STATE_WRITE_RAW_ACTIVE: 3255331Samw case SMB_SESSION_STATE_CONNECTED: 3265331Samw case SMB_SESSION_STATE_ESTABLISHED: 3275331Samw default: 3285331Samw return (SDRC_DROP_VC); 3295331Samw } 3306139Sjb150015 331*8934SJose.Borrego@Sun.COM smbsr_lookup_file(sr); 3326139Sjb150015 if (sr->fid_ofile == NULL) { 333*8934SJose.Borrego@Sun.COM (void) smb_session_send(sr->session, 0, NULL); 334*8934SJose.Borrego@Sun.COM return (SDRC_NO_REPLY); 3356139Sjb150015 } 3366139Sjb150015 3377961SNatalie.Li@Sun.COM sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 3387961SNatalie.Li@Sun.COM 339*8934SJose.Borrego@Sun.COM if (param->rw_mincnt > param->rw_count) 340*8934SJose.Borrego@Sun.COM param->rw_mincnt = 0; 3416139Sjb150015 342*8934SJose.Borrego@Sun.COM if (smb_common_read(sr, param) != 0) { 3436139Sjb150015 (void) smb_session_send(sr->session, 0, NULL); 3446139Sjb150015 m_freem(sr->raw_data.chain); 345*8934SJose.Borrego@Sun.COM sr->raw_data.chain = NULL; 3466139Sjb150015 } else { 3476139Sjb150015 (void) smb_session_send(sr->session, 0, &sr->raw_data); 3486139Sjb150015 } 3496139Sjb150015 3506139Sjb150015 return (SDRC_NO_REPLY); 3515331Samw } 3525331Samw 3535331Samw /* 3545331Samw * Read bytes from a file (SMB Core). This request was extended in 3555331Samw * LM 0.12 to support 64-bit offsets, indicated by sending a wct of 3565331Samw * 12 and including additional offset information. 357*8934SJose.Borrego@Sun.COM * 358*8934SJose.Borrego@Sun.COM * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4: 359*8934SJose.Borrego@Sun.COM * If wct is 12 and CAP_LARGE_READX is set, the count may be larger 360*8934SJose.Borrego@Sun.COM * than the negotiated buffer size. If maxcnt_high is 0xFF, it must 361*8934SJose.Borrego@Sun.COM * be ignored. Otherwise, maxcnt_high represents the upper 16 bits 362*8934SJose.Borrego@Sun.COM * of rw_count. 3635331Samw */ 3646030Sjb150015 smb_sdrc_t 3656139Sjb150015 smb_pre_read_andx(smb_request_t *sr) 3665331Samw { 3676139Sjb150015 smb_rw_param_t *param; 3685331Samw uint32_t off_low; 3695331Samw uint32_t off_high; 370*8934SJose.Borrego@Sun.COM uint32_t maxcnt_high; 371*8934SJose.Borrego@Sun.COM uint16_t maxcnt_low; 372*8934SJose.Borrego@Sun.COM uint16_t mincnt; 3735331Samw uint16_t remcnt; 3745331Samw int rc; 3755331Samw 3766139Sjb150015 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 3776139Sjb150015 sr->arg.rw = param; 3786139Sjb150015 3795331Samw if (sr->smb_wct == 12) { 380*8934SJose.Borrego@Sun.COM rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", ¶m->rw_andx, 381*8934SJose.Borrego@Sun.COM &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 382*8934SJose.Borrego@Sun.COM &remcnt, &off_high); 383*8934SJose.Borrego@Sun.COM 384*8934SJose.Borrego@Sun.COM param->rw_offset = ((uint64_t)off_high << 32) | 385*8934SJose.Borrego@Sun.COM (uint64_t)off_low; 3865331Samw 387*8934SJose.Borrego@Sun.COM param->rw_count = (uint32_t)maxcnt_low; 388*8934SJose.Borrego@Sun.COM if (maxcnt_high < 0xFF) 389*8934SJose.Borrego@Sun.COM param->rw_count |= maxcnt_high << 16; 3905331Samw } else { 391*8934SJose.Borrego@Sun.COM rc = smbsr_decode_vwv(sr, "b3.wlwwlw", ¶m->rw_andx, 392*8934SJose.Borrego@Sun.COM &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 393*8934SJose.Borrego@Sun.COM &remcnt); 3945331Samw 3956139Sjb150015 param->rw_offset = (uint64_t)off_low; 396*8934SJose.Borrego@Sun.COM param->rw_count = (uint32_t)maxcnt_low; 3975331Samw } 3985331Samw 3996139Sjb150015 param->rw_mincnt = 0; 4006139Sjb150015 4016139Sjb150015 DTRACE_SMB_2(op__ReadX__start, smb_request_t *, sr, 4026139Sjb150015 smb_rw_param_t *, param); 4036139Sjb150015 4046139Sjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 4056139Sjb150015 } 4065331Samw 4076139Sjb150015 void 4086139Sjb150015 smb_post_read_andx(smb_request_t *sr) 4096139Sjb150015 { 4106139Sjb150015 DTRACE_SMB_2(op__ReadX__done, smb_request_t *, sr, 4116139Sjb150015 smb_rw_param_t *, sr->arg.rw); 4126139Sjb150015 4136139Sjb150015 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 4146139Sjb150015 } 4156139Sjb150015 4166139Sjb150015 smb_sdrc_t 4176139Sjb150015 smb_com_read_andx(smb_request_t *sr) 4186139Sjb150015 { 4196139Sjb150015 smb_rw_param_t *param = sr->arg.rw; 420*8934SJose.Borrego@Sun.COM uint16_t datalen_high; 421*8934SJose.Borrego@Sun.COM uint16_t datalen_low; 422*8934SJose.Borrego@Sun.COM uint16_t data_offset; 4236139Sjb150015 uint16_t offset2; 4246139Sjb150015 int rc; 4255331Samw 426*8934SJose.Borrego@Sun.COM smbsr_lookup_file(sr); 4275331Samw if (sr->fid_ofile == NULL) { 4285772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 4296139Sjb150015 return (SDRC_ERROR); 4305331Samw } 4315331Samw 4327961SNatalie.Li@Sun.COM sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 4337961SNatalie.Li@Sun.COM 434*8934SJose.Borrego@Sun.COM if (param->rw_count >= SMB_READX_MAX) 435*8934SJose.Borrego@Sun.COM param->rw_count = 0; 436*8934SJose.Borrego@Sun.COM 4376139Sjb150015 if ((rc = smb_common_read(sr, param)) != 0) { 4385772Sas200622 smbsr_errno(sr, rc); 4396139Sjb150015 return (SDRC_ERROR); 4405331Samw } 4415331Samw 442*8934SJose.Borrego@Sun.COM datalen_low = param->rw_count & 0xFFFF; 443*8934SJose.Borrego@Sun.COM datalen_high = (param->rw_count >> 16) & 0xFF; 4445331Samw 4455331Samw /* 446*8934SJose.Borrego@Sun.COM * If this is a secondary command, the data offset 447*8934SJose.Borrego@Sun.COM * includes the previous wct + sizeof(wct). 4485331Samw */ 449*8934SJose.Borrego@Sun.COM data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1; 450*8934SJose.Borrego@Sun.COM 4515331Samw if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { 452*8934SJose.Borrego@Sun.COM data_offset += 60; 453*8934SJose.Borrego@Sun.COM offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60; 454*8934SJose.Borrego@Sun.COM 455*8934SJose.Borrego@Sun.COM rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC", 4565331Samw 12, /* wct */ 457*8934SJose.Borrego@Sun.COM param->rw_andx, /* secondary andx command */ 458*8934SJose.Borrego@Sun.COM offset2, /* offset to next command */ 459*8934SJose.Borrego@Sun.COM 0, /* set to 0 for named pipes */ 460*8934SJose.Borrego@Sun.COM datalen_low, /* data byte count */ 461*8934SJose.Borrego@Sun.COM data_offset, /* offset from start to data */ 462*8934SJose.Borrego@Sun.COM datalen_high, /* data byte count */ 4635331Samw VAR_BCC, /* BCC marker */ 464*8934SJose.Borrego@Sun.COM 0x00, /* padding */ 4655331Samw &sr->raw_data); 4665331Samw } else { 467*8934SJose.Borrego@Sun.COM data_offset += 59; 468*8934SJose.Borrego@Sun.COM offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59; 469*8934SJose.Borrego@Sun.COM 470*8934SJose.Borrego@Sun.COM rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC", 4715331Samw 12, /* wct */ 472*8934SJose.Borrego@Sun.COM param->rw_andx, /* secondary andx command */ 473*8934SJose.Borrego@Sun.COM offset2, /* offset to next command */ 474*8934SJose.Borrego@Sun.COM -1, /* must be -1 for regular files */ 475*8934SJose.Borrego@Sun.COM datalen_low, /* data byte count */ 476*8934SJose.Borrego@Sun.COM data_offset, /* offset from start to data */ 477*8934SJose.Borrego@Sun.COM datalen_high, /* data byte count */ 4785331Samw VAR_BCC, /* BCC marker */ 4795331Samw &sr->raw_data); 4805331Samw } 4815331Samw 4826139Sjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 4835331Samw } 4845331Samw 4855331Samw /* 4865331Samw * Common function for reading files or IPC/MSRPC named pipes. All 4875331Samw * protocol read functions should lookup the fid before calling this 4885331Samw * function. We can't move the fid lookup here because lock-and-read 4895331Samw * requires the fid to do locking before attempting the read. 4905331Samw * 4915331Samw * Returns errno values. 4925331Samw */ 4935331Samw int 4946139Sjb150015 smb_common_read(smb_request_t *sr, smb_rw_param_t *param) 4955331Samw { 4965331Samw smb_ofile_t *ofile = sr->fid_ofile; 4975331Samw smb_node_t *node; 4986139Sjb150015 smb_vdb_t *vdb = ¶m->rw_vdb; 4995331Samw struct mbuf *top; 5005331Samw int rc; 5015331Samw 502*8934SJose.Borrego@Sun.COM vdb->vdb_tag = 0; 503*8934SJose.Borrego@Sun.COM vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0]; 504*8934SJose.Borrego@Sun.COM vdb->vdb_uio.uio_iovcnt = MAX_IOVEC; 505*8934SJose.Borrego@Sun.COM vdb->vdb_uio.uio_resid = param->rw_count; 506*8934SJose.Borrego@Sun.COM vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset; 507*8934SJose.Borrego@Sun.COM vdb->vdb_uio.uio_segflg = UIO_SYSSPACE; 5085331Samw 5095331Samw switch (sr->tid_tree->t_res_type & STYPE_MASK) { 5105331Samw case STYPE_DISKTREE: 5115331Samw node = ofile->f_node; 5125331Samw 5135331Samw if (node->attr.sa_vattr.va_type != VDIR) { 5146139Sjb150015 rc = smb_lock_range_access(sr, node, param->rw_offset, 5156139Sjb150015 param->rw_count, B_FALSE); 5165331Samw if (rc != NT_STATUS_SUCCESS) { 5175331Samw rc = ERANGE; 5185331Samw break; 5195331Samw } 5205331Samw } 5215331Samw 522*8934SJose.Borrego@Sun.COM if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) && 523*8934SJose.Borrego@Sun.COM !(sr->smb_flg2 & SMB_FLAGS2_PAGING_IO)) { 524*8934SJose.Borrego@Sun.COM /* 525*8934SJose.Borrego@Sun.COM * SMB_FLAGS2_PAGING_IO: permit execute-only reads. 526*8934SJose.Borrego@Sun.COM * 527*8934SJose.Borrego@Sun.COM * Reject request if the file has been opened 528*8934SJose.Borrego@Sun.COM * execute-only and SMB_FLAGS2_PAGING_IO is not set. 529*8934SJose.Borrego@Sun.COM */ 530*8934SJose.Borrego@Sun.COM rc = EACCES; 531*8934SJose.Borrego@Sun.COM break; 532*8934SJose.Borrego@Sun.COM } 533*8934SJose.Borrego@Sun.COM 5345331Samw (void) smb_sync_fsattr(sr, sr->user_cr, node); 5355331Samw 536*8934SJose.Borrego@Sun.COM sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid; 537*8934SJose.Borrego@Sun.COM top = smb_mbuf_allocate(&vdb->vdb_uio); 5385331Samw 539*8934SJose.Borrego@Sun.COM rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->vdb_uio, 5405331Samw &node->attr); 5415331Samw 542*8934SJose.Borrego@Sun.COM sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid; 5435331Samw smb_mbuf_trim(top, sr->raw_data.max_bytes); 5445331Samw MBC_ATTACH_MBUF(&sr->raw_data, top); 5455331Samw break; 5465331Samw 5475331Samw case STYPE_IPC: 548*8934SJose.Borrego@Sun.COM rc = smb_opipe_read(sr, &vdb->vdb_uio); 5495331Samw break; 5505331Samw 5515331Samw default: 5525331Samw rc = EACCES; 5535331Samw break; 5545331Samw } 5555331Samw 556*8934SJose.Borrego@Sun.COM param->rw_count -= vdb->vdb_uio.uio_resid; 5575331Samw 5585331Samw if (rc != 0) 5595331Samw return (rc); 5605331Samw 5616139Sjb150015 if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) { 5625331Samw /* 5635331Samw * mincnt is only used by read-raw and is typically 5645331Samw * zero. If mincnt is greater than zero and the 5655331Samw * number of bytes read is less than mincnt, tell 5665331Samw * the client that we read nothing. 5675331Samw */ 5686139Sjb150015 param->rw_count = 0; 5695331Samw } 5705331Samw 5716139Sjb150015 param->rw_offset += param->rw_count; 5725331Samw mutex_enter(&sr->fid_ofile->f_mutex); 5736139Sjb150015 ofile->f_seek_pos = param->rw_offset; 5745331Samw mutex_exit(&sr->fid_ofile->f_mutex); 5755331Samw return (rc); 5765331Samw } 577