smb_read.c revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#pragma ident "%Z%%M% %I% %E% SMI"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef struct smb_read_param {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint smb_common_read(struct smb_request *sr, smb_read_param_t *param);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Read bytes from a file or named pipe (SMB Core).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The requested count specifies the number of bytes desired. Offset
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is limited to 32 bits, so this client request is inappropriate for
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * files with 64 bit offsets.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * On return, count is the number of bytes actually being returned, which
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * may be less than the count requested only if a read specifies bytes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * beyond the current file size. In this case only the bytes that exist
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * are returned. A read completely beyond the end of file results in a
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * response of length zero. This is the only circumstance when a zero
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * length response is generated. A count returned which is less than the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * count requested is the end of file indicator.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NOTREACHED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NOTREACHED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NOTREACHED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 5, param.r_count, VAR_BCC, 0x01, param.r_count, &sr->raw_data);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Lock and read bytes from a file (SMB Core Plus). The SmbLockAndRead/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SmbLockAndWrite sub-dialect is only valid on disk files: reject any
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * attempt to use it on non-disk shares.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The requested count specifies the number of bytes desired. Offset
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * specifies the offset in the file of the first byte to be locked then
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * read. Note that offset is limited to 32 bits, so this client request
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is inappropriate for files with 64 bit offsets.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * immediately an error should be returned to the client. If an error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * occurs on the lock, the bytes should not be read.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * On return, count is the number of bytes actually being returned, which
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * may be less than the count requested only if a read specifies bytes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * beyond the current file size. In this case only the bytes that exist
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * are returned. A read completely beyond the end of file results in a
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * response of length zero. This is the only circumstance when a zero
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * length response is generated. A count returned which is less than the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * count requested is the end of file indicator.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NOTREACHED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NOTREACHED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NOTREACHED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw result = smb_lock_range(sr, sr->fid_ofile, param.r_offset,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (uint64_t)param.r_count, 0xffffffff, SMB_LOCK_TYPE_READWRITE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NOTREACHED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 5, param.r_count, VAR_BCC, 0x1, param.r_count, &sr->raw_data);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The SMB_COM_READ_RAW protocol is a negotiated option introduced in
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SMB Core Plus to maximize performance when reading a large block
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * of data from a server. This request was extended in LM 0.12 to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * support 64-bit offsets; the server can indicate support by setting
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CAP_LARGE_FILES in the negotiated capabilities.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The client must guarantee that there is (and will be) no other request
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to the server for the duration of the SMB_COM_READ_RAW, since the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * server response has no header or trailer. To help ensure that there
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * are no interruptions, we block all I/O for the session during read raw.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If this is the first SMB request received since we sent an oplock break
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to this client, we don't know if it's safe to send the raw data because
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the requests may have crossed on the wire and the client may have
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * interpreted the oplock break as part of the raw data. To avoid problems,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * we send a zero length session packet, which will force the client to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * retry the read.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Read errors are handled by sending a zero length response.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NOTREACHED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NOTREACHED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * XXX Do we need to handle errors here? What if we have an
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * access error (either permissions or range lock violations?
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Read bytes from a file (SMB Core). This request was extended in
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 12 and including additional offset information.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &sr->smb_fid, &off_low, ¶m.r_count, &remcnt, &off_high);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NOTREACHED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NOTREACHED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NOTREACHED */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Ensure that the next response offset is zero
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * if there is no secondary command.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The STYPE_IPC response format is different.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The unknown value (2) may be to indicate that it
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is a follow-up to an earlier RPC transaction.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.ww10.wbC",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 0, /* must be 0 */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common function for reading files or IPC/MSRPC named pipes. All
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * protocol read functions should lookup the fid before calling this
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * function. We can't move the fid lookup here because lock-and-read
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * requires the fid to do locking before attempting the read.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns errno values.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_common_read(struct smb_request *sr, smb_read_param_t *param)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vdb = kmem_alloc(sizeof (struct vardata_block), KM_SLEEP);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (param->r_mincnt != 0 && param->r_count < param->r_mincnt) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mincnt is only used by read-raw and is typically
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * zero. If mincnt is greater than zero and the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * number of bytes read is less than mincnt, tell
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the client that we read nothing.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The Read Block Multiplexed protocol is used to maximize performance
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * when reading a large block of data from server to client while still
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * allowing other operations to take place between the client and server
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in parallel.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The mpx sub protocol is not supported because we support only
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * connection oriented transports and NT supports SMB_COM_READ_MPX
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * only over connectionless transports.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/