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 /* 22*2c2961f8Sjose borrego * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw #include <smbsrv/smb_incl.h> 27da6c28aaSamw #include <smbsrv/smb_fsops.h> 28da6c28aaSamw 29da6c28aaSamw 30*2c2961f8Sjose borrego /* 31*2c2961f8Sjose borrego * The maximum number of bytes to return from SMB Core 32*2c2961f8Sjose borrego * SmbRead or SmbLockAndRead. 33*2c2961f8Sjose borrego */ 34*2c2961f8Sjose borrego #define SMB_CORE_READ_MAX 4432 35da6c28aaSamw 36*2c2961f8Sjose borrego /* 37*2c2961f8Sjose borrego * The limit in bytes for SmbReadX. 38*2c2961f8Sjose borrego */ 39*2c2961f8Sjose borrego #define SMB_READX_MAX 0x10000 40*2c2961f8Sjose borrego 41*2c2961f8Sjose borrego int smb_common_read(smb_request_t *, smb_rw_param_t *); 42da6c28aaSamw 43da6c28aaSamw /* 44da6c28aaSamw * Read bytes from a file or named pipe (SMB Core). 45da6c28aaSamw * 46da6c28aaSamw * The requested count specifies the number of bytes desired. Offset 47da6c28aaSamw * is limited to 32 bits, so this client request is inappropriate for 48da6c28aaSamw * files with 64 bit offsets. 49da6c28aaSamw * 50da6c28aaSamw * On return, count is the number of bytes actually being returned, which 51da6c28aaSamw * may be less than the count requested only if a read specifies bytes 52da6c28aaSamw * beyond the current file size. In this case only the bytes that exist 53da6c28aaSamw * are returned. A read completely beyond the end of file results in a 54da6c28aaSamw * response of length zero. This is the only circumstance when a zero 55da6c28aaSamw * length response is generated. A count returned which is less than the 56da6c28aaSamw * count requested is the end of file indicator. 57da6c28aaSamw */ 587b59d02dSjb150015 smb_sdrc_t 59faa1795aSjb150015 smb_pre_read(smb_request_t *sr) 60da6c28aaSamw { 61faa1795aSjb150015 smb_rw_param_t *param; 62da6c28aaSamw uint32_t off_low; 63*2c2961f8Sjose borrego uint16_t count; 64da6c28aaSamw uint16_t remcnt; 65da6c28aaSamw int rc; 66da6c28aaSamw 67faa1795aSjb150015 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 68faa1795aSjb150015 sr->arg.rw = param; 69da6c28aaSamw 70faa1795aSjb150015 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 71*2c2961f8Sjose borrego &count, &off_low, &remcnt); 72faa1795aSjb150015 73faa1795aSjb150015 param->rw_offset = (uint64_t)off_low; 74*2c2961f8Sjose borrego param->rw_count = (uint32_t)count; 75faa1795aSjb150015 param->rw_mincnt = 0; 76faa1795aSjb150015 77faa1795aSjb150015 DTRACE_SMB_2(op__Read__start, smb_request_t *, sr, 78faa1795aSjb150015 smb_rw_param_t *, param); 79faa1795aSjb150015 80faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 81faa1795aSjb150015 } 82faa1795aSjb150015 83faa1795aSjb150015 void 84faa1795aSjb150015 smb_post_read(smb_request_t *sr) 85faa1795aSjb150015 { 86faa1795aSjb150015 DTRACE_SMB_2(op__Read__done, smb_request_t *, sr, 87faa1795aSjb150015 smb_rw_param_t *, sr->arg.rw); 88faa1795aSjb150015 89faa1795aSjb150015 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 90faa1795aSjb150015 } 91faa1795aSjb150015 92faa1795aSjb150015 smb_sdrc_t 93faa1795aSjb150015 smb_com_read(smb_request_t *sr) 94faa1795aSjb150015 { 95faa1795aSjb150015 smb_rw_param_t *param = sr->arg.rw; 96*2c2961f8Sjose borrego uint16_t count; 97faa1795aSjb150015 int rc; 98da6c28aaSamw 99*2c2961f8Sjose borrego smbsr_lookup_file(sr); 100da6c28aaSamw if (sr->fid_ofile == NULL) { 101dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 102faa1795aSjb150015 return (SDRC_ERROR); 103da6c28aaSamw } 104da6c28aaSamw 105b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 106b89a8333Snatalie li - Sun Microsystems - Irvine United States 107*2c2961f8Sjose borrego if (param->rw_count > SMB_CORE_READ_MAX) 108*2c2961f8Sjose borrego param->rw_count = SMB_CORE_READ_MAX; 109*2c2961f8Sjose borrego 110faa1795aSjb150015 if ((rc = smb_common_read(sr, param)) != 0) { 111dc20a302Sas200622 smbsr_errno(sr, rc); 112faa1795aSjb150015 return (SDRC_ERROR); 113da6c28aaSamw } 114da6c28aaSamw 115*2c2961f8Sjose borrego count = (uint16_t)param->rw_count; 1167b59d02dSjb150015 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 117*2c2961f8Sjose borrego 5, count, VAR_BCC, 0x01, count, &sr->raw_data); 118da6c28aaSamw 119faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 120da6c28aaSamw } 121da6c28aaSamw 122da6c28aaSamw /* 123da6c28aaSamw * Lock and read bytes from a file (SMB Core Plus). The SmbLockAndRead/ 124da6c28aaSamw * SmbLockAndWrite sub-dialect is only valid on disk files: reject any 125da6c28aaSamw * attempt to use it on non-disk shares. 126da6c28aaSamw * 127da6c28aaSamw * The requested count specifies the number of bytes desired. Offset 128da6c28aaSamw * specifies the offset in the file of the first byte to be locked then 129da6c28aaSamw * read. Note that offset is limited to 32 bits, so this client request 130da6c28aaSamw * is inappropriate for files with 64 bit offsets. 131da6c28aaSamw * 132da6c28aaSamw * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted 133da6c28aaSamw * immediately an error should be returned to the client. If an error 134da6c28aaSamw * occurs on the lock, the bytes should not be read. 135da6c28aaSamw * 136da6c28aaSamw * On return, count is the number of bytes actually being returned, which 137da6c28aaSamw * may be less than the count requested only if a read specifies bytes 138da6c28aaSamw * beyond the current file size. In this case only the bytes that exist 139da6c28aaSamw * are returned. A read completely beyond the end of file results in a 140da6c28aaSamw * response of length zero. This is the only circumstance when a zero 141da6c28aaSamw * length response is generated. A count returned which is less than the 142da6c28aaSamw * count requested is the end of file indicator. 143da6c28aaSamw */ 1447b59d02dSjb150015 smb_sdrc_t 145faa1795aSjb150015 smb_pre_lock_and_read(smb_request_t *sr) 146da6c28aaSamw { 147faa1795aSjb150015 smb_rw_param_t *param; 148da6c28aaSamw uint32_t off_low; 149*2c2961f8Sjose borrego uint16_t count; 150*2c2961f8Sjose borrego uint16_t remcnt; 151faa1795aSjb150015 int rc; 152faa1795aSjb150015 153faa1795aSjb150015 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 154faa1795aSjb150015 sr->arg.rw = param; 155faa1795aSjb150015 156faa1795aSjb150015 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 157*2c2961f8Sjose borrego &count, &off_low, &remcnt); 158faa1795aSjb150015 159faa1795aSjb150015 param->rw_offset = (uint64_t)off_low; 160*2c2961f8Sjose borrego param->rw_count = (uint32_t)count; 161faa1795aSjb150015 param->rw_mincnt = 0; 162faa1795aSjb150015 163faa1795aSjb150015 DTRACE_SMB_2(op__LockAndRead__start, smb_request_t *, sr, 164faa1795aSjb150015 smb_rw_param_t *, param); 165faa1795aSjb150015 166faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 167faa1795aSjb150015 } 168faa1795aSjb150015 169faa1795aSjb150015 void 170faa1795aSjb150015 smb_post_lock_and_read(smb_request_t *sr) 171faa1795aSjb150015 { 172faa1795aSjb150015 DTRACE_SMB_2(op__LockAndRead__done, smb_request_t *, sr, 173faa1795aSjb150015 smb_rw_param_t *, sr->arg.rw); 174faa1795aSjb150015 175faa1795aSjb150015 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 176faa1795aSjb150015 } 177faa1795aSjb150015 178faa1795aSjb150015 smb_sdrc_t 179faa1795aSjb150015 smb_com_lock_and_read(smb_request_t *sr) 180faa1795aSjb150015 { 181faa1795aSjb150015 smb_rw_param_t *param = sr->arg.rw; 182faa1795aSjb150015 DWORD status; 183*2c2961f8Sjose borrego uint16_t count; 184da6c28aaSamw int rc; 185da6c28aaSamw 186da6c28aaSamw if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { 187dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); 188faa1795aSjb150015 return (SDRC_ERROR); 189da6c28aaSamw } 190da6c28aaSamw 191*2c2961f8Sjose borrego smbsr_lookup_file(sr); 192da6c28aaSamw if (sr->fid_ofile == NULL) { 193dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 194faa1795aSjb150015 return (SDRC_ERROR); 195da6c28aaSamw } 196da6c28aaSamw 197b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 198b89a8333Snatalie li - Sun Microsystems - Irvine United States 1996537f381Sas200622 status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count, 200*2c2961f8Sjose borrego 0, SMB_LOCK_TYPE_READWRITE); 201*2c2961f8Sjose borrego 202faa1795aSjb150015 if (status != NT_STATUS_SUCCESS) { 203faa1795aSjb150015 smb_lock_range_error(sr, status); 204faa1795aSjb150015 return (SDRC_ERROR); 205da6c28aaSamw } 206da6c28aaSamw 207*2c2961f8Sjose borrego if (param->rw_count > SMB_CORE_READ_MAX) 208*2c2961f8Sjose borrego param->rw_count = SMB_CORE_READ_MAX; 209*2c2961f8Sjose borrego 210faa1795aSjb150015 if ((rc = smb_common_read(sr, param)) != 0) { 211dc20a302Sas200622 smbsr_errno(sr, rc); 212faa1795aSjb150015 return (SDRC_ERROR); 213da6c28aaSamw } 214da6c28aaSamw 215*2c2961f8Sjose borrego count = (uint16_t)param->rw_count; 2167b59d02dSjb150015 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 217*2c2961f8Sjose borrego 5, count, VAR_BCC, 0x1, count, &sr->raw_data); 218da6c28aaSamw 219faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 220da6c28aaSamw } 221da6c28aaSamw 222da6c28aaSamw /* 223da6c28aaSamw * The SMB_COM_READ_RAW protocol is a negotiated option introduced in 224da6c28aaSamw * SMB Core Plus to maximize performance when reading a large block 225da6c28aaSamw * of data from a server. This request was extended in LM 0.12 to 226da6c28aaSamw * support 64-bit offsets; the server can indicate support by setting 227da6c28aaSamw * CAP_LARGE_FILES in the negotiated capabilities. 228da6c28aaSamw * 229da6c28aaSamw * The client must guarantee that there is (and will be) no other request 230da6c28aaSamw * to the server for the duration of the SMB_COM_READ_RAW, since the 231da6c28aaSamw * server response has no header or trailer. To help ensure that there 232da6c28aaSamw * are no interruptions, we block all I/O for the session during read raw. 233da6c28aaSamw * 234da6c28aaSamw * If this is the first SMB request received since we sent an oplock break 235da6c28aaSamw * to this client, we don't know if it's safe to send the raw data because 236da6c28aaSamw * the requests may have crossed on the wire and the client may have 237da6c28aaSamw * interpreted the oplock break as part of the raw data. To avoid problems, 238da6c28aaSamw * we send a zero length session packet, which will force the client to 239da6c28aaSamw * retry the read. 240da6c28aaSamw * 241*2c2961f8Sjose borrego * Do not return errors from SmbReadRaw. 242da6c28aaSamw * Read errors are handled by sending a zero length response. 243da6c28aaSamw */ 2447b59d02dSjb150015 smb_sdrc_t 245faa1795aSjb150015 smb_pre_read_raw(smb_request_t *sr) 246da6c28aaSamw { 247faa1795aSjb150015 smb_rw_param_t *param; 248da6c28aaSamw uint32_t off_low; 249da6c28aaSamw uint32_t off_high; 250da6c28aaSamw uint32_t timeout; 251*2c2961f8Sjose borrego uint16_t count; 252da6c28aaSamw int rc; 253da6c28aaSamw 254faa1795aSjb150015 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 255faa1795aSjb150015 sr->arg.rw = param; 256faa1795aSjb150015 257da6c28aaSamw if (sr->smb_wct == 8) { 258da6c28aaSamw rc = smbsr_decode_vwv(sr, "wlwwl2.", &sr->smb_fid, 259*2c2961f8Sjose borrego &off_low, &count, ¶m->rw_mincnt, &timeout); 260*2c2961f8Sjose borrego if (rc == 0) { 261faa1795aSjb150015 param->rw_offset = (uint64_t)off_low; 262*2c2961f8Sjose borrego param->rw_count = (uint32_t)count; 263*2c2961f8Sjose borrego } 264da6c28aaSamw } else { 265da6c28aaSamw rc = smbsr_decode_vwv(sr, "wlwwl2.l", &sr->smb_fid, 266*2c2961f8Sjose borrego &off_low, &count, ¶m->rw_mincnt, &timeout, &off_high); 267*2c2961f8Sjose borrego if (rc == 0) { 268faa1795aSjb150015 param->rw_offset = ((uint64_t)off_high << 32) | off_low; 269*2c2961f8Sjose borrego param->rw_count = (uint32_t)count; 270*2c2961f8Sjose borrego } 271da6c28aaSamw } 272da6c28aaSamw 273faa1795aSjb150015 DTRACE_SMB_2(op__ReadRaw__start, smb_request_t *, sr, 274faa1795aSjb150015 smb_rw_param_t *, param); 275da6c28aaSamw 276*2c2961f8Sjose borrego return (SDRC_SUCCESS); 277faa1795aSjb150015 } 278faa1795aSjb150015 279faa1795aSjb150015 void 280faa1795aSjb150015 smb_post_read_raw(smb_request_t *sr) 281faa1795aSjb150015 { 282*2c2961f8Sjose borrego mbuf_chain_t *mbc; 283*2c2961f8Sjose borrego 284*2c2961f8Sjose borrego if (sr->session->s_state == SMB_SESSION_STATE_READ_RAW_ACTIVE) { 285*2c2961f8Sjose borrego sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; 286*2c2961f8Sjose borrego 287*2c2961f8Sjose borrego while ((mbc = list_head(&sr->session->s_oplock_brkreqs)) != 288*2c2961f8Sjose borrego NULL) { 289*2c2961f8Sjose borrego SMB_MBC_VALID(mbc); 290*2c2961f8Sjose borrego list_remove(&sr->session->s_oplock_brkreqs, mbc); 291*2c2961f8Sjose borrego (void) smb_session_send(sr->session, 0, mbc); 292*2c2961f8Sjose borrego smb_mbc_free(mbc); 293*2c2961f8Sjose borrego } 294*2c2961f8Sjose borrego } 295*2c2961f8Sjose borrego 296faa1795aSjb150015 DTRACE_SMB_2(op__ReadRaw__done, smb_request_t *, sr, 297faa1795aSjb150015 smb_rw_param_t *, sr->arg.rw); 298faa1795aSjb150015 299faa1795aSjb150015 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 300faa1795aSjb150015 } 301faa1795aSjb150015 302faa1795aSjb150015 smb_sdrc_t 303faa1795aSjb150015 smb_com_read_raw(smb_request_t *sr) 304faa1795aSjb150015 { 305faa1795aSjb150015 smb_rw_param_t *param = sr->arg.rw; 306faa1795aSjb150015 307faa1795aSjb150015 switch (sr->session->s_state) { 308faa1795aSjb150015 case SMB_SESSION_STATE_NEGOTIATED: 309*2c2961f8Sjose borrego sr->session->s_state = SMB_SESSION_STATE_READ_RAW_ACTIVE; 310faa1795aSjb150015 break; 311faa1795aSjb150015 312faa1795aSjb150015 case SMB_SESSION_STATE_OPLOCK_BREAKING: 313faa1795aSjb150015 (void) smb_session_send(sr->session, 0, NULL); 314faa1795aSjb150015 return (SDRC_NO_REPLY); 315faa1795aSjb150015 316faa1795aSjb150015 case SMB_SESSION_STATE_TERMINATED: 317faa1795aSjb150015 case SMB_SESSION_STATE_DISCONNECTED: 318faa1795aSjb150015 return (SDRC_NO_REPLY); 319faa1795aSjb150015 320*2c2961f8Sjose borrego case SMB_SESSION_STATE_READ_RAW_ACTIVE: 321*2c2961f8Sjose borrego sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; 322*2c2961f8Sjose borrego return (SDRC_DROP_VC); 323*2c2961f8Sjose borrego 324faa1795aSjb150015 case SMB_SESSION_STATE_WRITE_RAW_ACTIVE: 325faa1795aSjb150015 case SMB_SESSION_STATE_CONNECTED: 326faa1795aSjb150015 case SMB_SESSION_STATE_ESTABLISHED: 327faa1795aSjb150015 default: 328faa1795aSjb150015 return (SDRC_DROP_VC); 329faa1795aSjb150015 } 330faa1795aSjb150015 331*2c2961f8Sjose borrego smbsr_lookup_file(sr); 332da6c28aaSamw if (sr->fid_ofile == NULL) { 333*2c2961f8Sjose borrego (void) smb_session_send(sr->session, 0, NULL); 334*2c2961f8Sjose borrego return (SDRC_NO_REPLY); 335da6c28aaSamw } 336da6c28aaSamw 337b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 338b89a8333Snatalie li - Sun Microsystems - Irvine United States 339*2c2961f8Sjose borrego if (param->rw_mincnt > param->rw_count) 340*2c2961f8Sjose borrego param->rw_mincnt = 0; 341faa1795aSjb150015 342*2c2961f8Sjose borrego if (smb_common_read(sr, param) != 0) { 343da6c28aaSamw (void) smb_session_send(sr->session, 0, NULL); 344da6c28aaSamw m_freem(sr->raw_data.chain); 345*2c2961f8Sjose borrego sr->raw_data.chain = NULL; 346da6c28aaSamw } else { 347da6c28aaSamw (void) smb_session_send(sr->session, 0, &sr->raw_data); 348da6c28aaSamw } 349faa1795aSjb150015 350da6c28aaSamw return (SDRC_NO_REPLY); 351da6c28aaSamw } 352da6c28aaSamw 353da6c28aaSamw /* 354da6c28aaSamw * Read bytes from a file (SMB Core). This request was extended in 355da6c28aaSamw * LM 0.12 to support 64-bit offsets, indicated by sending a wct of 356da6c28aaSamw * 12 and including additional offset information. 357*2c2961f8Sjose borrego * 358*2c2961f8Sjose borrego * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4: 359*2c2961f8Sjose borrego * If wct is 12 and CAP_LARGE_READX is set, the count may be larger 360*2c2961f8Sjose borrego * than the negotiated buffer size. If maxcnt_high is 0xFF, it must 361*2c2961f8Sjose borrego * be ignored. Otherwise, maxcnt_high represents the upper 16 bits 362*2c2961f8Sjose borrego * of rw_count. 363da6c28aaSamw */ 3647b59d02dSjb150015 smb_sdrc_t 365faa1795aSjb150015 smb_pre_read_andx(smb_request_t *sr) 366da6c28aaSamw { 367faa1795aSjb150015 smb_rw_param_t *param; 368da6c28aaSamw uint32_t off_low; 369da6c28aaSamw uint32_t off_high; 370*2c2961f8Sjose borrego uint32_t maxcnt_high; 371*2c2961f8Sjose borrego uint16_t maxcnt_low; 372*2c2961f8Sjose borrego uint16_t mincnt; 373da6c28aaSamw uint16_t remcnt; 374da6c28aaSamw int rc; 375da6c28aaSamw 376faa1795aSjb150015 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 377faa1795aSjb150015 sr->arg.rw = param; 378faa1795aSjb150015 379da6c28aaSamw if (sr->smb_wct == 12) { 380*2c2961f8Sjose borrego rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", ¶m->rw_andx, 381*2c2961f8Sjose borrego &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 382*2c2961f8Sjose borrego &remcnt, &off_high); 383da6c28aaSamw 384*2c2961f8Sjose borrego param->rw_offset = ((uint64_t)off_high << 32) | 385*2c2961f8Sjose borrego (uint64_t)off_low; 386*2c2961f8Sjose borrego 387*2c2961f8Sjose borrego param->rw_count = (uint32_t)maxcnt_low; 388*2c2961f8Sjose borrego if (maxcnt_high < 0xFF) 389*2c2961f8Sjose borrego param->rw_count |= maxcnt_high << 16; 390da6c28aaSamw } else { 391*2c2961f8Sjose borrego rc = smbsr_decode_vwv(sr, "b3.wlwwlw", ¶m->rw_andx, 392*2c2961f8Sjose borrego &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 393*2c2961f8Sjose borrego &remcnt); 394da6c28aaSamw 395faa1795aSjb150015 param->rw_offset = (uint64_t)off_low; 396*2c2961f8Sjose borrego param->rw_count = (uint32_t)maxcnt_low; 397da6c28aaSamw } 398da6c28aaSamw 399faa1795aSjb150015 param->rw_mincnt = 0; 400da6c28aaSamw 401faa1795aSjb150015 DTRACE_SMB_2(op__ReadX__start, smb_request_t *, sr, 402faa1795aSjb150015 smb_rw_param_t *, param); 403faa1795aSjb150015 404faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 405faa1795aSjb150015 } 406faa1795aSjb150015 407faa1795aSjb150015 void 408faa1795aSjb150015 smb_post_read_andx(smb_request_t *sr) 409faa1795aSjb150015 { 410faa1795aSjb150015 DTRACE_SMB_2(op__ReadX__done, smb_request_t *, sr, 411faa1795aSjb150015 smb_rw_param_t *, sr->arg.rw); 412faa1795aSjb150015 413faa1795aSjb150015 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 414faa1795aSjb150015 } 415faa1795aSjb150015 416faa1795aSjb150015 smb_sdrc_t 417faa1795aSjb150015 smb_com_read_andx(smb_request_t *sr) 418faa1795aSjb150015 { 419faa1795aSjb150015 smb_rw_param_t *param = sr->arg.rw; 420*2c2961f8Sjose borrego uint16_t datalen_high; 421*2c2961f8Sjose borrego uint16_t datalen_low; 422*2c2961f8Sjose borrego uint16_t data_offset; 423faa1795aSjb150015 uint16_t offset2; 424faa1795aSjb150015 int rc; 425da6c28aaSamw 426*2c2961f8Sjose borrego smbsr_lookup_file(sr); 427da6c28aaSamw if (sr->fid_ofile == NULL) { 428dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 429faa1795aSjb150015 return (SDRC_ERROR); 430da6c28aaSamw } 431da6c28aaSamw 432b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 433b89a8333Snatalie li - Sun Microsystems - Irvine United States 434*2c2961f8Sjose borrego if (param->rw_count >= SMB_READX_MAX) 435*2c2961f8Sjose borrego param->rw_count = 0; 436*2c2961f8Sjose borrego 437faa1795aSjb150015 if ((rc = smb_common_read(sr, param)) != 0) { 438dc20a302Sas200622 smbsr_errno(sr, rc); 439faa1795aSjb150015 return (SDRC_ERROR); 440da6c28aaSamw } 441da6c28aaSamw 442*2c2961f8Sjose borrego datalen_low = param->rw_count & 0xFFFF; 443*2c2961f8Sjose borrego datalen_high = (param->rw_count >> 16) & 0xFF; 444da6c28aaSamw 445da6c28aaSamw /* 446*2c2961f8Sjose borrego * If this is a secondary command, the data offset 447*2c2961f8Sjose borrego * includes the previous wct + sizeof(wct). 448da6c28aaSamw */ 449*2c2961f8Sjose borrego data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1; 450*2c2961f8Sjose borrego 451da6c28aaSamw if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { 452*2c2961f8Sjose borrego data_offset += 60; 453*2c2961f8Sjose borrego offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60; 454*2c2961f8Sjose borrego 455*2c2961f8Sjose borrego rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC", 456da6c28aaSamw 12, /* wct */ 457*2c2961f8Sjose borrego param->rw_andx, /* secondary andx command */ 458*2c2961f8Sjose borrego offset2, /* offset to next command */ 459*2c2961f8Sjose borrego 0, /* set to 0 for named pipes */ 460*2c2961f8Sjose borrego datalen_low, /* data byte count */ 461*2c2961f8Sjose borrego data_offset, /* offset from start to data */ 462*2c2961f8Sjose borrego datalen_high, /* data byte count */ 463da6c28aaSamw VAR_BCC, /* BCC marker */ 464*2c2961f8Sjose borrego 0x00, /* padding */ 465da6c28aaSamw &sr->raw_data); 466da6c28aaSamw } else { 467*2c2961f8Sjose borrego data_offset += 59; 468*2c2961f8Sjose borrego offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59; 469*2c2961f8Sjose borrego 470*2c2961f8Sjose borrego rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC", 471da6c28aaSamw 12, /* wct */ 472*2c2961f8Sjose borrego param->rw_andx, /* secondary andx command */ 473*2c2961f8Sjose borrego offset2, /* offset to next command */ 474*2c2961f8Sjose borrego -1, /* must be -1 for regular files */ 475*2c2961f8Sjose borrego datalen_low, /* data byte count */ 476*2c2961f8Sjose borrego data_offset, /* offset from start to data */ 477*2c2961f8Sjose borrego datalen_high, /* data byte count */ 478da6c28aaSamw VAR_BCC, /* BCC marker */ 479da6c28aaSamw &sr->raw_data); 480da6c28aaSamw } 481da6c28aaSamw 482faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 483da6c28aaSamw } 484da6c28aaSamw 485da6c28aaSamw /* 486da6c28aaSamw * Common function for reading files or IPC/MSRPC named pipes. All 487da6c28aaSamw * protocol read functions should lookup the fid before calling this 488da6c28aaSamw * function. We can't move the fid lookup here because lock-and-read 489da6c28aaSamw * requires the fid to do locking before attempting the read. 490da6c28aaSamw * 491da6c28aaSamw * Returns errno values. 492da6c28aaSamw */ 493da6c28aaSamw int 494faa1795aSjb150015 smb_common_read(smb_request_t *sr, smb_rw_param_t *param) 495da6c28aaSamw { 496da6c28aaSamw smb_ofile_t *ofile = sr->fid_ofile; 497da6c28aaSamw smb_node_t *node; 498faa1795aSjb150015 smb_vdb_t *vdb = ¶m->rw_vdb; 499da6c28aaSamw struct mbuf *top; 500da6c28aaSamw int rc; 501da6c28aaSamw 502*2c2961f8Sjose borrego vdb->vdb_tag = 0; 503*2c2961f8Sjose borrego vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0]; 504*2c2961f8Sjose borrego vdb->vdb_uio.uio_iovcnt = MAX_IOVEC; 505*2c2961f8Sjose borrego vdb->vdb_uio.uio_resid = param->rw_count; 506*2c2961f8Sjose borrego vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset; 507*2c2961f8Sjose borrego vdb->vdb_uio.uio_segflg = UIO_SYSSPACE; 508da6c28aaSamw 509da6c28aaSamw switch (sr->tid_tree->t_res_type & STYPE_MASK) { 510da6c28aaSamw case STYPE_DISKTREE: 511da6c28aaSamw node = ofile->f_node; 512da6c28aaSamw 513da6c28aaSamw if (node->attr.sa_vattr.va_type != VDIR) { 514faa1795aSjb150015 rc = smb_lock_range_access(sr, node, param->rw_offset, 515faa1795aSjb150015 param->rw_count, B_FALSE); 516da6c28aaSamw if (rc != NT_STATUS_SUCCESS) { 517da6c28aaSamw rc = ERANGE; 518da6c28aaSamw break; 519da6c28aaSamw } 520da6c28aaSamw } 521da6c28aaSamw 522*2c2961f8Sjose borrego if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) && 523*2c2961f8Sjose borrego !(sr->smb_flg2 & SMB_FLAGS2_PAGING_IO)) { 524*2c2961f8Sjose borrego /* 525*2c2961f8Sjose borrego * SMB_FLAGS2_PAGING_IO: permit execute-only reads. 526*2c2961f8Sjose borrego * 527*2c2961f8Sjose borrego * Reject request if the file has been opened 528*2c2961f8Sjose borrego * execute-only and SMB_FLAGS2_PAGING_IO is not set. 529*2c2961f8Sjose borrego */ 530*2c2961f8Sjose borrego rc = EACCES; 531*2c2961f8Sjose borrego break; 532*2c2961f8Sjose borrego } 533*2c2961f8Sjose borrego 534da6c28aaSamw (void) smb_sync_fsattr(sr, sr->user_cr, node); 535da6c28aaSamw 536*2c2961f8Sjose borrego sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid; 537*2c2961f8Sjose borrego top = smb_mbuf_allocate(&vdb->vdb_uio); 538da6c28aaSamw 539*2c2961f8Sjose borrego rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->vdb_uio, 540da6c28aaSamw &node->attr); 541da6c28aaSamw 542*2c2961f8Sjose borrego sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid; 543da6c28aaSamw smb_mbuf_trim(top, sr->raw_data.max_bytes); 544da6c28aaSamw MBC_ATTACH_MBUF(&sr->raw_data, top); 545da6c28aaSamw break; 546da6c28aaSamw 547da6c28aaSamw case STYPE_IPC: 548*2c2961f8Sjose borrego rc = smb_opipe_read(sr, &vdb->vdb_uio); 549da6c28aaSamw break; 550da6c28aaSamw 551da6c28aaSamw default: 552da6c28aaSamw rc = EACCES; 553da6c28aaSamw break; 554da6c28aaSamw } 555da6c28aaSamw 556*2c2961f8Sjose borrego param->rw_count -= vdb->vdb_uio.uio_resid; 557da6c28aaSamw 558da6c28aaSamw if (rc != 0) 559da6c28aaSamw return (rc); 560da6c28aaSamw 561faa1795aSjb150015 if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) { 562da6c28aaSamw /* 563da6c28aaSamw * mincnt is only used by read-raw and is typically 564da6c28aaSamw * zero. If mincnt is greater than zero and the 565da6c28aaSamw * number of bytes read is less than mincnt, tell 566da6c28aaSamw * the client that we read nothing. 567da6c28aaSamw */ 568faa1795aSjb150015 param->rw_count = 0; 569da6c28aaSamw } 570da6c28aaSamw 571faa1795aSjb150015 param->rw_offset += param->rw_count; 572da6c28aaSamw mutex_enter(&sr->fid_ofile->f_mutex); 573faa1795aSjb150015 ofile->f_seek_pos = param->rw_offset; 574da6c28aaSamw mutex_exit(&sr->fid_ofile->f_mutex); 575da6c28aaSamw return (rc); 576da6c28aaSamw } 577