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 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2020 Tintri by DDN, Inc. All rights reserved.
24 * Copyright 2022 RackTop Systems, Inc.
25 */
26
27 /*
28 * smb1 oplock support
29 */
30
31 #include <smbsrv/smb_kproto.h>
32
33 #define BATCH_OR_EXCL (OPLOCK_LEVEL_BATCH | OPLOCK_LEVEL_ONE)
34
35 /*
36 * This is called by the SMB1 "Locking_andX" handler,
37 * for SMB1 oplock break acknowledgement.
38 * This is an "Ack" from the client.
39 */
40 void
smb1_oplock_ack_break(smb_request_t * sr,uchar_t oplock_level)41 smb1_oplock_ack_break(smb_request_t *sr, uchar_t oplock_level)
42 {
43 smb_ofile_t *ofile;
44 smb_node_t *node;
45 uint32_t NewLevel;
46
47 ofile = sr->fid_ofile;
48 node = ofile->f_node;
49
50 if (oplock_level == 0)
51 NewLevel = OPLOCK_LEVEL_NONE;
52 else
53 NewLevel = OPLOCK_LEVEL_TWO;
54
55 smb_llist_enter(&node->n_ofile_list, RW_READER);
56 mutex_enter(&node->n_oplock.ol_mutex);
57
58 ofile->f_oplock.og_breaking = B_FALSE;
59 cv_broadcast(&ofile->f_oplock.og_ack_cv);
60
61 (void) smb_oplock_ack_break(sr, ofile, &NewLevel);
62
63 ofile->f_oplock.og_state = NewLevel;
64
65 mutex_exit(&node->n_oplock.ol_mutex);
66 smb_llist_exit(&node->n_ofile_list);
67 }
68
69 /*
70 * Compose an SMB1 Oplock Break Notification packet, including
71 * the SMB1 header and everything, in sr->reply.
72 * The caller will send it and free the request.
73 */
74 static void
smb1_oplock_break_notification(smb_request_t * sr,uint32_t NewLevel)75 smb1_oplock_break_notification(smb_request_t *sr, uint32_t NewLevel)
76 {
77 smb_ofile_t *ofile = sr->fid_ofile;
78 uint16_t fid;
79 uint8_t lock_type;
80 uint8_t oplock_level;
81
82 /*
83 * Convert internal level to SMB1
84 */
85 switch (NewLevel) {
86 default:
87 ASSERT(0);
88 /* FALLTHROUGH */
89 case OPLOCK_LEVEL_NONE:
90 oplock_level = 0;
91 break;
92
93 case OPLOCK_LEVEL_TWO:
94 oplock_level = 1;
95 break;
96 }
97
98 sr->smb_com = SMB_COM_LOCKING_ANDX;
99 sr->smb_tid = ofile->f_tree->t_tid;
100 sr->smb_pid = 0xFFFF;
101 sr->smb_uid = 0;
102 sr->smb_mid = 0xFFFF;
103 fid = ofile->f_fid;
104 lock_type = LOCKING_ANDX_OPLOCK_RELEASE;
105
106 (void) smb_mbc_encodef(
107 &sr->reply, "Mb19.wwwwbb3.wbb10.",
108 /* "\xffSMB" M */
109 sr->smb_com, /* b */
110 /* status, flags, signature 19. */
111 sr->smb_tid, /* w */
112 sr->smb_pid, /* w */
113 sr->smb_uid, /* w */
114 sr->smb_mid, /* w */
115 8, /* word count b */
116 0xFF, /* AndX cmd b */
117 /* AndX reserved, offset 3. */
118 fid,
119 lock_type,
120 oplock_level);
121 }
122
123 /*
124 * Send an oplock break over the wire, or if we can't,
125 * then process the oplock break locally.
126 *
127 * [MS-CIFS] 3.3.4.2 Object Store Indicates an OpLock Break
128 *
129 * This is mostly similar to smb2_oplock_send_break()
130 * See top comment there about the design.
131 * Called from smb_oplock_async_break.
132 *
133 * This handles only SMB1, which has no durable handles,
134 * and never has GRANULAR oplocks.
135 */
136 void
smb1_oplock_send_break(smb_request_t * sr)137 smb1_oplock_send_break(smb_request_t *sr)
138 {
139 smb_ofile_t *ofile = sr->fid_ofile;
140 smb_node_t *node = ofile->f_node;
141 uint32_t NewLevel = sr->arg.olbrk.NewLevel;
142 boolean_t AckReq = sr->arg.olbrk.AckRequired;
143 uint32_t status;
144 int rc;
145
146 /*
147 * SMB1 clients should only get Level II oplocks if they
148 * set the capability indicating they know about them.
149 */
150 if (NewLevel == OPLOCK_LEVEL_TWO &&
151 ofile->f_oplock.og_dialect < NT_LM_0_12)
152 NewLevel = OPLOCK_LEVEL_NONE;
153
154 /*
155 * Build the break message in sr->reply.
156 * It's free'd in smb_request_free().
157 * Always SMB1 here.
158 */
159 sr->reply.max_bytes = MLEN;
160 smb1_oplock_break_notification(sr, NewLevel);
161
162 /*
163 * Try to send the break message to the client.
164 * If connected, this IF body will be true.
165 */
166 if (sr->session == ofile->f_session)
167 rc = smb_session_send(sr->session, 0, &sr->reply);
168 else
169 rc = ENOTCONN;
170
171 if (rc != 0) {
172 /*
173 * We were unable to send the oplock break request,
174 * presumably because the connection is gone.
175 * Just close the handle.
176 */
177 smb_ofile_close(ofile, 0);
178 return;
179 }
180
181 /*
182 * OK, we were able to send the break message.
183 * If no ack. required, we're done.
184 */
185 if (!AckReq)
186 return;
187
188 /*
189 * We're expecting an ACK. Wait in this thread
190 * so we can log clients that don't respond.
191 * Note: this can also fail for other reasons
192 * such as client disconnect or server shutdown.
193 */
194 status = smb_oplock_wait_ack(sr, NewLevel);
195 if (status == 0)
196 return;
197
198 DTRACE_PROBE2(wait__ack__failed, smb_request_t *, sr,
199 uint32_t, status);
200
201 /*
202 * Did not get an ACK, so do the ACK locally.
203 * Note: always break to none here, regardless
204 * of what the passed in cache level was.
205 */
206 NewLevel = OPLOCK_LEVEL_NONE;
207
208 smb_llist_enter(&node->n_ofile_list, RW_READER);
209 mutex_enter(&node->n_oplock.ol_mutex);
210
211 ofile->f_oplock.og_breaking = B_FALSE;
212 cv_broadcast(&ofile->f_oplock.og_ack_cv);
213
214 status = smb_oplock_ack_break(sr, ofile, &NewLevel);
215
216 ofile->f_oplock.og_state = NewLevel;
217
218 mutex_exit(&node->n_oplock.ol_mutex);
219 smb_llist_exit(&node->n_ofile_list);
220
221 #ifdef DEBUG
222 if (status != 0) {
223 cmn_err(CE_NOTE, "clnt %s local oplock ack, status=0x%x",
224 sr->session->ip_addr_str, status);
225 }
226 #endif
227 }
228
229 /*
230 * Client has an open handle and requests an oplock.
231 * Convert SMB1 oplock request info in to internal form,
232 * call common oplock code, convert result to SMB1.
233 */
234 void
smb1_oplock_acquire(smb_request_t * sr,boolean_t level2ok)235 smb1_oplock_acquire(smb_request_t *sr, boolean_t level2ok)
236 {
237 smb_arg_open_t *op = &sr->arg.open;
238 smb_ofile_t *ofile = sr->fid_ofile;
239 uint32_t status;
240
241 /* Only disk trees get oplocks. */
242 if ((sr->tid_tree->t_res_type & STYPE_MASK) != STYPE_DISKTREE) {
243 op->op_oplock_level = SMB_OPLOCK_NONE;
244 return;
245 }
246
247 if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_OPLOCKS)) {
248 op->op_oplock_level = SMB_OPLOCK_NONE;
249 return;
250 }
251
252 if (!smb_session_levelII_oplocks(sr->session))
253 level2ok = B_FALSE;
254
255 /* Common code checks file type. */
256
257 /*
258 * SMB1: Convert to internal form.
259 */
260 switch (op->op_oplock_level) {
261 case SMB_OPLOCK_BATCH:
262 op->op_oplock_state = OPLOCK_LEVEL_BATCH;
263 break;
264 case SMB_OPLOCK_EXCLUSIVE:
265 op->op_oplock_state = OPLOCK_LEVEL_ONE;
266 break;
267 case SMB_OPLOCK_LEVEL_II:
268 op->op_oplock_state = OPLOCK_LEVEL_TWO;
269 break;
270 case SMB_OPLOCK_NONE:
271 default:
272 op->op_oplock_level = SMB_OPLOCK_NONE;
273 return;
274 }
275
276 /*
277 * Tree options may force shared oplocks
278 */
279 if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_FORCE_L2_OPLOCK)) {
280 op->op_oplock_state = OPLOCK_LEVEL_TWO;
281 }
282
283 /*
284 * Try exclusive first, if requested
285 */
286 if ((op->op_oplock_state & BATCH_OR_EXCL) != 0) {
287 status = smb_oplock_request(sr, ofile,
288 &op->op_oplock_state);
289 } else {
290 status = NT_STATUS_OPLOCK_NOT_GRANTED;
291 }
292
293 /*
294 * If exclusive failed (or the tree forced shared oplocks)
295 * and if the caller supports Level II, try shared.
296 */
297 if (status == NT_STATUS_OPLOCK_NOT_GRANTED && level2ok) {
298 op->op_oplock_state = OPLOCK_LEVEL_TWO;
299 status = smb_oplock_request(sr, ofile,
300 &op->op_oplock_state);
301 }
302
303 /*
304 * Keep track of what we got (ofile->f_oplock.og_state etc)
305 * so we'll know what we had when sending a break later.
306 * The og_dialect here is the oplock dialect, which may be
307 * different than SMB dialect. Pre-NT clients did not
308 * support "Level II" oplocks. If we're talking to a
309 * client that didn't set the CAP_LEVEL_II_OPLOCKS in
310 * its capabilities, let og_dialect = LANMAN2_1.
311 */
312 switch (status) {
313 case NT_STATUS_SUCCESS:
314 case NT_STATUS_OPLOCK_BREAK_IN_PROGRESS:
315 ofile->f_oplock.og_dialect = (level2ok) ?
316 NT_LM_0_12 : LANMAN2_1;
317 ofile->f_oplock.og_state = op->op_oplock_state;
318 ofile->f_oplock.og_breakto = op->op_oplock_state;
319 ofile->f_oplock.og_breaking = B_FALSE;
320 break;
321 case NT_STATUS_OPLOCK_NOT_GRANTED:
322 op->op_oplock_level = SMB_OPLOCK_NONE;
323 return;
324 default:
325 /* Caller did not check args sufficiently? */
326 cmn_err(CE_NOTE, "clnt %s oplock req. err 0x%x",
327 sr->session->ip_addr_str, status);
328 op->op_oplock_level = SMB_OPLOCK_NONE;
329 return;
330 }
331
332 /*
333 * Only succes cases get here.
334 * Convert internal oplock state to SMB1
335 */
336 if (op->op_oplock_state & OPLOCK_LEVEL_BATCH) {
337 op->op_oplock_level = SMB_OPLOCK_BATCH;
338 } else if (op->op_oplock_state & OPLOCK_LEVEL_ONE) {
339 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
340 } else if (op->op_oplock_state & OPLOCK_LEVEL_TWO) {
341 op->op_oplock_level = SMB_OPLOCK_LEVEL_II;
342 } else {
343 op->op_oplock_level = SMB_OPLOCK_NONE;
344 }
345
346 /*
347 * An smb_oplock_reqest call may have returned the
348 * status code that says we should wait.
349 */
350 if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
351 (void) smb_oplock_wait_break(sr, ofile->f_node, 0);
352 }
353 }
354