1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
25  */
26 
27 /*
28  * SMB: unlock_byte_range
29  *
30  * This message is sent to unlock the given byte range.  Offset, Count, and
31  * Pid must be identical to that specified in a prior successful lock.  If
32  *
33  * an unlock references an address range that is not locked, no error is
34  * generated.
35  *
36  * Since Offset is a 32 bit quantity, this request is inappropriate for
37  * general locking within a very large file.
38  *
39  * Client Request                     Description
40  * ================================== =================================
41  *
42  * UCHAR WordCount;                   Count of parameter words = 5
43  * USHORT Fid;                        File handle
44  * ULONG Count;                       Count of bytes to unlock
45  * ULONG Offset;                      Offset from start of file
46  * USHORT ByteCount;                  Count of data bytes = 0
47  *
48  * Server Response                    Description
49  * ================================== =================================
50  *
51  * UCHAR WordCount;                   Count of parameter words = 0
52  * USHORT ByteCount;                  Count of data bytes = 0
53  */
54 
55 #include <smbsrv/smb_kproto.h>
56 
57 smb_sdrc_t
smb_pre_unlock_byte_range(smb_request_t * sr)58 smb_pre_unlock_byte_range(smb_request_t *sr)
59 {
60 	DTRACE_SMB_START(op__UnlockByteRange, smb_request_t *, sr);
61 	return (SDRC_SUCCESS);
62 }
63 
64 void
smb_post_unlock_byte_range(smb_request_t * sr)65 smb_post_unlock_byte_range(smb_request_t *sr)
66 {
67 	DTRACE_SMB_DONE(op__UnlockByteRange, smb_request_t *, sr);
68 }
69 
70 smb_sdrc_t
smb_com_unlock_byte_range(smb_request_t * sr)71 smb_com_unlock_byte_range(smb_request_t *sr)
72 {
73 	uint32_t	Length;
74 	uint32_t	Offset;
75 	uint32_t	lk_pid;
76 	DWORD		result;
77 
78 	if (smbsr_decode_vwv(sr, "wll", &sr->smb_fid, &Length, &Offset) != 0)
79 		return (SDRC_ERROR);
80 
81 	smbsr_lookup_file(sr);
82 	if (sr->fid_ofile == NULL) {
83 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
84 		return (SDRC_ERROR);
85 	}
86 
87 	/* Note: SMB1 locking uses 16-bit PIDs. */
88 	lk_pid = sr->smb_pid & 0xFFFF;
89 
90 	result = smb_unlock_range(sr, (uint64_t)Offset, (uint64_t)Length,
91 	    lk_pid);
92 	if (result != NT_STATUS_SUCCESS) {
93 		smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
94 		    ERRDOS, ERROR_NOT_LOCKED);
95 		return (SDRC_ERROR);
96 	}
97 
98 	if (smbsr_encode_empty_result(sr))
99 		return (SDRC_ERROR);
100 
101 	return (SDRC_SUCCESS);
102 }
103