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.
24525641e8SGordon Ross * Copyright 2020 Tintri by DDN, Inc. All rights reserved.
25*72b35b05SGordon Ross * Copyright 2022 RackTop Systems, Inc.
26da6c28aaSamw */
27148c5f43SAlan Wright
28da6c28aaSamw /*
29da6c28aaSamw * SMB: locking_andx
30da6c28aaSamw *
31da6c28aaSamw * SMB_COM_LOCKING_ANDX allows both locking and/or unlocking of file range(s).
32da6c28aaSamw *
33da6c28aaSamw * Client Request Description
34da6c28aaSamw * ================================== =================================
35da6c28aaSamw *
36da6c28aaSamw * UCHAR WordCount; Count of parameter words = 8
37da6c28aaSamw * UCHAR AndXCommand; Secondary (X) command; 0xFF = none
38da6c28aaSamw * UCHAR AndXReserved; Reserved (must be 0)
39da6c28aaSamw * USHORT AndXOffset; Offset to next command WordCount
40da6c28aaSamw * USHORT Fid; File handle
41da6c28aaSamw * UCHAR LockType; See LockType table below
42da6c28aaSamw * UCHAR OplockLevel; The new oplock level
43da6c28aaSamw * ULONG Timeout; Milliseconds to wait for unlock
44da6c28aaSamw * USHORT NumberOfUnlocks; Num. unlock range structs following
45da6c28aaSamw * USHORT NumberOfLocks; Num. lock range structs following
46da6c28aaSamw * USHORT ByteCount; Count of data bytes
47da6c28aaSamw * LOCKING_ANDX_RANGE Unlocks[]; Unlock ranges
48da6c28aaSamw * LOCKING_ANDX_RANGE Locks[]; Lock ranges
49da6c28aaSamw *
50da6c28aaSamw * LockType Flag Name Value Description
51da6c28aaSamw * ============================ ===== ================================
52da6c28aaSamw *
53da6c28aaSamw * LOCKING_ANDX_SHARED_LOCK 0x01 Read-only lock
54da6c28aaSamw * LOCKING_ANDX_OPLOCK_RELEASE 0x02 Oplock break notification
55da6c28aaSamw * LOCKING_ANDX_CHANGE_LOCKTYPE 0x04 Change lock type
56da6c28aaSamw * LOCKING_ANDX_CANCEL_LOCK 0x08 Cancel outstanding request
57da6c28aaSamw * LOCKING_ANDX_LARGE_FILES 0x10 Large file locking format
58da6c28aaSamw *
59da6c28aaSamw * LOCKING_ANDX_RANGE Format
60da6c28aaSamw * =====================================================================
61da6c28aaSamw *
62da6c28aaSamw * USHORT Pid; PID of process "owning" lock
63da6c28aaSamw * ULONG Offset; Offset to bytes to [un]lock
64da6c28aaSamw * ULONG Length; Number of bytes to [un]lock
65da6c28aaSamw *
66da6c28aaSamw * Large File LOCKING_ANDX_RANGE Format
67da6c28aaSamw * =====================================================================
68da6c28aaSamw *
69da6c28aaSamw * USHORT Pid; PID of process "owning" lock
70da6c28aaSamw * USHORT Pad; Pad to DWORD align (mbz)
71da6c28aaSamw * ULONG OffsetHigh; Offset to bytes to [un]lock
72da6c28aaSamw * (high)
73da6c28aaSamw * ULONG OffsetLow; Offset to bytes to [un]lock (low)
74da6c28aaSamw * ULONG LengthHigh; Number of bytes to [un]lock
75da6c28aaSamw * (high)
76da6c28aaSamw * ULONG LengthLow; Number of bytes to [un]lock (low)
77da6c28aaSamw *
78da6c28aaSamw * Server Response Description
79da6c28aaSamw * ================================== =================================
80da6c28aaSamw *
81da6c28aaSamw * UCHAR WordCount; Count of parameter words = 2
82da6c28aaSamw * UCHAR AndXCommand; Secondary (X) command; 0xFF =
83da6c28aaSamw * none
84da6c28aaSamw * UCHAR AndXReserved; Reserved (must be 0)
85da6c28aaSamw * USHORT AndXOffset; Offset to next command WordCount
86da6c28aaSamw * USHORT ByteCount; Count of data bytes = 0
87da6c28aaSamw *
88da6c28aaSamw * Locking is a simple mechanism for excluding other processes read/write
89da6c28aaSamw * access to regions of a file. The locked regions can be anywhere in the
90da6c28aaSamw * logical file. Locking beyond end-of-file is permitted. Any process
91da6c28aaSamw * using the Fid specified in this request's Fid has access to the locked
92da6c28aaSamw * bytes, other processes will be denied the locking of the same bytes.
93da6c28aaSamw *
94da6c28aaSamw * The proper method for using locks is not to rely on being denied read or
95da6c28aaSamw * write access on any of the read/write protocols but rather to attempt
96da6c28aaSamw * the locking protocol and proceed with the read/write only if the locks
97da6c28aaSamw * succeeded.
98da6c28aaSamw *
99da6c28aaSamw * Locking a range of bytes will fail if any subranges or overlapping
100da6c28aaSamw * ranges are locked. In other words, if any of the specified bytes are
101da6c28aaSamw * already locked, the lock will fail.
102da6c28aaSamw *
103da6c28aaSamw * If NumberOfUnlocks is non-zero, the Unlocks vector contains
104da6c28aaSamw * NumberOfUnlocks elements. Each element requests that a lock at Offset
105da6c28aaSamw * of Length be released. If NumberOfLocks is nonzero, the Locks vector
106da6c28aaSamw * contains NumberOfLocks elements. Each element requests the acquisition
107da6c28aaSamw * of a lock at Offset of Length.
108da6c28aaSamw *
109da6c28aaSamw * Timeout is the maximum amount of time to wait for the byte range(s)
110da6c28aaSamw * specified to become unlocked. A timeout value of 0 indicates that the
111da6c28aaSamw * server should fail immediately if any lock range specified is locked. A
112da6c28aaSamw *
113da6c28aaSamw * timeout value of -1 indicates that the server should wait as long as it
114da6c28aaSamw * takes for each byte range specified to become unlocked so that it may be
115da6c28aaSamw * again locked by this protocol. Any other value of smb_timeout specifies
116da6c28aaSamw * the maximum number of milliseconds to wait for all lock range(s)
117da6c28aaSamw * specified to become available.
118da6c28aaSamw *
119da6c28aaSamw * If any of the lock ranges timeout because of the area to be locked is
120da6c28aaSamw * already locked (or the lock fails), the other ranges in the protocol
121da6c28aaSamw * request which were successfully locked as a result of this protocol will
122da6c28aaSamw * be unlocked (either all requested ranges will be locked when this
123da6c28aaSamw * protocol returns to the client or none).
124da6c28aaSamw *
125da6c28aaSamw * If LockType has the LOCKING_ANDX_SHARED_LOCK flag set, the lock is
126da6c28aaSamw * specified as a shared lock. Locks for both read and write (where
127da6c28aaSamw * LOCKING_ANDX_SHARED_LOCK is clear) should be prohibited, but other
128da6c28aaSamw * shared locks should be permitted. If shared locks can not be supported
129da6c28aaSamw * by a server, the server should map the lock to a lock for both read and
130da6c28aaSamw * write. Closing a file with locks still in force causes the locks to be
131da6c28aaSamw * released in no defined order.
132da6c28aaSamw *
133da6c28aaSamw * If LockType has the LOCKING_ANDX_LARGE_FILES flag set and if the
134da6c28aaSamw * negotiated protocol is NT LM 0.12 or later, then the Locks and Unlocks
135da6c28aaSamw * vectors are in the Large File LOCKING_ANDX_RANGE format. This allows
136da6c28aaSamw * specification of 64 bit offsets for very large files.
137da6c28aaSamw *
138da6c28aaSamw * If the one and only member of the Locks vector has the
139da6c28aaSamw * LOCKING_ANDX_CANCEL_LOCK flag set in the LockType field, the client is
140da6c28aaSamw * requesting the server to cancel a previously requested, but not yet
141da6c28aaSamw * responded to, lock.
142da6c28aaSamw *
143da6c28aaSamw * If LockType has the LOCKING_ANDX_CHANGE_LOCKTYPE flag set, the client is
144da6c28aaSamw * requesting that the server atomically change the lock type from a shared
145da6c28aaSamw * lock to an exclusive lock or vice versa. If the server can not do this
146da6c28aaSamw * in an atomic fashion, the server must reject this request. NT and W95
147da6c28aaSamw * servers do not support this capability.
148da6c28aaSamw *
149da6c28aaSamw * Oplocks are described in the "Opportunistic Locks" section elsewhere in
150da6c28aaSamw * this document. A client requests an oplock by setting the appropriate
151da6c28aaSamw * bit in the SMB_COM_OPEN_ANDX request when the file is being opened in a
152da6c28aaSamw * mode which is not exclusive. The server responds by setting the
153da6c28aaSamw * appropriate bit in the response SMB indicating whether or not the oplock
154da6c28aaSamw * was granted. By granting the oplock, the server tells the client the
155da6c28aaSamw * file is currently only being used by this one client process at the
156da6c28aaSamw * current time. The client can therefore safely do read ahead and write
157da6c28aaSamw * behind as well as local caching of file locks knowing that the file will
158da6c28aaSamw * not be accessed/changed in any way by another process while the oplock
159da6c28aaSamw * is in effect. The client will be notified when any other process
160da6c28aaSamw * attempts to open or modify the oplocked file.
161da6c28aaSamw *
162da6c28aaSamw * When another user attempts to open or otherwise modify the file which a
163da6c28aaSamw * client has oplocked, the server delays the second attempt and notifies
164da6c28aaSamw * the client via an SMB_LOCKING_ANDX SMB asynchronously sent from the
165da6c28aaSamw * server to the client. This message has the LOCKING_ANDX_OPLOCK_RELEASE
166da6c28aaSamw * flag set indicating to the client that the oplock is being broken.
167da6c28aaSamw *
168da6c28aaSamw * OplockLevel indicates the type of oplock the client now owns. If
169da6c28aaSamw * OplockLevel is 0, the client possesses no oplocks on the file at all, if
170da6c28aaSamw * OplockLevel is 1 the client possesses a Level II oplock. The client is
171da6c28aaSamw * expected to flush any dirty buffers to the server, submit any file locks
172da6c28aaSamw * and respond to the server with either an SMB_LOCKING_ANDX SMB having the
173da6c28aaSamw * LOCKING_ANDX_OPLOCK_RELEASE flag set, or with a file close if the file
174da6c28aaSamw * is no longer in use by the client. If the client sends an
175da6c28aaSamw * SMB_LOCKING_ANDX SMB with the LOCKING_ANDX_OPLOCK_RELEASE flag set and
176da6c28aaSamw * NumberOfLocks is zero, the server does not send a response. Since a
177da6c28aaSamw * close being sent to the server and break oplock notification from the
178da6c28aaSamw * server could cross on the wire, if the client gets an oplock
179da6c28aaSamw * notification on a file which it does not have open, that notification
180da6c28aaSamw * should be ignored.
181da6c28aaSamw *
182da6c28aaSamw * Due to timing, the client could get an "oplock broken" notification in a
183da6c28aaSamw * user's data buffer as a result of this notification crossing on the wire
184da6c28aaSamw * with a SMB_COM_READ_RAW request. The client must detect this (use
185da6c28aaSamw * length of msg, "FFSMB", MID of -1 and Command of SMB_COM_LOCKING_ANDX)
186da6c28aaSamw * and honor the "oplock broken" notification as usual. The server must
187da6c28aaSamw * also note on receipt of an SMB_COM_READ_RAW request that there is an
188da6c28aaSamw * outstanding (unanswered) "oplock broken" notification to the client and
189da6c28aaSamw * return a zero length response denoting failure of the read raw request.
190da6c28aaSamw * The client should (after responding to the "oplock broken"
191da6c28aaSamw * notification), use a standard read protocol to redo the read request.
192da6c28aaSamw * This allows a file to actually contain data matching an "oplock broken"
193da6c28aaSamw * notification and still be read correctly.
194da6c28aaSamw *
195da6c28aaSamw * The entire message sent and received including the optional second
196da6c28aaSamw * protocol must fit in the negotiated maximum transfer size. The
197da6c28aaSamw * following are the only valid SMB commands for AndXCommand for
198da6c28aaSamw * SMB_COM_LOCKING_ANDX:
199da6c28aaSamw *
200da6c28aaSamw * SMB_COM_READ SMB_COM_READ_ANDX
201da6c28aaSamw * SMB_COM_WRITE SMB_COM_WRITE_ANDX
202da6c28aaSamw * SMB_COM_FLUSH
203da6c28aaSamw *
204da6c28aaSamw * 4.2.6.1 Errors
205da6c28aaSamw *
206da6c28aaSamw * ERRDOS/ERRbadfile
207da6c28aaSamw * ERRDOS/ERRbadfid
208da6c28aaSamw * ERRDOS/ERRlock
209da6c28aaSamw * ERRDOS/ERRinvdevice
210da6c28aaSamw * ERRSRV/ERRinvid
211da6c28aaSamw * ERRSRV/ERRbaduid
212da6c28aaSamw */
213da6c28aaSamw
214bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
215da6c28aaSamw
2160897f7fbSGordon Ross /*
2170897f7fbSGordon Ross * This is a somewhat arbitrary sanity limit on the length of the
2180897f7fbSGordon Ross * SMB2_LOCK_ELEMENT array. It usually has length one or two.
2190897f7fbSGordon Ross */
2200897f7fbSGordon Ross int smb_lock_max_elem = 1024;
2210897f7fbSGordon Ross
2227b59d02dSjb smb_sdrc_t
smb_pre_locking_andx(smb_request_t * sr)223faa1795aSjb smb_pre_locking_andx(smb_request_t *sr)
224faa1795aSjb {
22593bc28dbSGordon Ross DTRACE_SMB_START(op__LockingX, smb_request_t *, sr);
226faa1795aSjb return (SDRC_SUCCESS);
227faa1795aSjb }
228faa1795aSjb
229faa1795aSjb void
smb_post_locking_andx(smb_request_t * sr)230faa1795aSjb smb_post_locking_andx(smb_request_t *sr)
231faa1795aSjb {
23293bc28dbSGordon Ross DTRACE_SMB_DONE(op__LockingX, smb_request_t *, sr);
233faa1795aSjb }
234faa1795aSjb
2350897f7fbSGordon Ross struct lreq {
2360897f7fbSGordon Ross uint64_t off;
2370897f7fbSGordon Ross uint64_t len;
2380897f7fbSGordon Ross uint32_t pid;
2390897f7fbSGordon Ross uint32_t reserved;
2400897f7fbSGordon Ross };
2410897f7fbSGordon Ross
242faa1795aSjb smb_sdrc_t
smb_com_locking_andx(smb_request_t * sr)243faa1795aSjb smb_com_locking_andx(smb_request_t *sr)
244da6c28aaSamw {
245da6c28aaSamw unsigned short i;
246da6c28aaSamw unsigned char lock_type; /* See lock_type table above */
247da6c28aaSamw unsigned char oplock_level; /* The new oplock level */
248da6c28aaSamw uint32_t timeout; /* Milliseconds to wait for lock */
249da6c28aaSamw unsigned short unlock_num; /* # unlock range structs */
250da6c28aaSamw unsigned short lock_num; /* # lock range structs */
251da6c28aaSamw DWORD result;
25294047d49SGordon Ross int rc;
253da6c28aaSamw uint32_t ltype;
254cb174861Sjoyce mcintosh smb_ofile_t *ofile;
255a90cf9f2SGordon Ross uint16_t tmp_pid; /* locking uses 16-bit pids */
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);
2637b59d02dSjb if (rc != 0)
264faa1795aSjb return (SDRC_ERROR);
265da6c28aaSamw
2662c2961f8Sjose borrego smbsr_lookup_file(sr);
267da6c28aaSamw if (sr->fid_ofile == NULL) {
268dc20a302Sas smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
269faa1795aSjb 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) {
291*72b35b05SGordon Ross smb1_oplock_ack_break(sr, oplock_level);
292da6c28aaSamw if (unlock_num == 0 && lock_num == 0)
293da6c28aaSamw return (SDRC_NO_REPLY);
294*72b35b05SGordon Ross /*
295*72b35b05SGordon Ross * Don't allow combining other lock/unlock actions
296*72b35b05SGordon Ross * with an oplock ACK (normally don't get here).
297*72b35b05SGordon Ross */
298*72b35b05SGordon Ross smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
299*72b35b05SGordon Ross ERRDOS, ERROR_INVALID_PARAMETER);
300*72b35b05SGordon Ross return (SDRC_ERROR);
301da6c28aaSamw }
302da6c28aaSamw
303da6c28aaSamw /*
304da6c28aaSamw * No support for changing locktype (although we could probably
305da6c28aaSamw * implement this)
306da6c28aaSamw */
307da6c28aaSamw if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) {
308148c5f43SAlan Wright smbsr_error(sr, 0, ERRDOS,
309148c5f43SAlan Wright ERROR_ATOMIC_LOCKS_NOT_SUPPORTED);
310faa1795aSjb return (SDRC_ERROR);
311da6c28aaSamw }
312da6c28aaSamw
313da6c28aaSamw if (lock_type & LOCKING_ANDX_LARGE_FILES) {
314da6c28aaSamw /*
315da6c28aaSamw * negotiated protocol should be NT LM 0.12 or later
316da6c28aaSamw */
317da6c28aaSamw if (sr->session->dialect < NT_LM_0_12) {
318dc20a302Sas smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
319da6c28aaSamw ERRDOS, ERROR_INVALID_PARAMETER);
320faa1795aSjb return (SDRC_ERROR);
321da6c28aaSamw }
3220897f7fbSGordon Ross }
323da6c28aaSamw
3240897f7fbSGordon Ross /*
3250897f7fbSGordon Ross * Parse the unlock, lock vectors. Will parse all the
3260897f7fbSGordon Ross * unlock + lock records into one array, and then use
3270897f7fbSGordon Ross * pointers to the unlock and lock parts.
3280897f7fbSGordon Ross */
3290897f7fbSGordon Ross lrv_tot = unlock_num + lock_num;
3300897f7fbSGordon Ross lrv_ul = smb_srm_zalloc(sr, lrv_tot * sizeof (*lrv_ul));
3310897f7fbSGordon Ross lrv_lk = &lrv_ul[unlock_num];
332da6c28aaSamw
3330897f7fbSGordon Ross for (i = 0; i < lrv_tot; i++) {
3340897f7fbSGordon Ross lr = &lrv_ul[i];
3350897f7fbSGordon Ross if (lock_type & LOCKING_ANDX_LARGE_FILES) {
3360897f7fbSGordon Ross rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
3370897f7fbSGordon Ross &tmp_pid, &lr->off, &lr->len);
3380897f7fbSGordon Ross } else {
3390897f7fbSGordon Ross uint32_t offset32, length32;
3400897f7fbSGordon Ross rc = smb_mbc_decodef(&sr->smb_data, "wll",
3410897f7fbSGordon Ross &tmp_pid, &offset32, &length32);
3420897f7fbSGordon Ross lr->off = offset32;
3430897f7fbSGordon Ross lr->len = length32;
344da6c28aaSamw }
3450897f7fbSGordon Ross lr->pid = tmp_pid; /* 16-bit PID */
3460897f7fbSGordon Ross if (rc) {
3470897f7fbSGordon Ross /*
3480897f7fbSGordon Ross * This is the error returned by Windows 2000
3490897f7fbSGordon Ross * even when STATUS32 has been negotiated.
3500897f7fbSGordon Ross */
3510897f7fbSGordon Ross smbsr_error(sr, 0, ERRSRV, ERRerror);
3520897f7fbSGordon Ross return (SDRC_ERROR);
3530897f7fbSGordon Ross }
3540897f7fbSGordon Ross }
355da6c28aaSamw
3560897f7fbSGordon Ross /*
3570897f7fbSGordon Ross * Cancel waiting locks. MS-CIFS says one place that
3580897f7fbSGordon Ross * this cancels all waiting locks for this FID+PID,
3590897f7fbSGordon Ross * but smbtorture insists this cancels just one.
3600897f7fbSGordon Ross * Tests with Windows 7 confirms that.
3610897f7fbSGordon Ross */
3620897f7fbSGordon Ross if ((lock_type & LOCKING_ANDX_CANCEL_LOCK) != 0) {
3630897f7fbSGordon Ross lr = lrv_lk;
364da6c28aaSamw
3650897f7fbSGordon Ross result = smb_lock_range_cancel(sr, lr->off, lr->len, lr->pid);
366da6c28aaSamw
3670897f7fbSGordon Ross if (result != NT_STATUS_SUCCESS) {
3680897f7fbSGordon Ross smbsr_error(sr, 0, ERRDOS,
3690897f7fbSGordon Ross ERROR_CANCEL_VIOLATION);
3700897f7fbSGordon Ross return (SDRC_ERROR);
371da6c28aaSamw }
3720897f7fbSGordon Ross goto out;
3730897f7fbSGordon Ross }
374da6c28aaSamw
3750897f7fbSGordon Ross /*
3760897f7fbSGordon Ross * Normal unlock and lock list
3770897f7fbSGordon Ross */
3780897f7fbSGordon Ross for (i = 0; i < unlock_num; i++) {
3790897f7fbSGordon Ross lr = &lrv_ul[i];
380da6c28aaSamw
3810897f7fbSGordon Ross result = smb_unlock_range(sr, lr->off, lr->len, lr->pid);
3820897f7fbSGordon Ross if (result != NT_STATUS_SUCCESS) {
3830897f7fbSGordon Ross smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
3840897f7fbSGordon Ross ERRDOS, ERROR_NOT_LOCKED);
3850897f7fbSGordon Ross return (SDRC_ERROR);
3860897f7fbSGordon Ross }
3870897f7fbSGordon Ross }
3880897f7fbSGordon Ross for (i = 0; i < lock_num; i++) {
3890897f7fbSGordon Ross lr = &lrv_lk[i];
3900897f7fbSGordon Ross
3910897f7fbSGordon Ross result = smb_lock_range(sr, lr->off, lr->len, lr->pid,
3920897f7fbSGordon Ross ltype, timeout);
3930897f7fbSGordon Ross if (result != NT_STATUS_SUCCESS) {
3940897f7fbSGordon Ross /*
3950897f7fbSGordon Ross * Oh... we have to rollback.
3960897f7fbSGordon Ross */
3970897f7fbSGordon Ross while (i > 0) {
3980897f7fbSGordon Ross --i;
3990897f7fbSGordon Ross lr = &lrv_lk[i];
4000897f7fbSGordon Ross (void) smb_unlock_range(sr,
4010897f7fbSGordon Ross lr->off, lr->len, lr->pid);
402da6c28aaSamw }
4030897f7fbSGordon Ross smb_lock_range_error(sr, result);
4040897f7fbSGordon Ross return (SDRC_ERROR);
405da6c28aaSamw }
406da6c28aaSamw }
407da6c28aaSamw
4080897f7fbSGordon Ross out:
4090897f7fbSGordon Ross if (smbsr_encode_result(sr, 2, 0, "bb.ww",
4100897f7fbSGordon Ross 2, sr->andx_com, 0x27, 0) != 0)
411faa1795aSjb return (SDRC_ERROR);
412faa1795aSjb return (SDRC_SUCCESS);
413da6c28aaSamw }
414