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