xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c (revision 93bc28dbaee6387120d48b12b3dc1ba5f7418e6e)
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  */
21148c5f43SAlan Wright 
22da6c28aaSamw /*
23148c5f43SAlan Wright  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24*93bc28dbSGordon Ross  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
25da6c28aaSamw  */
26148c5f43SAlan Wright 
27da6c28aaSamw /*
28da6c28aaSamw  * SMB: locking_andx
29da6c28aaSamw  *
30da6c28aaSamw  * SMB_COM_LOCKING_ANDX allows both locking and/or unlocking of file range(s).
31da6c28aaSamw  *
32da6c28aaSamw  *  Client Request                     Description
33da6c28aaSamw  *  ================================== =================================
34da6c28aaSamw  *
35da6c28aaSamw  *  UCHAR WordCount;                   Count of parameter words = 8
36da6c28aaSamw  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF = none
37da6c28aaSamw  *  UCHAR AndXReserved;                Reserved (must be 0)
38da6c28aaSamw  *  USHORT AndXOffset;                 Offset to next command WordCount
39da6c28aaSamw  *  USHORT Fid;                        File handle
40da6c28aaSamw  *  UCHAR LockType;                    See LockType table below
41da6c28aaSamw  *  UCHAR OplockLevel;                 The new oplock level
42da6c28aaSamw  *  ULONG Timeout;                     Milliseconds to wait for unlock
43da6c28aaSamw  *  USHORT NumberOfUnlocks;            Num. unlock range structs following
44da6c28aaSamw  *  USHORT NumberOfLocks;              Num. lock range structs following
45da6c28aaSamw  *  USHORT ByteCount;                  Count of data bytes
46da6c28aaSamw  *  LOCKING_ANDX_RANGE Unlocks[];      Unlock ranges
47da6c28aaSamw  *  LOCKING_ANDX_RANGE Locks[];        Lock ranges
48da6c28aaSamw  *
49da6c28aaSamw  *  LockType Flag Name            Value Description
50da6c28aaSamw  *  ============================  ===== ================================
51da6c28aaSamw  *
52da6c28aaSamw  *  LOCKING_ANDX_SHARED_LOCK      0x01  Read-only lock
53da6c28aaSamw  *  LOCKING_ANDX_OPLOCK_RELEASE   0x02  Oplock break notification
54da6c28aaSamw  *  LOCKING_ANDX_CHANGE_LOCKTYPE  0x04  Change lock type
55da6c28aaSamw  *  LOCKING_ANDX_CANCEL_LOCK      0x08  Cancel outstanding request
56da6c28aaSamw  *  LOCKING_ANDX_LARGE_FILES      0x10  Large file locking format
57da6c28aaSamw  *
58da6c28aaSamw  *  LOCKING_ANDX_RANGE Format
59da6c28aaSamw  *  =====================================================================
60da6c28aaSamw  *
61da6c28aaSamw  *  USHORT Pid;                        PID of process "owning" lock
62da6c28aaSamw  *  ULONG Offset;                      Offset to bytes to [un]lock
63da6c28aaSamw  *  ULONG Length;                      Number of bytes to [un]lock
64da6c28aaSamw  *
65da6c28aaSamw  *  Large File LOCKING_ANDX_RANGE Format
66da6c28aaSamw  *  =====================================================================
67da6c28aaSamw  *
68da6c28aaSamw  *  USHORT Pid;                        PID of process "owning" lock
69da6c28aaSamw  *  USHORT Pad;                        Pad to DWORD align (mbz)
70da6c28aaSamw  *  ULONG OffsetHigh;                  Offset to bytes to [un]lock
71da6c28aaSamw  *                                      (high)
72da6c28aaSamw  *  ULONG OffsetLow;                   Offset to bytes to [un]lock (low)
73da6c28aaSamw  *  ULONG LengthHigh;                  Number of bytes to [un]lock
74da6c28aaSamw  *                                      (high)
75da6c28aaSamw  *  ULONG LengthLow;                   Number of bytes to [un]lock (low)
76da6c28aaSamw  *
77da6c28aaSamw  *  Server Response                    Description
78da6c28aaSamw  *  ================================== =================================
79da6c28aaSamw  *
80da6c28aaSamw  *  UCHAR WordCount;                   Count of parameter words = 2
81da6c28aaSamw  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF =
82da6c28aaSamw  *                                      none
83da6c28aaSamw  *  UCHAR AndXReserved;                Reserved (must be 0)
84da6c28aaSamw  *  USHORT AndXOffset;                 Offset to next command WordCount
85da6c28aaSamw  *  USHORT ByteCount;                  Count of data bytes = 0
86da6c28aaSamw  *
87da6c28aaSamw  * Locking is a simple mechanism for excluding other processes read/write
88da6c28aaSamw  * access to regions of a file.  The locked regions can be anywhere in the
89da6c28aaSamw  * logical file.  Locking beyond end-of-file is permitted.  Any process
90da6c28aaSamw  * using the Fid specified in this request's Fid has access to the locked
91da6c28aaSamw  * bytes, other processes will be denied the locking of the same bytes.
92da6c28aaSamw  *
93da6c28aaSamw  * The proper method for using locks is not to rely on being denied read or
94da6c28aaSamw  * write access on any of the read/write protocols but rather to attempt
95da6c28aaSamw  * the locking protocol and proceed with the read/write only if the locks
96da6c28aaSamw  * succeeded.
97da6c28aaSamw  *
98da6c28aaSamw  * Locking a range of bytes will fail if any subranges or overlapping
99da6c28aaSamw  * ranges are locked.  In other words, if any of the specified bytes are
100da6c28aaSamw  * already locked, the lock will fail.
101da6c28aaSamw  *
102da6c28aaSamw  * If NumberOfUnlocks is non-zero, the Unlocks vector contains
103da6c28aaSamw  * NumberOfUnlocks elements.  Each element requests that a lock at Offset
104da6c28aaSamw  * of Length be released.  If NumberOfLocks is nonzero, the Locks vector
105da6c28aaSamw  * contains NumberOfLocks elements.  Each element requests the acquisition
106da6c28aaSamw  * of a lock at Offset of Length.
107da6c28aaSamw  *
108da6c28aaSamw  * Timeout is the maximum amount of time to wait for the byte range(s)
109da6c28aaSamw  * specified to become unlocked.  A timeout value of 0 indicates that the
110da6c28aaSamw  * server should fail immediately if any lock range specified is locked.  A
111da6c28aaSamw  *
112da6c28aaSamw  * timeout value of -1 indicates that the server should wait as long as it
113da6c28aaSamw  * takes for each byte range specified to become unlocked so that it may be
114da6c28aaSamw  * again locked by this protocol.  Any other value of smb_timeout specifies
115da6c28aaSamw  * the maximum number of milliseconds to wait for all lock range(s)
116da6c28aaSamw  * specified to become available.
117da6c28aaSamw  *
118da6c28aaSamw  * If any of the lock ranges timeout because of the area to be locked is
119da6c28aaSamw  * already locked (or the lock fails), the other ranges in the protocol
120da6c28aaSamw  * request which were successfully locked as a result of this protocol will
121da6c28aaSamw  * be unlocked (either all requested ranges will be locked when this
122da6c28aaSamw  * protocol returns to the client or none).
123da6c28aaSamw  *
124da6c28aaSamw  * If LockType has the LOCKING_ANDX_SHARED_LOCK flag set, the lock is
125da6c28aaSamw  * specified as a shared lock.  Locks for both read and write (where
126da6c28aaSamw  * LOCKING_ANDX_SHARED_LOCK is clear) should be prohibited, but other
127da6c28aaSamw  * shared locks should be permitted.  If shared locks can not be supported
128da6c28aaSamw  * by a server, the server should map the lock to a lock for both read and
129da6c28aaSamw  * write.  Closing a file with locks still in force causes the locks to be
130da6c28aaSamw  * released in no defined order.
131da6c28aaSamw  *
132da6c28aaSamw  * If LockType has the LOCKING_ANDX_LARGE_FILES flag set and if the
133da6c28aaSamw  * negotiated protocol is NT LM 0.12 or later, then the Locks and Unlocks
134da6c28aaSamw  * vectors are in the Large File LOCKING_ANDX_RANGE format.  This allows
135da6c28aaSamw  * specification of 64 bit offsets for very large files.
136da6c28aaSamw  *
137da6c28aaSamw  * If the one and only member of the Locks vector has the
138da6c28aaSamw  * LOCKING_ANDX_CANCEL_LOCK flag set in the LockType field, the client is
139da6c28aaSamw  * requesting the server to cancel a previously requested, but not yet
140da6c28aaSamw  * responded to, lock.
141da6c28aaSamw  *
142da6c28aaSamw  * If LockType has the LOCKING_ANDX_CHANGE_LOCKTYPE flag set, the client is
143da6c28aaSamw  * requesting that the server atomically change the lock type from a shared
144da6c28aaSamw  * lock to an exclusive lock or vice versa.  If the server can not do this
145da6c28aaSamw  * in an atomic fashion, the server must reject this request.  NT and W95
146da6c28aaSamw  * servers do not support this capability.
147da6c28aaSamw  *
148da6c28aaSamw  * Oplocks are described in the "Opportunistic Locks" section elsewhere in
149da6c28aaSamw  * this document.  A client requests an oplock by setting the appropriate
150da6c28aaSamw  * bit in the SMB_COM_OPEN_ANDX request when the file is being opened in a
151da6c28aaSamw  * mode which is not exclusive.  The server responds by setting the
152da6c28aaSamw  * appropriate bit in the response SMB indicating whether or not the oplock
153da6c28aaSamw  * was granted.  By granting the oplock, the server tells the client the
154da6c28aaSamw  * file is currently only being used by this one client process at the
155da6c28aaSamw  * current time.  The client can therefore safely do read ahead and write
156da6c28aaSamw  * behind as well as local caching of file locks knowing that the file will
157da6c28aaSamw  * not be accessed/changed in any way by another process while the oplock
158da6c28aaSamw  * is in effect.  The client will be notified when any other process
159da6c28aaSamw  * attempts to open or modify the oplocked file.
160da6c28aaSamw  *
161da6c28aaSamw  * When another user attempts to open or otherwise modify the file which a
162da6c28aaSamw  * client has oplocked, the server delays the second attempt and notifies
163da6c28aaSamw  * the client via an SMB_LOCKING_ANDX SMB asynchronously sent from the
164da6c28aaSamw  * server to the client.  This message has the LOCKING_ANDX_OPLOCK_RELEASE
165da6c28aaSamw  * flag set indicating to the client that the oplock is being broken.
166da6c28aaSamw  *
167da6c28aaSamw  * OplockLevel indicates the type of oplock the client now owns. If
168da6c28aaSamw  * OplockLevel is 0, the client possesses no oplocks on the file at all, if
169da6c28aaSamw  * OplockLevel is 1 the client possesses a Level II oplock.  The client is
170da6c28aaSamw  * expected to flush any dirty buffers to the server, submit any file locks
171da6c28aaSamw  * and respond to the server with either an SMB_LOCKING_ANDX SMB having the
172da6c28aaSamw  * LOCKING_ANDX_OPLOCK_RELEASE flag set, or with a file close if the file
173da6c28aaSamw  * is no longer in use by the client.  If the client sends an
174da6c28aaSamw  * SMB_LOCKING_ANDX SMB with the LOCKING_ANDX_OPLOCK_RELEASE flag set and
175da6c28aaSamw  * NumberOfLocks is zero, the server does not send a response.  Since a
176da6c28aaSamw  * close being sent to the server and break oplock notification from the
177da6c28aaSamw  * server could cross on the wire, if the client gets an oplock
178da6c28aaSamw  * notification on a file which it does not have open, that notification
179da6c28aaSamw  * should be ignored.
180da6c28aaSamw  *
181da6c28aaSamw  * Due to timing, the client could get an "oplock broken" notification in a
182da6c28aaSamw  * user's data buffer as a result of this notification crossing on the wire
183da6c28aaSamw  * with a SMB_COM_READ_RAW request.  The client must detect this (use
184da6c28aaSamw  * length of msg, "FFSMB", MID of -1 and Command of SMB_COM_LOCKING_ANDX)
185da6c28aaSamw  * and honor the "oplock broken" notification as usual.  The server must
186da6c28aaSamw  * also note on receipt of an SMB_COM_READ_RAW request that there is an
187da6c28aaSamw  * outstanding (unanswered) "oplock broken" notification to the client and
188da6c28aaSamw  * return a zero length response denoting failure of the read raw request.
189da6c28aaSamw  * The client should (after responding to the "oplock broken"
190da6c28aaSamw  * notification), use a standard read protocol to redo the read request.
191da6c28aaSamw  * This allows a file to actually contain data matching an "oplock broken"
192da6c28aaSamw  * notification and still be read correctly.
193da6c28aaSamw  *
194da6c28aaSamw  * The entire message sent and received including the optional second
195da6c28aaSamw  * protocol must fit in the negotiated maximum transfer size.  The
196da6c28aaSamw  * following are the only valid SMB commands for AndXCommand for
197da6c28aaSamw  * SMB_COM_LOCKING_ANDX:
198da6c28aaSamw  *
199da6c28aaSamw  *     SMB_COM_READ       SMB_COM_READ_ANDX
200da6c28aaSamw  *     SMB_COM_WRITE      SMB_COM_WRITE_ANDX
201da6c28aaSamw  *     SMB_COM_FLUSH
202da6c28aaSamw  *
203da6c28aaSamw  * 4.2.6.1   Errors
204da6c28aaSamw  *
205da6c28aaSamw  * ERRDOS/ERRbadfile
206da6c28aaSamw  * ERRDOS/ERRbadfid
207da6c28aaSamw  * ERRDOS/ERRlock
208da6c28aaSamw  * ERRDOS/ERRinvdevice
209da6c28aaSamw  * ERRSRV/ERRinvid
210da6c28aaSamw  * ERRSRV/ERRbaduid
211da6c28aaSamw  */
212da6c28aaSamw 
213bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
214da6c28aaSamw 
2150897f7fbSGordon Ross /*
2160897f7fbSGordon Ross  * This is a somewhat arbitrary sanity limit on the length of the
2170897f7fbSGordon Ross  * SMB2_LOCK_ELEMENT array.  It usually has length one or two.
2180897f7fbSGordon Ross  */
2190897f7fbSGordon Ross int smb_lock_max_elem = 1024;
2200897f7fbSGordon Ross 
2217b59d02dSjb150015 smb_sdrc_t
222faa1795aSjb150015 smb_pre_locking_andx(smb_request_t *sr)
223faa1795aSjb150015 {
224*93bc28dbSGordon Ross 	DTRACE_SMB_START(op__LockingX, smb_request_t *, sr);
225faa1795aSjb150015 	return (SDRC_SUCCESS);
226faa1795aSjb150015 }
227faa1795aSjb150015 
228faa1795aSjb150015 void
229faa1795aSjb150015 smb_post_locking_andx(smb_request_t *sr)
230faa1795aSjb150015 {
231*93bc28dbSGordon Ross 	DTRACE_SMB_DONE(op__LockingX, smb_request_t *, sr);
232faa1795aSjb150015 }
233faa1795aSjb150015 
2340897f7fbSGordon Ross struct lreq {
2350897f7fbSGordon Ross 	uint64_t off;
2360897f7fbSGordon Ross 	uint64_t len;
2370897f7fbSGordon Ross 	uint32_t pid;
2380897f7fbSGordon Ross 	uint32_t reserved;
2390897f7fbSGordon Ross };
2400897f7fbSGordon Ross 
241faa1795aSjb150015 smb_sdrc_t
242faa1795aSjb150015 smb_com_locking_andx(smb_request_t *sr)
243da6c28aaSamw {
244da6c28aaSamw 	unsigned short	i;
245da6c28aaSamw 	unsigned char	lock_type;	/* See lock_type table above */
246da6c28aaSamw 	unsigned char	oplock_level;	/* The new oplock level */
247da6c28aaSamw 	uint32_t	timeout;	/* Milliseconds to wait for lock */
248da6c28aaSamw 	unsigned short	unlock_num;	/* # unlock range structs */
249da6c28aaSamw 	unsigned short	lock_num;	/* # lock range structs */
250da6c28aaSamw 	DWORD		result;
251da6c28aaSamw 	int 		rc;
252da6c28aaSamw 	uint32_t	ltype;
253cb174861Sjoyce mcintosh 	smb_ofile_t	*ofile;
254a90cf9f2SGordon Ross 	uint16_t	tmp_pid;	/* locking uses 16-bit pids */
255cb174861Sjoyce mcintosh 	uint8_t		brk;
2560897f7fbSGordon Ross 	uint32_t	lrv_tot;
2570897f7fbSGordon Ross 	struct lreq	*lrv_ul;
2580897f7fbSGordon Ross 	struct lreq	*lrv_lk;
2590897f7fbSGordon Ross 	struct lreq	*lr;
260da6c28aaSamw 
261da6c28aaSamw 	rc = smbsr_decode_vwv(sr, "4.wbblww", &sr->smb_fid, &lock_type,
262da6c28aaSamw 	    &oplock_level, &timeout, &unlock_num, &lock_num);
2637b59d02dSjb150015 	if (rc != 0)
264faa1795aSjb150015 		return (SDRC_ERROR);
265da6c28aaSamw 
2662c2961f8Sjose borrego 	smbsr_lookup_file(sr);
267da6c28aaSamw 	if (sr->fid_ofile == NULL) {
268dc20a302Sas200622 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
269faa1795aSjb150015 		return (SDRC_ERROR);
270da6c28aaSamw 	}
271cb174861Sjoyce mcintosh 	ofile = sr->fid_ofile;
2729c787c76SGordon Ross 	if (ofile->f_node == NULL) {
2739c787c76SGordon Ross 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
2749c787c76SGordon Ross 		    ERRDOS, ERROR_INVALID_PARAMETER);
2759c787c76SGordon Ross 		return (SDRC_ERROR);
2769c787c76SGordon Ross 	}
277da6c28aaSamw 
2780897f7fbSGordon Ross 	if (unlock_num > smb_lock_max_elem ||
2790897f7fbSGordon Ross 	    lock_num > smb_lock_max_elem) {
2800897f7fbSGordon Ross 		smbsr_error(sr, NT_STATUS_INSUFFICIENT_RESOURCES,
2810897f7fbSGordon Ross 		    ERRDOS, ERROR_NO_SYSTEM_RESOURCES);
2820897f7fbSGordon Ross 		return (SDRC_ERROR);
2830897f7fbSGordon Ross 	}
2840897f7fbSGordon Ross 
285da6c28aaSamw 	if (lock_type & LOCKING_ANDX_SHARED_LOCK)
286da6c28aaSamw 		ltype = SMB_LOCK_TYPE_READONLY;
287da6c28aaSamw 	else
288da6c28aaSamw 		ltype = SMB_LOCK_TYPE_READWRITE;
289da6c28aaSamw 
290da6c28aaSamw 	if (lock_type & LOCKING_ANDX_OPLOCK_RELEASE) {
291cb174861Sjoyce mcintosh 		if (oplock_level == 0)
292cb174861Sjoyce mcintosh 			brk = SMB_OPLOCK_BREAK_TO_NONE;
293cb174861Sjoyce mcintosh 		else
294cb174861Sjoyce mcintosh 			brk = SMB_OPLOCK_BREAK_TO_LEVEL_II;
295cb174861Sjoyce mcintosh 		smb_oplock_ack(ofile->f_node, ofile, brk);
296da6c28aaSamw 		if (unlock_num == 0 && lock_num == 0)
297da6c28aaSamw 			return (SDRC_NO_REPLY);
298da6c28aaSamw 	}
299da6c28aaSamw 
300da6c28aaSamw 	/*
301da6c28aaSamw 	 * No support for changing locktype (although we could probably
302da6c28aaSamw 	 * implement this)
303da6c28aaSamw 	 */
304da6c28aaSamw 	if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) {
305148c5f43SAlan Wright 		smbsr_error(sr, 0, ERRDOS,
306148c5f43SAlan Wright 		    ERROR_ATOMIC_LOCKS_NOT_SUPPORTED);
307faa1795aSjb150015 		return (SDRC_ERROR);
308da6c28aaSamw 	}
309da6c28aaSamw 
310da6c28aaSamw 	if (lock_type & LOCKING_ANDX_LARGE_FILES) {
311da6c28aaSamw 		/*
312da6c28aaSamw 		 * negotiated protocol should be NT LM 0.12 or later
313da6c28aaSamw 		 */
314da6c28aaSamw 		if (sr->session->dialect < NT_LM_0_12) {
315dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
316da6c28aaSamw 			    ERRDOS, ERROR_INVALID_PARAMETER);
317faa1795aSjb150015 			return (SDRC_ERROR);
318da6c28aaSamw 		}
3190897f7fbSGordon Ross 	}
320da6c28aaSamw 
3210897f7fbSGordon Ross 	/*
3220897f7fbSGordon Ross 	 * Parse the unlock, lock vectors.  Will parse all the
3230897f7fbSGordon Ross 	 * unlock + lock records into one array, and then use
3240897f7fbSGordon Ross 	 * pointers to the unlock and lock parts.
3250897f7fbSGordon Ross 	 */
3260897f7fbSGordon Ross 	lrv_tot = unlock_num + lock_num;
3270897f7fbSGordon Ross 	lrv_ul = smb_srm_zalloc(sr, lrv_tot * sizeof (*lrv_ul));
3280897f7fbSGordon Ross 	lrv_lk = &lrv_ul[unlock_num];
3290897f7fbSGordon Ross 
3300897f7fbSGordon Ross 	for (i = 0; i < lrv_tot; i++) {
3310897f7fbSGordon Ross 		lr = &lrv_ul[i];
3320897f7fbSGordon Ross 		if (lock_type & LOCKING_ANDX_LARGE_FILES) {
3333db3f65cSamw 			rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
3340897f7fbSGordon Ross 			    &tmp_pid, &lr->off, &lr->len);
3350897f7fbSGordon Ross 		} else {
3360897f7fbSGordon Ross 			uint32_t	offset32, length32;
3370897f7fbSGordon Ross 			rc = smb_mbc_decodef(&sr->smb_data, "wll",
3380897f7fbSGordon Ross 			    &tmp_pid, &offset32, &length32);
3390897f7fbSGordon Ross 			lr->off = offset32;
3400897f7fbSGordon Ross 			lr->len = length32;
3410897f7fbSGordon Ross 		}
3420897f7fbSGordon Ross 		lr->pid = tmp_pid;	/* 16-bit PID */
343da6c28aaSamw 		if (rc) {
344da6c28aaSamw 			/*
345dc20a302Sas200622 			 * This is the error returned by Windows 2000
346dc20a302Sas200622 			 * even when STATUS32 has been negotiated.
347da6c28aaSamw 			 */
348dc20a302Sas200622 			smbsr_error(sr, 0, ERRSRV, ERRerror);
349faa1795aSjb150015 			return (SDRC_ERROR);
350da6c28aaSamw 		}
3510897f7fbSGordon Ross 	}
352da6c28aaSamw 
3530897f7fbSGordon Ross 	/*
3540897f7fbSGordon Ross 	 * Cancel waiting locks.  MS-CIFS says one place that
3550897f7fbSGordon Ross 	 * this cancels all waiting locks for this FID+PID,
3560897f7fbSGordon Ross 	 * but smbtorture insists this cancels just one.
3570897f7fbSGordon Ross 	 * Tests with Windows 7 confirms that.
3580897f7fbSGordon Ross 	 */
3590897f7fbSGordon Ross 	if ((lock_type & LOCKING_ANDX_CANCEL_LOCK) != 0) {
3600897f7fbSGordon Ross 		lr = lrv_lk;
3610897f7fbSGordon Ross 
3620897f7fbSGordon Ross 		result = smb_lock_range_cancel(sr, lr->off, lr->len, lr->pid);
3630897f7fbSGordon Ross 
364da6c28aaSamw 		if (result != NT_STATUS_SUCCESS) {
3650897f7fbSGordon Ross 			smbsr_error(sr, 0, ERRDOS,
3660897f7fbSGordon Ross 			    ERROR_CANCEL_VIOLATION);
367faa1795aSjb150015 			return (SDRC_ERROR);
368da6c28aaSamw 		}
3690897f7fbSGordon Ross 		goto out;
370da6c28aaSamw 	}
371da6c28aaSamw 
3720897f7fbSGordon Ross 	/*
3730897f7fbSGordon Ross 	 * Normal unlock and lock list
3740897f7fbSGordon Ross 	 */
375da6c28aaSamw 	for (i = 0; i < unlock_num; i++) {
3760897f7fbSGordon Ross 		lr = &lrv_ul[i];
377da6c28aaSamw 
3780897f7fbSGordon Ross 		result = smb_unlock_range(sr, lr->off, lr->len, lr->pid);
379da6c28aaSamw 		if (result != NT_STATUS_SUCCESS) {
380dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
381148c5f43SAlan Wright 			    ERRDOS, ERROR_NOT_LOCKED);
382faa1795aSjb150015 			return (SDRC_ERROR);
383da6c28aaSamw 		}
384da6c28aaSamw 	}
385da6c28aaSamw 	for (i = 0; i < lock_num; i++) {
3860897f7fbSGordon Ross 		lr = &lrv_lk[i];
387da6c28aaSamw 
3880897f7fbSGordon Ross 		result = smb_lock_range(sr, lr->off, lr->len, lr->pid,
3890897f7fbSGordon Ross 		    ltype, timeout);
390da6c28aaSamw 		if (result != NT_STATUS_SUCCESS) {
3910897f7fbSGordon Ross 			/*
3920897f7fbSGordon Ross 			 * Oh... we have to rollback.
3930897f7fbSGordon Ross 			 */
3940897f7fbSGordon Ross 			while (i > 0) {
3950897f7fbSGordon Ross 				--i;
3960897f7fbSGordon Ross 				lr = &lrv_lk[i];
3970897f7fbSGordon Ross 				(void) smb_unlock_range(sr,
3980897f7fbSGordon Ross 				    lr->off, lr->len, lr->pid);
3990897f7fbSGordon Ross 			}
400dc20a302Sas200622 			smb_lock_range_error(sr, result);
401faa1795aSjb150015 			return (SDRC_ERROR);
402da6c28aaSamw 		}
403da6c28aaSamw 	}
404da6c28aaSamw 
4050897f7fbSGordon Ross out:
4060897f7fbSGordon Ross 	if (smbsr_encode_result(sr, 2, 0, "bb.ww",
4070897f7fbSGordon Ross 	    2, sr->andx_com, 0x27, 0) != 0)
408faa1795aSjb150015 		return (SDRC_ERROR);
409faa1795aSjb150015 	return (SDRC_SUCCESS);
410da6c28aaSamw }
411a90cf9f2SGordon Ross 
412a90cf9f2SGordon Ross /*
413a90cf9f2SGordon Ross  * Compose an SMB1 Oplock Break Notification packet, including
414a90cf9f2SGordon Ross  * the SMB1 header and everything, in sr->reply.
415a90cf9f2SGordon Ross  * The caller will send it and free the request.
416a90cf9f2SGordon Ross  */
417a90cf9f2SGordon Ross void
418a90cf9f2SGordon Ross smb1_oplock_break_notification(smb_request_t *sr, uint8_t brk)
419a90cf9f2SGordon Ross {
420a90cf9f2SGordon Ross 	smb_ofile_t *ofile = sr->fid_ofile;
421a90cf9f2SGordon Ross 	uint16_t fid;
422a90cf9f2SGordon Ross 	uint8_t lock_type;
423a90cf9f2SGordon Ross 	uint8_t oplock_level;
424a90cf9f2SGordon Ross 
425a90cf9f2SGordon Ross 	switch (brk) {
426a90cf9f2SGordon Ross 	default:
427a90cf9f2SGordon Ross 		ASSERT(0);
428a90cf9f2SGordon Ross 		/* FALLTHROUGH */
429a90cf9f2SGordon Ross 	case SMB_OPLOCK_BREAK_TO_NONE:
430a90cf9f2SGordon Ross 		oplock_level = 0;
431a90cf9f2SGordon Ross 		break;
432a90cf9f2SGordon Ross 	case SMB_OPLOCK_BREAK_TO_LEVEL_II:
433a90cf9f2SGordon Ross 		oplock_level = 1;
434a90cf9f2SGordon Ross 		break;
435a90cf9f2SGordon Ross 	}
436a90cf9f2SGordon Ross 
437a90cf9f2SGordon Ross 	sr->smb_com = SMB_COM_LOCKING_ANDX;
438a90cf9f2SGordon Ross 	sr->smb_tid = ofile->f_tree->t_tid;
439a90cf9f2SGordon Ross 	sr->smb_pid = 0xFFFF;
440a90cf9f2SGordon Ross 	sr->smb_uid = 0;
441a90cf9f2SGordon Ross 	sr->smb_mid = 0xFFFF;
442a90cf9f2SGordon Ross 	fid = ofile->f_fid;
443a90cf9f2SGordon Ross 	lock_type = LOCKING_ANDX_OPLOCK_RELEASE;
444a90cf9f2SGordon Ross 
445a90cf9f2SGordon Ross 	(void) smb_mbc_encodef(
446a90cf9f2SGordon Ross 	    &sr->reply, "Mb19.wwwwbb3.wbb10.",
447a90cf9f2SGordon Ross 	    /*  "\xffSMB"		   M */
448a90cf9f2SGordon Ross 	    sr->smb_com,		/* b */
449a90cf9f2SGordon Ross 	    /* status, flags, signature	 19. */
450a90cf9f2SGordon Ross 	    sr->smb_tid,		/* w */
451a90cf9f2SGordon Ross 	    sr->smb_pid,		/* w */
452a90cf9f2SGordon Ross 	    sr->smb_uid,		/* w */
453a90cf9f2SGordon Ross 	    sr->smb_mid,		/* w */
454a90cf9f2SGordon Ross 	    8,		/* word count	   b */
455a90cf9f2SGordon Ross 	    0xFF,	/* AndX cmd	   b */
456a90cf9f2SGordon Ross 	    /*  AndX reserved, offset	  3. */
457a90cf9f2SGordon Ross 	    fid,
458a90cf9f2SGordon Ross 	    lock_type,
459a90cf9f2SGordon Ross 	    oplock_level);
460a90cf9f2SGordon Ross }
461