15331Samw /*
25331Samw * CDDL HEADER START
35331Samw *
45331Samw * The contents of this file are subject to the terms of the
55331Samw * Common Development and Distribution License (the "License").
65331Samw * You may not use this file except in compliance with the License.
75331Samw *
85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw * or http://www.opensolaris.org/os/licensing.
105331Samw * See the License for the specific language governing permissions
115331Samw * and limitations under the License.
125331Samw *
135331Samw * When distributing Covered Code, include this CDDL HEADER in each
145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw * If applicable, add the following below this CDDL HEADER, with the
165331Samw * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw *
195331Samw * CDDL HEADER END
205331Samw */
2112508Samw@Sun.COM
225331Samw /*
2312508Samw@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
245331Samw */
2512508Samw@Sun.COM
265331Samw /*
275331Samw * SMB: locking_andx
285331Samw *
295331Samw * SMB_COM_LOCKING_ANDX allows both locking and/or unlocking of file range(s).
305331Samw *
315331Samw * Client Request Description
325331Samw * ================================== =================================
335331Samw *
345331Samw * UCHAR WordCount; Count of parameter words = 8
355331Samw * UCHAR AndXCommand; Secondary (X) command; 0xFF = none
365331Samw * UCHAR AndXReserved; Reserved (must be 0)
375331Samw * USHORT AndXOffset; Offset to next command WordCount
385331Samw * USHORT Fid; File handle
395331Samw * UCHAR LockType; See LockType table below
405331Samw * UCHAR OplockLevel; The new oplock level
415331Samw * ULONG Timeout; Milliseconds to wait for unlock
425331Samw * USHORT NumberOfUnlocks; Num. unlock range structs following
435331Samw * USHORT NumberOfLocks; Num. lock range structs following
445331Samw * USHORT ByteCount; Count of data bytes
455331Samw * LOCKING_ANDX_RANGE Unlocks[]; Unlock ranges
465331Samw * LOCKING_ANDX_RANGE Locks[]; Lock ranges
475331Samw *
485331Samw * LockType Flag Name Value Description
495331Samw * ============================ ===== ================================
505331Samw *
515331Samw * LOCKING_ANDX_SHARED_LOCK 0x01 Read-only lock
525331Samw * LOCKING_ANDX_OPLOCK_RELEASE 0x02 Oplock break notification
535331Samw * LOCKING_ANDX_CHANGE_LOCKTYPE 0x04 Change lock type
545331Samw * LOCKING_ANDX_CANCEL_LOCK 0x08 Cancel outstanding request
555331Samw * LOCKING_ANDX_LARGE_FILES 0x10 Large file locking format
565331Samw *
575331Samw * LOCKING_ANDX_RANGE Format
585331Samw * =====================================================================
595331Samw *
605331Samw * USHORT Pid; PID of process "owning" lock
615331Samw * ULONG Offset; Offset to bytes to [un]lock
625331Samw * ULONG Length; Number of bytes to [un]lock
635331Samw *
645331Samw * Large File LOCKING_ANDX_RANGE Format
655331Samw * =====================================================================
665331Samw *
675331Samw * USHORT Pid; PID of process "owning" lock
685331Samw * USHORT Pad; Pad to DWORD align (mbz)
695331Samw * ULONG OffsetHigh; Offset to bytes to [un]lock
705331Samw * (high)
715331Samw * ULONG OffsetLow; Offset to bytes to [un]lock (low)
725331Samw * ULONG LengthHigh; Number of bytes to [un]lock
735331Samw * (high)
745331Samw * ULONG LengthLow; Number of bytes to [un]lock (low)
755331Samw *
765331Samw * Server Response Description
775331Samw * ================================== =================================
785331Samw *
795331Samw * UCHAR WordCount; Count of parameter words = 2
805331Samw * UCHAR AndXCommand; Secondary (X) command; 0xFF =
815331Samw * none
825331Samw * UCHAR AndXReserved; Reserved (must be 0)
835331Samw * USHORT AndXOffset; Offset to next command WordCount
845331Samw * USHORT ByteCount; Count of data bytes = 0
855331Samw *
865331Samw * Locking is a simple mechanism for excluding other processes read/write
875331Samw * access to regions of a file. The locked regions can be anywhere in the
885331Samw * logical file. Locking beyond end-of-file is permitted. Any process
895331Samw * using the Fid specified in this request's Fid has access to the locked
905331Samw * bytes, other processes will be denied the locking of the same bytes.
915331Samw *
925331Samw * The proper method for using locks is not to rely on being denied read or
935331Samw * write access on any of the read/write protocols but rather to attempt
945331Samw * the locking protocol and proceed with the read/write only if the locks
955331Samw * succeeded.
965331Samw *
975331Samw * Locking a range of bytes will fail if any subranges or overlapping
985331Samw * ranges are locked. In other words, if any of the specified bytes are
995331Samw * already locked, the lock will fail.
1005331Samw *
1015331Samw * If NumberOfUnlocks is non-zero, the Unlocks vector contains
1025331Samw * NumberOfUnlocks elements. Each element requests that a lock at Offset
1035331Samw * of Length be released. If NumberOfLocks is nonzero, the Locks vector
1045331Samw * contains NumberOfLocks elements. Each element requests the acquisition
1055331Samw * of a lock at Offset of Length.
1065331Samw *
1075331Samw * Timeout is the maximum amount of time to wait for the byte range(s)
1085331Samw * specified to become unlocked. A timeout value of 0 indicates that the
1095331Samw * server should fail immediately if any lock range specified is locked. A
1105331Samw *
1115331Samw * timeout value of -1 indicates that the server should wait as long as it
1125331Samw * takes for each byte range specified to become unlocked so that it may be
1135331Samw * again locked by this protocol. Any other value of smb_timeout specifies
1145331Samw * the maximum number of milliseconds to wait for all lock range(s)
1155331Samw * specified to become available.
1165331Samw *
1175331Samw * If any of the lock ranges timeout because of the area to be locked is
1185331Samw * already locked (or the lock fails), the other ranges in the protocol
1195331Samw * request which were successfully locked as a result of this protocol will
1205331Samw * be unlocked (either all requested ranges will be locked when this
1215331Samw * protocol returns to the client or none).
1225331Samw *
1235331Samw * If LockType has the LOCKING_ANDX_SHARED_LOCK flag set, the lock is
1245331Samw * specified as a shared lock. Locks for both read and write (where
1255331Samw * LOCKING_ANDX_SHARED_LOCK is clear) should be prohibited, but other
1265331Samw * shared locks should be permitted. If shared locks can not be supported
1275331Samw * by a server, the server should map the lock to a lock for both read and
1285331Samw * write. Closing a file with locks still in force causes the locks to be
1295331Samw * released in no defined order.
1305331Samw *
1315331Samw * If LockType has the LOCKING_ANDX_LARGE_FILES flag set and if the
1325331Samw * negotiated protocol is NT LM 0.12 or later, then the Locks and Unlocks
1335331Samw * vectors are in the Large File LOCKING_ANDX_RANGE format. This allows
1345331Samw * specification of 64 bit offsets for very large files.
1355331Samw *
1365331Samw * If the one and only member of the Locks vector has the
1375331Samw * LOCKING_ANDX_CANCEL_LOCK flag set in the LockType field, the client is
1385331Samw * requesting the server to cancel a previously requested, but not yet
1395331Samw * responded to, lock.
1405331Samw *
1415331Samw * If LockType has the LOCKING_ANDX_CHANGE_LOCKTYPE flag set, the client is
1425331Samw * requesting that the server atomically change the lock type from a shared
1435331Samw * lock to an exclusive lock or vice versa. If the server can not do this
1445331Samw * in an atomic fashion, the server must reject this request. NT and W95
1455331Samw * servers do not support this capability.
1465331Samw *
1475331Samw * Oplocks are described in the "Opportunistic Locks" section elsewhere in
1485331Samw * this document. A client requests an oplock by setting the appropriate
1495331Samw * bit in the SMB_COM_OPEN_ANDX request when the file is being opened in a
1505331Samw * mode which is not exclusive. The server responds by setting the
1515331Samw * appropriate bit in the response SMB indicating whether or not the oplock
1525331Samw * was granted. By granting the oplock, the server tells the client the
1535331Samw * file is currently only being used by this one client process at the
1545331Samw * current time. The client can therefore safely do read ahead and write
1555331Samw * behind as well as local caching of file locks knowing that the file will
1565331Samw * not be accessed/changed in any way by another process while the oplock
1575331Samw * is in effect. The client will be notified when any other process
1585331Samw * attempts to open or modify the oplocked file.
1595331Samw *
1605331Samw * When another user attempts to open or otherwise modify the file which a
1615331Samw * client has oplocked, the server delays the second attempt and notifies
1625331Samw * the client via an SMB_LOCKING_ANDX SMB asynchronously sent from the
1635331Samw * server to the client. This message has the LOCKING_ANDX_OPLOCK_RELEASE
1645331Samw * flag set indicating to the client that the oplock is being broken.
1655331Samw *
1665331Samw * OplockLevel indicates the type of oplock the client now owns. If
1675331Samw * OplockLevel is 0, the client possesses no oplocks on the file at all, if
1685331Samw * OplockLevel is 1 the client possesses a Level II oplock. The client is
1695331Samw * expected to flush any dirty buffers to the server, submit any file locks
1705331Samw * and respond to the server with either an SMB_LOCKING_ANDX SMB having the
1715331Samw * LOCKING_ANDX_OPLOCK_RELEASE flag set, or with a file close if the file
1725331Samw * is no longer in use by the client. If the client sends an
1735331Samw * SMB_LOCKING_ANDX SMB with the LOCKING_ANDX_OPLOCK_RELEASE flag set and
1745331Samw * NumberOfLocks is zero, the server does not send a response. Since a
1755331Samw * close being sent to the server and break oplock notification from the
1765331Samw * server could cross on the wire, if the client gets an oplock
1775331Samw * notification on a file which it does not have open, that notification
1785331Samw * should be ignored.
1795331Samw *
1805331Samw * Due to timing, the client could get an "oplock broken" notification in a
1815331Samw * user's data buffer as a result of this notification crossing on the wire
1825331Samw * with a SMB_COM_READ_RAW request. The client must detect this (use
1835331Samw * length of msg, "FFSMB", MID of -1 and Command of SMB_COM_LOCKING_ANDX)
1845331Samw * and honor the "oplock broken" notification as usual. The server must
1855331Samw * also note on receipt of an SMB_COM_READ_RAW request that there is an
1865331Samw * outstanding (unanswered) "oplock broken" notification to the client and
1875331Samw * return a zero length response denoting failure of the read raw request.
1885331Samw * The client should (after responding to the "oplock broken"
1895331Samw * notification), use a standard read protocol to redo the read request.
1905331Samw * This allows a file to actually contain data matching an "oplock broken"
1915331Samw * notification and still be read correctly.
1925331Samw *
1935331Samw * The entire message sent and received including the optional second
1945331Samw * protocol must fit in the negotiated maximum transfer size. The
1955331Samw * following are the only valid SMB commands for AndXCommand for
1965331Samw * SMB_COM_LOCKING_ANDX:
1975331Samw *
1985331Samw * SMB_COM_READ SMB_COM_READ_ANDX
1995331Samw * SMB_COM_WRITE SMB_COM_WRITE_ANDX
2005331Samw * SMB_COM_FLUSH
2015331Samw *
2025331Samw * 4.2.6.1 Errors
2035331Samw *
2045331Samw * ERRDOS/ERRbadfile
2055331Samw * ERRDOS/ERRbadfid
2065331Samw * ERRDOS/ERRlock
2075331Samw * ERRDOS/ERRinvdevice
2085331Samw * ERRSRV/ERRinvid
2095331Samw * ERRSRV/ERRbaduid
2105331Samw */
2115331Samw
21210966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
2135331Samw
2146030Sjb150015 smb_sdrc_t
smb_pre_locking_andx(smb_request_t * sr)2156139Sjb150015 smb_pre_locking_andx(smb_request_t *sr)
2166139Sjb150015 {
2176139Sjb150015 DTRACE_SMB_1(op__LockingX__start, smb_request_t *, sr);
2186139Sjb150015 return (SDRC_SUCCESS);
2196139Sjb150015 }
2206139Sjb150015
2216139Sjb150015 void
smb_post_locking_andx(smb_request_t * sr)2226139Sjb150015 smb_post_locking_andx(smb_request_t *sr)
2236139Sjb150015 {
2246139Sjb150015 DTRACE_SMB_1(op__LockingX__done, smb_request_t *, sr);
2256139Sjb150015 }
2266139Sjb150015
2276139Sjb150015 smb_sdrc_t
smb_com_locking_andx(smb_request_t * sr)2286139Sjb150015 smb_com_locking_andx(smb_request_t *sr)
2295331Samw {
2305331Samw unsigned short i;
2315331Samw unsigned char lock_type; /* See lock_type table above */
2325331Samw unsigned char oplock_level; /* The new oplock level */
2335331Samw uint32_t timeout; /* Milliseconds to wait for lock */
2345331Samw unsigned short unlock_num; /* # unlock range structs */
2355331Samw unsigned short lock_num; /* # lock range structs */
2365331Samw unsigned short pid; /* Process Id of owner */
2375331Samw uint32_t offset32, length32;
2385331Samw uint64_t offset64;
2395331Samw uint64_t length64;
2405331Samw DWORD result;
2415331Samw int rc;
2425331Samw uint32_t ltype;
243*12890SJoyce.McIntosh@Sun.COM smb_ofile_t *ofile;
244*12890SJoyce.McIntosh@Sun.COM uint8_t brk;
2455331Samw
2465331Samw rc = smbsr_decode_vwv(sr, "4.wbblww", &sr->smb_fid, &lock_type,
2475331Samw &oplock_level, &timeout, &unlock_num, &lock_num);
2486030Sjb150015 if (rc != 0)
2496139Sjb150015 return (SDRC_ERROR);
2505331Samw
2518934SJose.Borrego@Sun.COM smbsr_lookup_file(sr);
2525331Samw if (sr->fid_ofile == NULL) {
2535772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
2546139Sjb150015 return (SDRC_ERROR);
2555331Samw }
256*12890SJoyce.McIntosh@Sun.COM ofile = sr->fid_ofile;
2575331Samw
2585331Samw if (lock_type & LOCKING_ANDX_SHARED_LOCK)
2595331Samw ltype = SMB_LOCK_TYPE_READONLY;
2605331Samw else
2615331Samw ltype = SMB_LOCK_TYPE_READWRITE;
2625331Samw
2635331Samw pid = sr->smb_pid; /* Save the original pid */
2645331Samw
2655331Samw if (lock_type & LOCKING_ANDX_OPLOCK_RELEASE) {
266*12890SJoyce.McIntosh@Sun.COM if (oplock_level == 0)
267*12890SJoyce.McIntosh@Sun.COM brk = SMB_OPLOCK_BREAK_TO_NONE;
268*12890SJoyce.McIntosh@Sun.COM else
269*12890SJoyce.McIntosh@Sun.COM brk = SMB_OPLOCK_BREAK_TO_LEVEL_II;
270*12890SJoyce.McIntosh@Sun.COM smb_oplock_ack(ofile->f_node, ofile, brk);
2715331Samw if (unlock_num == 0 && lock_num == 0)
2725331Samw return (SDRC_NO_REPLY);
2735331Samw }
2745331Samw
2755331Samw /*
2765331Samw * No support for changing locktype (although we could probably
2775331Samw * implement this)
2785331Samw */
2795331Samw if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) {
28012508Samw@Sun.COM smbsr_error(sr, 0, ERRDOS,
28112508Samw@Sun.COM ERROR_ATOMIC_LOCKS_NOT_SUPPORTED);
2826139Sjb150015 return (SDRC_ERROR);
2835331Samw }
2845331Samw
2855331Samw /*
2865331Samw * No support for cancel lock (smbtorture expects this)
2875331Samw */
2885331Samw if (lock_type & LOCKING_ANDX_CANCEL_LOCK) {
2895772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
2905331Samw ERRDOS, ERROR_INVALID_PARAMETER);
2916139Sjb150015 return (SDRC_ERROR);
2925331Samw }
2935331Samw
2945331Samw if (lock_type & LOCKING_ANDX_LARGE_FILES) {
2955331Samw /*
2965331Samw * negotiated protocol should be NT LM 0.12 or later
2975331Samw */
2985331Samw if (sr->session->dialect < NT_LM_0_12) {
2995772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
3005331Samw ERRDOS, ERROR_INVALID_PARAMETER);
3016139Sjb150015 return (SDRC_ERROR);
3025331Samw }
3035331Samw
3045331Samw for (i = 0; i < unlock_num; i++) {
3057052Samw rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
3065331Samw &sr->smb_pid, &offset64, &length64);
3075331Samw if (rc) {
3085331Samw /*
3095772Sas200622 * This is the error returned by Windows 2000
3105772Sas200622 * even when STATUS32 has been negotiated.
3115331Samw */
3125772Sas200622 smbsr_error(sr, 0, ERRSRV, ERRerror);
3136139Sjb150015 return (SDRC_ERROR);
3145331Samw }
3155331Samw
3165331Samw result = smb_unlock_range(sr, sr->fid_ofile->f_node,
3175331Samw offset64, length64);
3185331Samw if (result != NT_STATUS_SUCCESS) {
3195772Sas200622 smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
32012508Samw@Sun.COM ERRDOS, ERROR_NOT_LOCKED);
3216139Sjb150015 return (SDRC_ERROR);
3225331Samw }
3235331Samw }
3245331Samw
3255331Samw for (i = 0; i < lock_num; i++) {
3267052Samw rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
3275331Samw &sr->smb_pid, &offset64, &length64);
3285331Samw if (rc) {
3295772Sas200622 smbsr_error(sr, 0, ERRSRV, ERRerror);
3306139Sjb150015 return (SDRC_ERROR);
3315331Samw }
3325331Samw
3336432Sas200622 result = smb_lock_range(sr, offset64, length64, timeout,
3346432Sas200622 ltype);
3355331Samw if (result != NT_STATUS_SUCCESS) {
3365772Sas200622 smb_lock_range_error(sr, result);
3376139Sjb150015 return (SDRC_ERROR);
3385331Samw }
3395331Samw }
3405331Samw } else {
3415331Samw for (i = 0; i < unlock_num; i++) {
3427052Samw rc = smb_mbc_decodef(&sr->smb_data, "wll", &sr->smb_pid,
3435331Samw &offset32, &length32);
3445331Samw if (rc) {
3455772Sas200622 smbsr_error(sr, 0, ERRSRV, ERRerror);
3466139Sjb150015 return (SDRC_ERROR);
3475331Samw }
3485331Samw
3495331Samw result = smb_unlock_range(sr, sr->fid_ofile->f_node,
3505331Samw (uint64_t)offset32, (uint64_t)length32);
3515331Samw if (result != NT_STATUS_SUCCESS) {
3525772Sas200622 smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
35312508Samw@Sun.COM ERRDOS, ERROR_NOT_LOCKED);
3546139Sjb150015 return (SDRC_ERROR);
3555331Samw }
3565331Samw }
3575331Samw
3585331Samw for (i = 0; i < lock_num; i++) {
3597052Samw rc = smb_mbc_decodef(&sr->smb_data, "wll", &sr->smb_pid,
3605331Samw &offset32, &length32);
3615331Samw if (rc) {
3625772Sas200622 smbsr_error(sr, 0, ERRSRV, ERRerror);
3636139Sjb150015 return (SDRC_ERROR);
3645331Samw }
3655331Samw
3666432Sas200622 result = smb_lock_range(sr, (uint64_t)offset32,
3676432Sas200622 (uint64_t)length32, timeout, ltype);
3685331Samw if (result != NT_STATUS_SUCCESS) {
3695772Sas200622 smb_lock_range_error(sr, result);
3706139Sjb150015 return (SDRC_ERROR);
3715331Samw }
3725331Samw }
3735331Samw }
3745331Samw
3755331Samw sr->smb_pid = pid;
3766030Sjb150015 if (smbsr_encode_result(sr, 2, 0, "bb.ww", 2, sr->andx_com, 7, 0))
3776139Sjb150015 return (SDRC_ERROR);
3786139Sjb150015 return (SDRC_SUCCESS);
3795331Samw }
380