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