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 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 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 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 */ 192 status = smb_oplock_wait_ack(sr, NewLevel); 193 if (status == 0) 194 return; 195 196 cmn_err(CE_NOTE, "clnt %s oplock break timeout", 197 sr->session->ip_addr_str); 198 DTRACE_PROBE1(ack_timeout, smb_request_t *, sr); 199 200 /* 201 * Did not get an ACK, so do the ACK locally. 202 * Note: always break to none here, regardless 203 * of what the passed in cache level was. 204 */ 205 NewLevel = OPLOCK_LEVEL_NONE; 206 207 smb_llist_enter(&node->n_ofile_list, RW_READER); 208 mutex_enter(&node->n_oplock.ol_mutex); 209 210 ofile->f_oplock.og_breaking = B_FALSE; 211 cv_broadcast(&ofile->f_oplock.og_ack_cv); 212 213 status = smb_oplock_ack_break(sr, ofile, &NewLevel); 214 215 ofile->f_oplock.og_state = NewLevel; 216 217 mutex_exit(&node->n_oplock.ol_mutex); 218 smb_llist_exit(&node->n_ofile_list); 219 220 #ifdef DEBUG 221 if (status != 0) { 222 cmn_err(CE_NOTE, "clnt %s local oplock ack, status=0x%x", 223 sr->session->ip_addr_str, status); 224 } 225 #endif 226 } 227 228 /* 229 * Client has an open handle and requests an oplock. 230 * Convert SMB1 oplock request info in to internal form, 231 * call common oplock code, convert result to SMB1. 232 */ 233 void 234 smb1_oplock_acquire(smb_request_t *sr, boolean_t level2ok) 235 { 236 smb_arg_open_t *op = &sr->arg.open; 237 smb_ofile_t *ofile = sr->fid_ofile; 238 uint32_t status; 239 240 /* Only disk trees get oplocks. */ 241 if ((sr->tid_tree->t_res_type & STYPE_MASK) != STYPE_DISKTREE) { 242 op->op_oplock_level = SMB_OPLOCK_NONE; 243 return; 244 } 245 246 if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_OPLOCKS)) { 247 op->op_oplock_level = SMB_OPLOCK_NONE; 248 return; 249 } 250 251 if (!smb_session_levelII_oplocks(sr->session)) 252 level2ok = B_FALSE; 253 254 /* Common code checks file type. */ 255 256 /* 257 * SMB1: Convert to internal form. 258 */ 259 switch (op->op_oplock_level) { 260 case SMB_OPLOCK_BATCH: 261 op->op_oplock_state = OPLOCK_LEVEL_BATCH; 262 break; 263 case SMB_OPLOCK_EXCLUSIVE: 264 op->op_oplock_state = OPLOCK_LEVEL_ONE; 265 break; 266 case SMB_OPLOCK_LEVEL_II: 267 op->op_oplock_state = OPLOCK_LEVEL_TWO; 268 break; 269 case SMB_OPLOCK_NONE: 270 default: 271 op->op_oplock_level = SMB_OPLOCK_NONE; 272 return; 273 } 274 275 /* 276 * Tree options may force shared oplocks 277 */ 278 if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_FORCE_L2_OPLOCK)) { 279 op->op_oplock_state = OPLOCK_LEVEL_TWO; 280 } 281 282 /* 283 * Try exclusive first, if requested 284 */ 285 if ((op->op_oplock_state & BATCH_OR_EXCL) != 0) { 286 status = smb_oplock_request(sr, ofile, 287 &op->op_oplock_state); 288 } else { 289 status = NT_STATUS_OPLOCK_NOT_GRANTED; 290 } 291 292 /* 293 * If exclusive failed (or the tree forced shared oplocks) 294 * and if the caller supports Level II, try shared. 295 */ 296 if (status == NT_STATUS_OPLOCK_NOT_GRANTED && level2ok) { 297 op->op_oplock_state = OPLOCK_LEVEL_TWO; 298 status = smb_oplock_request(sr, ofile, 299 &op->op_oplock_state); 300 } 301 302 /* 303 * Keep track of what we got (ofile->f_oplock.og_state etc) 304 * so we'll know what we had when sending a break later. 305 * The og_dialect here is the oplock dialect, which may be 306 * different than SMB dialect. Pre-NT clients did not 307 * support "Level II" oplocks. If we're talking to a 308 * client that didn't set the CAP_LEVEL_II_OPLOCKS in 309 * its capabilities, let og_dialect = LANMAN2_1. 310 */ 311 switch (status) { 312 case NT_STATUS_SUCCESS: 313 case NT_STATUS_OPLOCK_BREAK_IN_PROGRESS: 314 ofile->f_oplock.og_dialect = (level2ok) ? 315 NT_LM_0_12 : LANMAN2_1; 316 ofile->f_oplock.og_state = op->op_oplock_state; 317 ofile->f_oplock.og_breakto = op->op_oplock_state; 318 ofile->f_oplock.og_breaking = B_FALSE; 319 break; 320 case NT_STATUS_OPLOCK_NOT_GRANTED: 321 op->op_oplock_level = SMB_OPLOCK_NONE; 322 return; 323 default: 324 /* Caller did not check args sufficiently? */ 325 cmn_err(CE_NOTE, "clnt %s oplock req. err 0x%x", 326 sr->session->ip_addr_str, status); 327 op->op_oplock_level = SMB_OPLOCK_NONE; 328 return; 329 } 330 331 /* 332 * Only succes cases get here. 333 * Convert internal oplock state to SMB1 334 */ 335 if (op->op_oplock_state & OPLOCK_LEVEL_BATCH) { 336 op->op_oplock_level = SMB_OPLOCK_BATCH; 337 } else if (op->op_oplock_state & OPLOCK_LEVEL_ONE) { 338 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 339 } else if (op->op_oplock_state & OPLOCK_LEVEL_TWO) { 340 op->op_oplock_level = SMB_OPLOCK_LEVEL_II; 341 } else { 342 op->op_oplock_level = SMB_OPLOCK_NONE; 343 } 344 345 /* 346 * An smb_oplock_reqest call may have returned the 347 * status code that says we should wait. 348 */ 349 if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) { 350 (void) smb_oplock_wait_break(sr, ofile->f_node, 0); 351 } 352 } 353