smb_locking_andx.c revision 9c787c76803e57736d13413909945366ce3a9448
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
* SMB: locking_andx
*
*
* Client Request Description
* ================================== =================================
*
* UCHAR WordCount; Count of parameter words = 8
* UCHAR AndXCommand; Secondary (X) command; 0xFF = none
* UCHAR AndXReserved; Reserved (must be 0)
* USHORT AndXOffset; Offset to next command WordCount
* USHORT Fid; File handle
* UCHAR LockType; See LockType table below
* UCHAR OplockLevel; The new oplock level
* ULONG Timeout; Milliseconds to wait for unlock
* USHORT NumberOfUnlocks; Num. unlock range structs following
* USHORT NumberOfLocks; Num. lock range structs following
* USHORT ByteCount; Count of data bytes
* LOCKING_ANDX_RANGE Unlocks[]; Unlock ranges
* LOCKING_ANDX_RANGE Locks[]; Lock ranges
*
* LockType Flag Name Value Description
* ============================ ===== ================================
*
* LOCKING_ANDX_SHARED_LOCK 0x01 Read-only lock
* LOCKING_ANDX_OPLOCK_RELEASE 0x02 Oplock break notification
* LOCKING_ANDX_CHANGE_LOCKTYPE 0x04 Change lock type
* LOCKING_ANDX_CANCEL_LOCK 0x08 Cancel outstanding request
* LOCKING_ANDX_LARGE_FILES 0x10 Large file locking format
*
* LOCKING_ANDX_RANGE Format
* =====================================================================
*
* USHORT Pid; PID of process "owning" lock
* ULONG Offset; Offset to bytes to [un]lock
* ULONG Length; Number of bytes to [un]lock
*
* Large File LOCKING_ANDX_RANGE Format
* =====================================================================
*
* USHORT Pid; PID of process "owning" lock
* USHORT Pad; Pad to DWORD align (mbz)
* ULONG OffsetHigh; Offset to bytes to [un]lock
* (high)
* ULONG OffsetLow; Offset to bytes to [un]lock (low)
* ULONG LengthHigh; Number of bytes to [un]lock
* (high)
* ULONG LengthLow; Number of bytes to [un]lock (low)
*
* Server Response Description
* ================================== =================================
*
* UCHAR WordCount; Count of parameter words = 2
* UCHAR AndXCommand; Secondary (X) command; 0xFF =
* none
* UCHAR AndXReserved; Reserved (must be 0)
* USHORT AndXOffset; Offset to next command WordCount
* USHORT ByteCount; Count of data bytes = 0
*
* access to regions of a file. The locked regions can be anywhere in the
* logical file. Locking beyond end-of-file is permitted. Any process
* using the Fid specified in this request's Fid has access to the locked
* bytes, other processes will be denied the locking of the same bytes.
*
* The proper method for using locks is not to rely on being denied read or
* succeeded.
*
* Locking a range of bytes will fail if any subranges or overlapping
* ranges are locked. In other words, if any of the specified bytes are
* already locked, the lock will fail.
*
* If NumberOfUnlocks is non-zero, the Unlocks vector contains
* NumberOfUnlocks elements. Each element requests that a lock at Offset
* of Length be released. If NumberOfLocks is nonzero, the Locks vector
* contains NumberOfLocks elements. Each element requests the acquisition
* of a lock at Offset of Length.
*
* Timeout is the maximum amount of time to wait for the byte range(s)
* specified to become unlocked. A timeout value of 0 indicates that the
* server should fail immediately if any lock range specified is locked. A
*
* timeout value of -1 indicates that the server should wait as long as it
* takes for each byte range specified to become unlocked so that it may be
* again locked by this protocol. Any other value of smb_timeout specifies
* the maximum number of milliseconds to wait for all lock range(s)
* specified to become available.
*
* If any of the lock ranges timeout because of the area to be locked is
* already locked (or the lock fails), the other ranges in the protocol
* request which were successfully locked as a result of this protocol will
* be unlocked (either all requested ranges will be locked when this
* protocol returns to the client or none).
*
* If LockType has the LOCKING_ANDX_SHARED_LOCK flag set, the lock is
* specified as a shared lock. Locks for both read and write (where
* LOCKING_ANDX_SHARED_LOCK is clear) should be prohibited, but other
* shared locks should be permitted. If shared locks can not be supported
* by a server, the server should map the lock to a lock for both read and
* write. Closing a file with locks still in force causes the locks to be
* released in no defined order.
*
* If LockType has the LOCKING_ANDX_LARGE_FILES flag set and if the
* negotiated protocol is NT LM 0.12 or later, then the Locks and Unlocks
* vectors are in the Large File LOCKING_ANDX_RANGE format. This allows
* specification of 64 bit offsets for very large files.
*
* If the one and only member of the Locks vector has the
* LOCKING_ANDX_CANCEL_LOCK flag set in the LockType field, the client is
* requesting the server to cancel a previously requested, but not yet
* responded to, lock.
*
* If LockType has the LOCKING_ANDX_CHANGE_LOCKTYPE flag set, the client is
* requesting that the server atomically change the lock type from a shared
* lock to an exclusive lock or vice versa. If the server can not do this
* in an atomic fashion, the server must reject this request. NT and W95
* servers do not support this capability.
*
* Oplocks are described in the "Opportunistic Locks" section elsewhere in
* this document. A client requests an oplock by setting the appropriate
* bit in the SMB_COM_OPEN_ANDX request when the file is being opened in a
* mode which is not exclusive. The server responds by setting the
* appropriate bit in the response SMB indicating whether or not the oplock
* was granted. By granting the oplock, the server tells the client the
* file is currently only being used by this one client process at the
* current time. The client can therefore safely do read ahead and write
* behind as well as local caching of file locks knowing that the file will
* is in effect. The client will be notified when any other process
* attempts to open or modify the oplocked file.
*
* When another user attempts to open or otherwise modify the file which a
* client has oplocked, the server delays the second attempt and notifies
* the client via an SMB_LOCKING_ANDX SMB asynchronously sent from the
* server to the client. This message has the LOCKING_ANDX_OPLOCK_RELEASE
* flag set indicating to the client that the oplock is being broken.
*
* OplockLevel indicates the type of oplock the client now owns. If
* OplockLevel is 0, the client possesses no oplocks on the file at all, if
* OplockLevel is 1 the client possesses a Level II oplock. The client is
* expected to flush any dirty buffers to the server, submit any file locks
* and respond to the server with either an SMB_LOCKING_ANDX SMB having the
* LOCKING_ANDX_OPLOCK_RELEASE flag set, or with a file close if the file
* is no longer in use by the client. If the client sends an
* SMB_LOCKING_ANDX SMB with the LOCKING_ANDX_OPLOCK_RELEASE flag set and
* NumberOfLocks is zero, the server does not send a response. Since a
* close being sent to the server and break oplock notification from the
* server could cross on the wire, if the client gets an oplock
* notification on a file which it does not have open, that notification
* should be ignored.
*
* Due to timing, the client could get an "oplock broken" notification in a
* user's data buffer as a result of this notification crossing on the wire
* with a SMB_COM_READ_RAW request. The client must detect this (use
* length of msg, "FFSMB", MID of -1 and Command of SMB_COM_LOCKING_ANDX)
* and honor the "oplock broken" notification as usual. The server must
* also note on receipt of an SMB_COM_READ_RAW request that there is an
* outstanding (unanswered) "oplock broken" notification to the client and
* return a zero length response denoting failure of the read raw request.
* The client should (after responding to the "oplock broken"
* notification), use a standard read protocol to redo the read request.
* This allows a file to actually contain data matching an "oplock broken"
* notification and still be read correctly.
*
* The entire message sent and received including the optional second
* protocol must fit in the negotiated maximum transfer size. The
* following are the only valid SMB commands for AndXCommand for
* SMB_COM_LOCKING_ANDX:
*
* SMB_COM_READ SMB_COM_READ_ANDX
* SMB_COM_WRITE SMB_COM_WRITE_ANDX
* SMB_COM_FLUSH
*
* 4.2.6.1 Errors
*
*/
#include <smbsrv/smb_kproto.h>
{
return (SDRC_SUCCESS);
}
void
{
}
{
unsigned short i;
unsigned char lock_type; /* See lock_type table above */
unsigned char oplock_level; /* The new oplock level */
unsigned short unlock_num; /* # unlock range structs */
unsigned short lock_num; /* # lock range structs */
unsigned short pid; /* Process Id of owner */
int rc;
if (rc != 0)
return (SDRC_ERROR);
return (SDRC_ERROR);
}
return (SDRC_ERROR);
}
else
if (lock_type & LOCKING_ANDX_OPLOCK_RELEASE) {
if (oplock_level == 0)
else
if (unlock_num == 0 && lock_num == 0)
return (SDRC_NO_REPLY);
}
/*
* No support for changing locktype (although we could probably
* implement this)
*/
if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) {
return (SDRC_ERROR);
}
/*
* No support for cancel lock (smbtorture expects this)
*/
if (lock_type & LOCKING_ANDX_CANCEL_LOCK) {
return (SDRC_ERROR);
}
if (lock_type & LOCKING_ANDX_LARGE_FILES) {
/*
* negotiated protocol should be NT LM 0.12 or later
*/
return (SDRC_ERROR);
}
for (i = 0; i < unlock_num; i++) {
if (rc) {
/*
* This is the error returned by Windows 2000
* even when STATUS32 has been negotiated.
*/
return (SDRC_ERROR);
}
if (result != NT_STATUS_SUCCESS) {
return (SDRC_ERROR);
}
}
for (i = 0; i < lock_num; i++) {
if (rc) {
return (SDRC_ERROR);
}
ltype);
if (result != NT_STATUS_SUCCESS) {
return (SDRC_ERROR);
}
}
} else {
for (i = 0; i < unlock_num; i++) {
if (rc) {
return (SDRC_ERROR);
}
if (result != NT_STATUS_SUCCESS) {
return (SDRC_ERROR);
}
}
for (i = 0; i < lock_num; i++) {
if (rc) {
return (SDRC_ERROR);
}
if (result != NT_STATUS_SUCCESS) {
return (SDRC_ERROR);
}
}
}
return (SDRC_ERROR);
return (SDRC_SUCCESS);
}