3.3.5.12 Receiving an SMB2 READ Request

When the server receives a request with an SMB2 header with a Command value equal to SMB2 READ, message handling proceeds as follows:

The server MUST locate the session, as specified in section 3.3.5.2.9.

The server MUST locate the tree connection, as specified in section 3.3.5.2.11.

Next the server MUST locate the open that is being read from, by performing a lookup in the Session.OpenTable, using the FileId.Volatile of the request as the lookup key. If no open is found, or if Open.DurableFileId is not equal to FileId.Persistent, the server MUST fail the request with STATUS_FILE_CLOSED. Otherwise, the server MUST locate the Request in Connection.RequestList for which Request.MessageId matches the MessageId value in the SMB2 header, and set Request.Open to the Open.

If Open.GrantedAccess does not allow for FILE_READ_DATA, the request MUST be failed with STATUS_ACCESS_DENIED.

The server SHOULD<315> fail the request with STATUS_INVALID_PARAMETER if the Length field is greater than Connection.MaxReadSize.

If Connection.SupportsMultiCredit is TRUE the server MUST validate CreditCharge based on Length, as specified in section 3.3.5.2.5. If the validation fails, it MUST fail the read request with STATUS_INVALID_PARAMETER.

If the server implements the SMB 3.0.2 or SMB 3.1.1 dialect, the read is being executed on a named pipe, and the SMB2_READFLAG_READ_UNBUFFERED bit is set in the Flags field, the server MUST fail the request with STATUS_INVALID_PARAMETER.

If Connection.Dialect belongs to the SMB 3.x dialect family and if any of the following conditions are TRUE, the server MUST fail the request with STATUS_INVALID_PARAMETER:

  • Connection.Dialect is "3.0.2" or "3.1.1" and Channel is not equal to SMB2_CHANNEL_RDMA_V1_INVALIDATE or SMB2_CHANNEL_RDMA_V1 or SMB2_CHANNEL_NONE.

  • Connection.Dialect is "3.0" and Channel is not equal to SMB2_CHANNEL_RDMA_V1 or SMB2_CHANNEL_NONE.

  • Channel is equal to SMB2_CHANNEL_RDMA_V1 or SMB2_CHANNEL_RDMA_V1_INVALIDATE and any of the following conditions is TRUE:

    • The underlying Connection is not RDMA.

    • Length, ReadChannelInfoOffset, or ReadChannelInfoLength is equal to 0.

The server MUST issue a read to the underlying object store represented by Open.LocalOpen for the length, in bytes, given by Length, at the offset, in bytes, from the beginning of the file, provided in Offset. If the server implements the SMB 3.0.2 or SMB 3.1.1 dialect and if the SMB2_READFLAG_READ_UNBUFFERED bit is set in the Flags field of the request, the server SHOULD<316> indicate to the underlying object store not to buffer the read data.

If the read is being executed on a named pipe, and the pipe is in blocking mode (the default), the operation could block for a long time, so the server MAY<317> choose to handle it asynchronously, as specified in section 3.3.4.2. To query a pipe's blocking mode, use the FilePipeInformation file information class, as specified in [MS-FSCC] section 2.4.29. To change a pipe's blocking mode, use an SMB2 SET_INFO Request with the FilePipeInformation file information class, as specified in [MS-FSCC] section 2.4.29.<318> If the read is not finished in 0.5 milliseconds, the server MUST send an interim response to the client.

If the read fails, the server MUST fail the request using the error code received from the read operation. If the read returns fewer bytes than specified by the MinimumCount field of the request, the server MUST fail the request with STATUS_END_OF_FILE.

If the read succeeds, the server MUST construct a read response using the syntax specified in section 2.2.20 with the following values.

If the request Channel field contains the value SMB2_CHANNEL_NONE, then:

  • DataOffset MUST be set to the offset into the response, in bytes, from the beginning of the SMB2 header where the data is located.

  • The data MUST be copied into the response.

  • DataLength MUST be set to the number of bytes returned.

  • DataRemaining MUST be set to zero.

If IsCompressionSupported is TRUE, Connection.CompressionIds is not empty, underlying Connection is not RDMA, and Flags field in the request includes SMB2_READFLAG_REQUEST_COMPRESSED, Request.CompressReply MUST be set to TRUE.

If the request Channel field contains the value SMB2_CHANNEL_RDMA_V1 or SMB2_CHANNEL_RDMA_V1_INVALIDATE, the server MUST do the following:

  • If Connection.Dialect is “3.1.1”, Request.IsEncrypted is TRUE, and Connection.RDMATransformIds includes SMB2_RDMA_TRANSFORM_ENCRYPTION, the server MUST do the following:

    • Construct SMB2_RDMA_TRANSFORM structure by setting Channel to SMB2_CHANNEL_NONE, TransformCount to 1, and RdmaDescriptorOffset and RdmaDescriptorLength to zero.

    • Construct SMB2_RDMA_ENCRYPTION_TRANSFORM structure with the following values:

      • If Connection.CipherID is AES-128-CCM or AES-256-CCM, Nonce MUST be set to an 11-byte implementation-specific value. If Connection.CipherID is AES-128-GCM or AES-256-GCM, Nonce MUST be set to a 12-byte implementation-specific value.

      • Set Signature to a value generated using the algorithm specified in Connection.CipherID with the following inputs:

        • Nonce.

        • Read data to be signed.

        • Session.EncryptionKey, as the key for signing.

      • Set SignatureLength to the length of the Signature field.

      • Set NonceLength to the length of the Nonce field.

    • Buffer field of the response MUST be set to the constructed SMB2_RDMA_TRANSFORM structure, followed by the constructed SMB2_RDMA_ENCRYPTION_TRANSFORM structure.

    • DataLength field of the response MUST be set to the sum of the sizes of SMB2_RDMA_TRANSFORM and SMB2_RDMA_ENCRYPTION_TRANSFORM structures.

    • SMB2_READFLAG_RESPONSE_RDMA_TRANSFORM bit in the Flags field of the response MUST be set.

    • The read data MUST be encrypted using Session.EncryptionKey with the algorithm specified in Connection.CipherId.

  • Otherwise, DataLength MUST be set to zero.

  • The data MUST be sent via the processing specified in [MS-SMBD] section 3.1.4.5 RDMA Write to Peer Buffer, providing the Connection, the data, and the array of SMB_DIRECT_BUFFER_DESCRIPTOR_V1 structures passed in the request at offset ReadChannelInfoOffset and of length ReadChannelInfoLength fields.

  • The DataOffset field MUST be set to the offset into the response, in bytes, from the beginning of the SMB2 header to the Buffer field.

  • The data MUST NOT be copied into the response.

  • DataRemaining MUST be set to the number of bytes returned via RDMA.

The response MUST then be sent to the client. If the request Channel field contains the value SMB2_CHANNEL_RDMA_V1_INVALIDATE, then the Token in the first element of the array of SMB_DIRECT_BUFFER_DESCRIPTOR_V1 structures passed in the request MUST additionally be supplied, as specified in [MS-SMBD] section 3.1.4.2.

The status code returned by this operation MUST be one of those defined in [MS-ERREF]. Common status codes returned by this operation include:

  • STATUS_SUCCESS

  • STATUS_INSUFFICIENT_RESOURCES

  • STATUS_ACCESS_DENIED

  • STATUS_FILE_CLOSED

  • STATUS_NETWORK_NAME_DELETED

  • STATUS_USER_SESSION_DELETED

  • STATUS_NETWORK_SESSION_EXPIRED

  • STATUS_INVALID_PARAMETER

  • STATUS_END_OF_FILE

  • STATUS_PIPE_BROKEN

  • STATUS_BUFFER_OVERFLOW

  • STATUS_CANCELLED

  • STATUS_FILE_LOCK_CONFLICT