2 Unix SMB/CIFS implementation.
4 test suite for SMB2 oplocks
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Stefan Metzmacher 2008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "libcli/smb2/smb2.h"
26 #include "libcli/smb2/smb2_calls.h"
27 #include "libcli/smb_composite/smb_composite.h"
28 #include "libcli/resolve/resolve.h"
30 #include "lib/cmdline/popt_common.h"
31 #include "lib/events/events.h"
33 #include "param/param.h"
34 #include "system/filesys.h"
36 #include "torture/torture.h"
37 #include "torture/smb2/proto.h"
39 #include "lib/util/sys_rw.h"
41 #define CHECK_RANGE(v, min, max) do { \
42 if ((v) < (min) || (v) > (max)) { \
43 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s " \
44 "got %d - should be between %d and %d\n", \
45 __location__, #v, (int)v, (int)min, (int)max); \
49 #define CHECK_STRMATCH(v, correct) do { \
50 if (!v || strstr((v),(correct)) == NULL) { \
51 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s "\
52 "got '%s' - should be '%s'\n", \
53 __location__, #v, v?v:"NULL", correct); \
57 #define CHECK_VAL(v, correct) do { \
58 if ((v) != (correct)) { \
59 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s " \
60 "got 0x%x - should be 0x%x\n", \
61 __location__, #v, (int)v, (int)correct); \
65 #define BASEDIR "oplock_test"
68 struct smb2_handle handle;
73 NTSTATUS failure_status;
76 static void torture_oplock_break_callback(struct smb2_request *req)
82 status = smb2_break_recv(req, &break_info.br);
83 if (!NT_STATUS_IS_OK(status)) {
84 break_info.failures++;
85 break_info.failure_status = status;
91 /* A general oplock break notification handler. This should be used when a
92 * test expects to break from batch or exclusive to a lower level. */
93 static bool torture_oplock_handler(struct smb2_transport *transport,
94 const struct smb2_handle *handle,
98 struct smb2_tree *tree = private_data;
100 struct smb2_request *req;
101 ZERO_STRUCT(break_info.br);
103 break_info.handle = *handle;
104 break_info.level = level;
108 case SMB2_OPLOCK_LEVEL_II:
111 case SMB2_OPLOCK_LEVEL_NONE:
116 break_info.failures++;
118 printf("Acking to %s [0x%02X] in oplock handler\n", name, level);
120 break_info.br.in.file.handle = *handle;
121 break_info.br.in.oplock_level = level;
122 break_info.br.in.reserved = 0;
123 break_info.br.in.reserved2 = 0;
125 req = smb2_break_send(tree, &break_info.br);
126 req->async.fn = torture_oplock_break_callback;
127 req->async.private_data = NULL;
132 A handler function for oplock break notifications. Send a break to none
135 static bool torture_oplock_handler_ack_to_none(struct smb2_transport *transport,
136 const struct smb2_handle *handle,
140 struct smb2_tree *tree = private_data;
141 struct smb2_request *req;
143 break_info.handle = *handle;
144 break_info.level = level;
147 printf("Acking to none in oplock handler\n");
149 ZERO_STRUCT(break_info.br);
150 break_info.br.in.file.handle = *handle;
151 break_info.br.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
152 break_info.br.in.reserved = 0;
153 break_info.br.in.reserved2 = 0;
155 req = smb2_break_send(tree, &break_info.br);
156 req->async.fn = torture_oplock_break_callback;
157 req->async.private_data = NULL;
163 A handler function for oplock break notifications. Break from level II to
164 none. SMB2 requires that the client does not send an oplock break request to
165 the server in this case.
167 static bool torture_oplock_handler_level2_to_none(
168 struct smb2_transport *transport,
169 const struct smb2_handle *handle,
173 break_info.handle = *handle;
174 break_info.level = level;
177 printf("Break from level II to none in oplock handler\n");
182 /* A handler function for oplock break notifications. This should be used when
183 * test expects two break notifications, first to level II, then to none. */
184 static bool torture_oplock_handler_two_notifications(
185 struct smb2_transport *transport,
186 const struct smb2_handle *handle,
190 struct smb2_tree *tree = private_data;
192 struct smb2_request *req;
193 ZERO_STRUCT(break_info.br);
195 break_info.handle = *handle;
196 break_info.level = level;
200 case SMB2_OPLOCK_LEVEL_II:
203 case SMB2_OPLOCK_LEVEL_NONE:
208 break_info.failures++;
210 printf("Breaking to %s [0x%02X] in oplock handler\n", name, level);
212 if (level == SMB2_OPLOCK_LEVEL_NONE)
215 break_info.br.in.file.handle = *handle;
216 break_info.br.in.oplock_level = level;
217 break_info.br.in.reserved = 0;
218 break_info.br.in.reserved2 = 0;
220 req = smb2_break_send(tree, &break_info.br);
221 req->async.fn = torture_oplock_break_callback;
222 req->async.private_data = NULL;
225 static void torture_oplock_handler_close_recv(struct smb2_request *req)
227 if (!smb2_request_receive(req)) {
228 printf("close failed in oplock_handler_close\n");
229 break_info.failures++;
234 a handler function for oplock break requests - close the file
236 static bool torture_oplock_handler_close(struct smb2_transport *transport,
237 const struct smb2_handle *handle,
241 struct smb2_close io;
242 struct smb2_tree *tree = private_data;
243 struct smb2_request *req;
245 break_info.handle = *handle;
246 break_info.level = level;
250 io.in.file.handle = *handle;
251 io.in.flags = RAW_CLOSE_SMB2;
252 req = smb2_close_send(tree, &io);
254 printf("failed to send close in oplock_handler_close\n");
258 req->async.fn = torture_oplock_handler_close_recv;
259 req->async.private_data = NULL;
265 a handler function for oplock break requests. Let it timeout
267 static bool torture_oplock_handler_timeout(struct smb2_transport *transport,
268 const struct smb2_handle *handle,
272 break_info.handle = *handle;
273 break_info.level = level;
276 printf("Let oplock break timeout\n");
280 static bool open_smb2_connection_no_level2_oplocks(struct torture_context *tctx,
281 struct smb2_tree **tree)
284 const char *host = torture_setting_string(tctx, "host", NULL);
285 const char *share = torture_setting_string(tctx, "share", NULL);
286 struct smbcli_options options;
288 lpcfg_smbcli_options(tctx->lp_ctx, &options);
289 options.use_level2_oplocks = false;
291 status = smb2_connect(tctx, host,
292 lpcfg_smb_ports(tctx->lp_ctx), share,
293 lpcfg_resolve_context(tctx->lp_ctx),
294 popt_get_cmdline_credentials(),
295 tree, tctx->ev, &options,
296 lpcfg_socket_options(tctx->lp_ctx),
297 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
298 if (!NT_STATUS_IS_OK(status)) {
299 torture_comment(tctx, "Failed to connect to SMB2 share "
300 "\\\\%s\\%s - %s\n", host, share,
308 Timer handler function notifies the registering function that time is up
310 static void timeout_cb(struct tevent_context *ev,
311 struct tevent_timer *te,
312 struct timeval current_time,
315 bool *timesup = (bool *)private_data;
321 Wait a short period of time to receive a single oplock break request
323 static void torture_wait_for_oplock_break(struct torture_context *tctx)
325 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
326 struct tevent_timer *te = NULL;
328 bool timesup = false;
329 int old_count = break_info.count;
331 /* Wait .1 seconds for an oplock break */
332 ne = tevent_timeval_current_ofs(0, 100000);
334 if ((te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, ×up))
337 torture_comment(tctx, "Failed to wait for an oplock break. "
338 "test results may not be accurate.");
342 while (!timesup && break_info.count < old_count + 1) {
343 if (tevent_loop_once(tctx->ev) != 0) {
344 torture_comment(tctx, "Failed to wait for an oplock "
345 "break. test results may not be "
352 /* We don't know if the timed event fired and was freed, we received
353 * our oplock break, or some other event triggered the loop. Thus,
354 * we create a tmp_ctx to be able to safely free/remove the timed
355 * event in all 3 cases. */
356 talloc_free(tmp_ctx);
361 static bool test_smb2_oplock_exclusive1(struct torture_context *tctx,
362 struct smb2_tree *tree1,
363 struct smb2_tree *tree2)
365 const char *fname = BASEDIR "\\test_exclusive1.dat";
369 struct smb2_handle h1;
370 struct smb2_handle h;
372 status = torture_smb2_testdir(tree1, BASEDIR, &h);
373 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
376 smb2_util_unlink(tree1, fname);
378 tree1->session->transport->oplock.handler = torture_oplock_handler;
379 tree1->session->transport->oplock.private_data = tree1;
384 ZERO_STRUCT(io.smb2);
385 io.generic.level = RAW_OPEN_SMB2;
386 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
387 io.smb2.in.alloc_size = 0;
388 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
389 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
390 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
391 io.smb2.in.create_options = 0;
392 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
393 io.smb2.in.security_flags = 0;
394 io.smb2.in.fname = fname;
396 torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive "
397 "oplock (share mode: none)\n");
398 ZERO_STRUCT(break_info);
399 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
401 status = smb2_create(tree1, tctx, &(io.smb2));
402 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
403 h1 = io.smb2.out.file.handle;
404 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
406 torture_comment(tctx, "a 2nd open should not cause a break\n");
407 status = smb2_create(tree2, tctx, &(io.smb2));
408 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
410 torture_wait_for_oplock_break(tctx);
411 CHECK_VAL(break_info.count, 0);
412 CHECK_VAL(break_info.failures, 0);
414 torture_comment(tctx, "unlink it - should also be no break\n");
415 status = smb2_util_unlink(tree2, fname);
416 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
418 torture_wait_for_oplock_break(tctx);
419 CHECK_VAL(break_info.count, 0);
420 CHECK_VAL(break_info.failures, 0);
422 smb2_util_close(tree1, h1);
423 smb2_util_close(tree1, h);
425 smb2_deltree(tree1, BASEDIR);
429 static bool test_smb2_oplock_exclusive2(struct torture_context *tctx,
430 struct smb2_tree *tree1,
431 struct smb2_tree *tree2)
433 const char *fname = BASEDIR "\\test_exclusive2.dat";
437 struct smb2_handle h, h1, h2;
439 status = torture_smb2_testdir(tree1, BASEDIR, &h);
440 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
443 smb2_util_unlink(tree1, fname);
445 tree1->session->transport->oplock.handler = torture_oplock_handler;
446 tree1->session->transport->oplock.private_data = tree1;
451 ZERO_STRUCT(io.smb2);
452 io.generic.level = RAW_OPEN_SMB2;
453 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
454 io.smb2.in.alloc_size = 0;
455 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
456 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
457 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
458 io.smb2.in.create_options = 0;
459 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
460 io.smb2.in.security_flags = 0;
461 io.smb2.in.fname = fname;
463 torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive "
464 "oplock (share mode: all)\n");
465 ZERO_STRUCT(break_info);
466 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
467 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
468 NTCREATEX_SHARE_ACCESS_WRITE|
469 NTCREATEX_SHARE_ACCESS_DELETE;
470 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
472 status = smb2_create(tree1, tctx, &(io.smb2));
473 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
474 h1 = io.smb2.out.file.handle;
475 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
477 torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
478 status = smb2_create(tree2, tctx, &(io.smb2));
479 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
480 h2 = io.smb2.out.file.handle;
481 torture_wait_for_oplock_break(tctx);
482 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
483 CHECK_VAL(break_info.count, 1);
484 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
485 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
486 CHECK_VAL(break_info.failures, 0);
487 ZERO_STRUCT(break_info);
489 /* now we have 2 level II oplocks... */
490 torture_comment(tctx, "try to unlink it - should cause a break\n");
491 status = smb2_util_unlink(tree2, fname);
492 torture_assert_ntstatus_ok(tctx, status, "Error unlinking the file");
493 torture_wait_for_oplock_break(tctx);
494 CHECK_VAL(break_info.count, 0);
495 CHECK_VAL(break_info.failures, 0);
497 torture_comment(tctx, "close both handles\n");
498 smb2_util_close(tree1, h1);
499 smb2_util_close(tree1, h2);
500 smb2_util_close(tree1, h);
502 smb2_deltree(tree1, BASEDIR);
506 static bool test_smb2_oplock_exclusive3(struct torture_context *tctx,
507 struct smb2_tree *tree1,
508 struct smb2_tree *tree2)
510 const char *fname = BASEDIR "\\test_exclusive3.dat";
514 union smb_setfileinfo sfi;
515 struct smb2_handle h, h1;
517 status = torture_smb2_testdir(tree1, BASEDIR, &h);
518 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
521 smb2_util_unlink(tree1, fname);
523 tree1->session->transport->oplock.handler = torture_oplock_handler;
524 tree1->session->transport->oplock.private_data = tree1;
529 ZERO_STRUCT(io.smb2);
530 io.generic.level = RAW_OPEN_SMB2;
531 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
532 io.smb2.in.alloc_size = 0;
533 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
534 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
535 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
536 io.smb2.in.create_options = 0;
537 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
538 io.smb2.in.security_flags = 0;
539 io.smb2.in.fname = fname;
541 torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive "
542 "oplock (share mode: none)\n");
544 ZERO_STRUCT(break_info);
545 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
546 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
548 status = smb2_create(tree1, tctx, &(io.smb2));
549 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
550 h1 = io.smb2.out.file.handle;
551 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
553 torture_comment(tctx, "setpathinfo EOF should trigger a break to "
556 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
557 sfi.generic.in.file.path = fname;
558 sfi.end_of_file_info.in.size = 100;
560 status = smb2_composite_setpathinfo(tree2, &sfi);
562 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
564 torture_wait_for_oplock_break(tctx);
565 CHECK_VAL(break_info.count, 0);
566 CHECK_VAL(break_info.failures, 0);
567 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
569 smb2_util_close(tree1, h1);
570 smb2_util_close(tree1, h);
572 smb2_deltree(tree1, BASEDIR);
576 static bool test_smb2_oplock_exclusive4(struct torture_context *tctx,
577 struct smb2_tree *tree1,
578 struct smb2_tree *tree2)
580 const char *fname = BASEDIR "\\test_exclusive4.dat";
584 struct smb2_handle h, h1, h2;
586 status = torture_smb2_testdir(tree1, BASEDIR, &h);
587 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
590 smb2_util_unlink(tree1, fname);
592 tree1->session->transport->oplock.handler = torture_oplock_handler;
593 tree1->session->transport->oplock.private_data = tree1;
598 ZERO_STRUCT(io.smb2);
599 io.generic.level = RAW_OPEN_SMB2;
600 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
601 io.smb2.in.alloc_size = 0;
602 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
603 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
604 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
605 io.smb2.in.create_options = 0;
606 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
607 io.smb2.in.security_flags = 0;
608 io.smb2.in.fname = fname;
610 torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
611 ZERO_STRUCT(break_info);
613 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
614 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
615 status = smb2_create(tree1, tctx, &(io.smb2));
616 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
617 h1 = io.smb2.out.file.handle;
618 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
620 ZERO_STRUCT(break_info);
621 torture_comment(tctx, "second open with attributes only shouldn't "
622 "cause oplock break\n");
624 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
625 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
626 SEC_FILE_WRITE_ATTRIBUTE |
628 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
629 status = smb2_create(tree2, tctx, &(io.smb2));
630 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
631 h2 = io.smb2.out.file.handle;
632 CHECK_VAL(io.smb2.out.oplock_level, NO_OPLOCK_RETURN);
633 torture_wait_for_oplock_break(tctx);
634 CHECK_VAL(break_info.count, 0);
635 CHECK_VAL(break_info.failures, 0);
637 smb2_util_close(tree1, h1);
638 smb2_util_close(tree2, h2);
639 smb2_util_close(tree1, h);
641 smb2_deltree(tree1, BASEDIR);
645 static bool test_smb2_oplock_exclusive5(struct torture_context *tctx,
646 struct smb2_tree *tree1,
647 struct smb2_tree *tree2)
649 const char *fname = BASEDIR "\\test_exclusive5.dat";
653 struct smb2_handle h, h1, h2;
655 status = torture_smb2_testdir(tree1, BASEDIR, &h);
656 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
659 smb2_util_unlink(tree1, fname);
661 tree1->session->transport->oplock.handler = torture_oplock_handler;
662 tree1->session->transport->oplock.private_data = tree1;
664 tree2->session->transport->oplock.handler = torture_oplock_handler;
665 tree2->session->transport->oplock.private_data = tree2;
670 ZERO_STRUCT(io.smb2);
671 io.generic.level = RAW_OPEN_SMB2;
672 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
673 io.smb2.in.alloc_size = 0;
674 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
675 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
676 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
677 io.smb2.in.create_options = 0;
678 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
679 io.smb2.in.security_flags = 0;
680 io.smb2.in.fname = fname;
682 torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
683 ZERO_STRUCT(break_info);
685 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
686 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
687 NTCREATEX_SHARE_ACCESS_WRITE|
688 NTCREATEX_SHARE_ACCESS_DELETE;
689 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
690 status = smb2_create(tree1, tctx, &(io.smb2));
691 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
692 h1 = io.smb2.out.file.handle;
693 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
695 ZERO_STRUCT(break_info);
697 torture_comment(tctx, "second open with attributes only and "
698 "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
701 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
702 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
703 SEC_FILE_WRITE_ATTRIBUTE |
705 io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
706 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
707 status = smb2_create(tree2, tctx, &(io.smb2));
708 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
709 h2 = io.smb2.out.file.handle;
710 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
711 torture_wait_for_oplock_break(tctx);
712 CHECK_VAL(break_info.count, 1);
713 CHECK_VAL(break_info.failures, 0);
715 smb2_util_close(tree1, h1);
716 smb2_util_close(tree2, h2);
717 smb2_util_close(tree1, h);
719 smb2_deltree(tree1, BASEDIR);
723 static bool test_smb2_oplock_exclusive6(struct torture_context *tctx,
724 struct smb2_tree *tree1,
725 struct smb2_tree *tree2)
727 const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
728 const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
732 union smb_setfileinfo sinfo;
733 struct smb2_close closeio;
734 struct smb2_handle h, h1;
736 status = torture_smb2_testdir(tree1, BASEDIR, &h);
737 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
740 smb2_util_unlink(tree1, fname1);
741 smb2_util_unlink(tree2, fname2);
743 tree1->session->transport->oplock.handler = torture_oplock_handler;
744 tree1->session->transport->oplock.private_data = tree1;
749 ZERO_STRUCT(io.smb2);
750 io.generic.level = RAW_OPEN_SMB2;
751 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
752 io.smb2.in.alloc_size = 0;
753 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
754 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
755 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
756 io.smb2.in.create_options = 0;
757 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
758 io.smb2.in.security_flags = 0;
759 io.smb2.in.fname = fname1;
761 torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
762 "oplock (share mode: none)\n");
763 ZERO_STRUCT(break_info);
764 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
765 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
767 status = smb2_create(tree1, tctx, &(io.smb2));
768 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
769 h1 = io.smb2.out.file.handle;
770 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
772 torture_comment(tctx, "rename with the parent directory handle open "
773 "for DELETE should not generate a break but get "
774 "a sharing violation\n");
776 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
777 sinfo.rename_information.in.file.handle = h1;
778 sinfo.rename_information.in.overwrite = true;
779 sinfo.rename_information.in.new_name = fname2;
780 status = smb2_setinfo_file(tree1, &sinfo);
782 torture_comment(tctx, "trying rename while parent handle open for delete.\n");
783 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
785 torture_wait_for_oplock_break(tctx);
786 CHECK_VAL(break_info.count, 0);
787 CHECK_VAL(break_info.failures, 0);
789 /* Close the parent directory handle. */
790 ZERO_STRUCT(closeio);
791 closeio.in.file.handle = h;
792 status = smb2_close(tree1, &closeio);
793 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
796 /* Re-open without DELETE access. */
798 io.smb2.in.oplock_level = 0;
799 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL & (~SEC_STD_DELETE);
800 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
801 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
802 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
803 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
804 io.smb2.in.fname = BASEDIR;
806 status = smb2_create(tree1, tctx, &(io.smb2));
807 torture_assert_ntstatus_ok(tctx, status, "Error opening the base directory");
809 torture_comment(tctx, "rename with the parent directory handle open "
810 "without DELETE should succeed without a break\n");
812 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
813 sinfo.rename_information.in.file.handle = h1;
814 sinfo.rename_information.in.overwrite = true;
815 sinfo.rename_information.in.new_name = fname2;
816 status = smb2_setinfo_file(tree1, &sinfo);
818 torture_comment(tctx, "trying rename while parent handle open without delete\n");
819 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
821 torture_wait_for_oplock_break(tctx);
822 CHECK_VAL(break_info.count, 0);
823 CHECK_VAL(break_info.failures, 0);
825 smb2_util_close(tree1, h1);
826 smb2_util_close(tree1, h);
828 smb2_deltree(tree1, BASEDIR);
832 static bool test_smb2_oplock_exclusive9(struct torture_context *tctx,
833 struct smb2_tree *tree1,
834 struct smb2_tree *tree2)
836 const char *fname = BASEDIR "\\test_exclusive9.dat";
840 struct smb2_handle h1, h2;
844 uint32_t create_disposition;
845 uint32_t break_level;
847 { NTCREATEX_DISP_SUPERSEDE, SMB2_OPLOCK_LEVEL_NONE },
848 { NTCREATEX_DISP_OPEN, SMB2_OPLOCK_LEVEL_II },
849 { NTCREATEX_DISP_OVERWRITE_IF, SMB2_OPLOCK_LEVEL_NONE },
850 { NTCREATEX_DISP_OPEN_IF, SMB2_OPLOCK_LEVEL_II },
854 status = torture_smb2_testdir(tree1, BASEDIR, &h1);
855 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
856 smb2_util_close(tree1, h1);
859 smb2_util_unlink(tree1, fname);
861 tree1->session->transport->oplock.handler = torture_oplock_handler;
862 tree1->session->transport->oplock.private_data = tree1;
867 ZERO_STRUCT(io.smb2);
868 io.generic.level = RAW_OPEN_SMB2;
869 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
870 io.smb2.in.alloc_size = 0;
871 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
872 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
873 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
874 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
875 io.smb2.in.create_options = 0;
876 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
877 io.smb2.in.security_flags = 0;
878 io.smb2.in.fname = fname;
880 for (i=0; i<ARRAY_SIZE(levels); i++) {
882 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
883 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
885 status = smb2_create(tree1, tctx, &(io.smb2));
886 torture_assert_ntstatus_ok(tctx, status,
887 "Error opening the file");
888 h1 = io.smb2.out.file.handle;
889 CHECK_VAL(io.smb2.out.oplock_level,
890 SMB2_OPLOCK_LEVEL_EXCLUSIVE);
892 ZERO_STRUCT(break_info);
894 io.smb2.in.create_disposition = levels[i].create_disposition;
895 status = smb2_create(tree2, tctx, &(io.smb2));
896 torture_assert_ntstatus_ok(tctx, status,
897 "Error opening the file");
898 h2 = io.smb2.out.file.handle;
899 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
901 CHECK_VAL(break_info.count, 1);
902 CHECK_VAL(break_info.level, levels[i].break_level);
903 CHECK_VAL(break_info.failures, 0);
905 smb2_util_close(tree2, h2);
906 smb2_util_close(tree1, h1);
909 smb2_deltree(tree1, BASEDIR);
913 static bool test_smb2_oplock_batch1(struct torture_context *tctx,
914 struct smb2_tree *tree1,
915 struct smb2_tree *tree2)
917 const char *fname = BASEDIR "\\test_batch1.dat";
921 struct smb2_handle h, h1;
924 status = torture_smb2_testdir(tree1, BASEDIR, &h);
925 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
928 smb2_util_unlink(tree1, fname);
930 tree1->session->transport->oplock.handler = torture_oplock_handler;
931 tree1->session->transport->oplock.private_data = tree1;
936 ZERO_STRUCT(io.smb2);
937 io.generic.level = RAW_OPEN_SMB2;
938 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
939 io.smb2.in.alloc_size = 0;
940 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
941 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
942 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
943 io.smb2.in.create_options = 0;
944 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
945 io.smb2.in.security_flags = 0;
946 io.smb2.in.fname = fname;
949 with a batch oplock we get a break
951 torture_comment(tctx, "BATCH1: open with batch oplock\n");
952 ZERO_STRUCT(break_info);
953 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
954 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
955 status = smb2_create(tree1, tctx, &(io.smb2));
956 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
957 h1 = io.smb2.out.file.handle;
958 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
960 torture_comment(tctx, "unlink should generate a break\n");
961 status = smb2_util_unlink(tree2, fname);
962 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
965 torture_wait_for_oplock_break(tctx);
966 CHECK_VAL(break_info.count, 1);
967 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
968 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
969 CHECK_VAL(break_info.failures, 0);
971 torture_comment(tctx, "2nd unlink should not generate a break\n");
972 ZERO_STRUCT(break_info);
973 status = smb2_util_unlink(tree2, fname);
974 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
977 torture_wait_for_oplock_break(tctx);
978 CHECK_VAL(break_info.count, 0);
980 torture_comment(tctx, "writing should generate a self break to none\n");
981 tree1->session->transport->oplock.handler =
982 torture_oplock_handler_level2_to_none;
983 smb2_util_write(tree1, h1, &c, 0, 1);
985 torture_wait_for_oplock_break(tctx);
987 CHECK_VAL(break_info.count, 1);
988 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
989 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
990 CHECK_VAL(break_info.failures, 0);
992 smb2_util_close(tree1, h1);
993 smb2_util_close(tree1, h);
995 smb2_deltree(tree1, BASEDIR);
999 static bool test_smb2_oplock_batch2(struct torture_context *tctx,
1000 struct smb2_tree *tree1,
1001 struct smb2_tree *tree2)
1003 const char *fname = BASEDIR "\\test_batch2.dat";
1008 struct smb2_handle h, h1;
1010 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1011 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1014 smb2_util_unlink(tree1, fname);
1016 tree1->session->transport->oplock.handler = torture_oplock_handler;
1017 tree1->session->transport->oplock.private_data = tree1;
1020 base ntcreatex parms
1022 ZERO_STRUCT(io.smb2);
1023 io.generic.level = RAW_OPEN_SMB2;
1024 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1025 io.smb2.in.alloc_size = 0;
1026 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1027 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1028 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1029 io.smb2.in.create_options = 0;
1030 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1031 io.smb2.in.security_flags = 0;
1032 io.smb2.in.fname = fname;
1034 torture_comment(tctx, "BATCH2: open with batch oplock\n");
1035 ZERO_STRUCT(break_info);
1036 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1037 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1038 status = smb2_create(tree1, tctx, &(io.smb2));
1039 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1040 h1 = io.smb2.out.file.handle;
1041 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1043 torture_comment(tctx, "unlink should generate a break, which we ack "
1044 "as break to none\n");
1045 tree1->session->transport->oplock.handler =
1046 torture_oplock_handler_ack_to_none;
1047 tree1->session->transport->oplock.private_data = tree1;
1048 status = smb2_util_unlink(tree2, fname);
1049 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
1050 "Incorrect status");
1052 torture_wait_for_oplock_break(tctx);
1053 CHECK_VAL(break_info.count, 1);
1054 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1055 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
1056 CHECK_VAL(break_info.failures, 0);
1058 torture_comment(tctx, "2nd unlink should not generate a break\n");
1059 ZERO_STRUCT(break_info);
1060 status = smb2_util_unlink(tree2, fname);
1061 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
1062 "Incorrect status");
1064 torture_wait_for_oplock_break(tctx);
1065 CHECK_VAL(break_info.count, 0);
1067 torture_comment(tctx, "writing should not generate a break\n");
1068 smb2_util_write(tree1, h1, &c, 0, 1);
1070 torture_wait_for_oplock_break(tctx);
1071 CHECK_VAL(break_info.count, 0);
1073 smb2_util_close(tree1, h1);
1074 smb2_util_close(tree1, h);
1076 smb2_deltree(tree1, BASEDIR);
1080 static bool test_smb2_oplock_batch3(struct torture_context *tctx,
1081 struct smb2_tree *tree1,
1082 struct smb2_tree *tree2)
1084 const char *fname = BASEDIR "\\test_batch3.dat";
1088 struct smb2_handle h, h1;
1090 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1091 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1094 smb2_util_unlink(tree1, fname);
1095 tree1->session->transport->oplock.handler = torture_oplock_handler;
1096 tree1->session->transport->oplock.private_data = tree1;
1099 base ntcreatex parms
1101 ZERO_STRUCT(io.smb2);
1102 io.generic.level = RAW_OPEN_SMB2;
1103 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1104 io.smb2.in.alloc_size = 0;
1105 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1106 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1107 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1108 io.smb2.in.create_options = 0;
1109 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1110 io.smb2.in.security_flags = 0;
1111 io.smb2.in.fname = fname;
1113 torture_comment(tctx, "BATCH3: if we close on break then the unlink "
1115 ZERO_STRUCT(break_info);
1116 tree1->session->transport->oplock.handler =
1117 torture_oplock_handler_close;
1118 tree1->session->transport->oplock.private_data = tree1;
1120 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1121 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1122 status = smb2_create(tree1, tctx, &(io.smb2));
1123 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1124 h1 = io.smb2.out.file.handle;
1125 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1127 ZERO_STRUCT(break_info);
1128 status = smb2_util_unlink(tree2, fname);
1129 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1131 torture_wait_for_oplock_break(tctx);
1132 CHECK_VAL(break_info.count, 1);
1133 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1134 CHECK_VAL(break_info.level, 1);
1135 CHECK_VAL(break_info.failures, 0);
1137 smb2_util_close(tree1, h1);
1138 smb2_util_close(tree1, h);
1140 smb2_deltree(tree1, BASEDIR);
1144 static bool test_smb2_oplock_batch4(struct torture_context *tctx,
1145 struct smb2_tree *tree1,
1146 struct smb2_tree *tree2)
1148 const char *fname = BASEDIR "\\test_batch4.dat";
1153 struct smb2_handle h, h1;
1155 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1156 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1159 smb2_util_unlink(tree1, fname);
1161 tree1->session->transport->oplock.handler = torture_oplock_handler;
1162 tree1->session->transport->oplock.private_data = tree1;
1165 base ntcreatex parms
1167 ZERO_STRUCT(io.smb2);
1168 io.generic.level = RAW_OPEN_SMB2;
1169 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1170 io.smb2.in.alloc_size = 0;
1171 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1172 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1173 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1174 io.smb2.in.create_options = 0;
1175 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1176 io.smb2.in.security_flags = 0;
1177 io.smb2.in.fname = fname;
1179 torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
1180 ZERO_STRUCT(break_info);
1182 tree1->session->transport->oplock.handler = torture_oplock_handler;
1183 tree1->session->transport->oplock.private_data = tree1;
1185 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1186 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1187 status = smb2_create(tree1, tctx, &(io.smb2));
1188 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1189 h1 = io.smb2.out.file.handle;
1190 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1193 r.in.file.handle = h1;
1196 status = smb2_read(tree1, tree1, &r);
1197 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1198 torture_wait_for_oplock_break(tctx);
1199 CHECK_VAL(break_info.count, 0);
1200 CHECK_VAL(break_info.failures, 0);
1202 smb2_util_close(tree1, h1);
1203 smb2_util_close(tree1, h);
1205 smb2_deltree(tree1, BASEDIR);
1209 static bool test_smb2_oplock_batch5(struct torture_context *tctx,
1210 struct smb2_tree *tree1,
1211 struct smb2_tree *tree2)
1213 const char *fname = BASEDIR "\\test_batch5.dat";
1217 struct smb2_handle h, h1;
1219 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1220 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1223 smb2_util_unlink(tree1, fname);
1225 tree1->session->transport->oplock.handler = torture_oplock_handler;
1226 tree1->session->transport->oplock.private_data = tree1;
1229 base ntcreatex parms
1231 ZERO_STRUCT(io.smb2);
1232 io.generic.level = RAW_OPEN_SMB2;
1233 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1234 io.smb2.in.alloc_size = 0;
1235 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1236 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1237 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1238 io.smb2.in.create_options = 0;
1239 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1240 io.smb2.in.security_flags = 0;
1241 io.smb2.in.fname = fname;
1243 torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1244 ZERO_STRUCT(break_info);
1246 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1247 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1248 status = smb2_create(tree1, tctx, &(io.smb2));
1249 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1250 h1 = io.smb2.out.file.handle;
1251 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1253 ZERO_STRUCT(break_info);
1255 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1256 status = smb2_create(tree2, tctx, &(io.smb2));
1257 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
1258 "Incorrect status");
1260 torture_wait_for_oplock_break(tctx);
1261 CHECK_VAL(break_info.count, 1);
1262 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1263 CHECK_VAL(break_info.level, 1);
1264 CHECK_VAL(break_info.failures, 0);
1266 smb2_util_close(tree1, h1);
1267 smb2_util_close(tree1, h);
1269 smb2_deltree(tree1, BASEDIR);
1273 static bool test_smb2_oplock_batch6(struct torture_context *tctx,
1274 struct smb2_tree *tree1,
1275 struct smb2_tree *tree2)
1277 const char *fname = BASEDIR "\\test_batch6.dat";
1281 struct smb2_handle h, h1, h2;
1284 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1285 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1288 smb2_util_unlink(tree1, fname);
1290 tree1->session->transport->oplock.handler = torture_oplock_handler;
1291 tree1->session->transport->oplock.private_data = tree1;
1294 base ntcreatex parms
1296 ZERO_STRUCT(io.smb2);
1297 io.generic.level = RAW_OPEN_SMB2;
1298 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1299 io.smb2.in.alloc_size = 0;
1300 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1301 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1302 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1303 io.smb2.in.create_options = 0;
1304 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1305 io.smb2.in.security_flags = 0;
1306 io.smb2.in.fname = fname;
1308 torture_comment(tctx, "BATCH6: a 2nd open should give a break to "
1309 "level II if the first open allowed shared read\n");
1310 ZERO_STRUCT(break_info);
1311 tree2->session->transport->oplock.handler = torture_oplock_handler;
1312 tree2->session->transport->oplock.private_data = tree2;
1314 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
1315 SEC_RIGHTS_FILE_WRITE;
1316 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1317 NTCREATEX_SHARE_ACCESS_WRITE;
1318 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1319 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1320 status = smb2_create(tree1, tctx, &(io.smb2));
1321 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1322 h1 = io.smb2.out.file.handle;
1323 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1325 ZERO_STRUCT(break_info);
1327 status = smb2_create(tree2, tctx, &(io.smb2));
1328 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1329 h2 = io.smb2.out.file.handle;
1330 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1332 torture_wait_for_oplock_break(tctx);
1333 CHECK_VAL(break_info.count, 1);
1334 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1335 CHECK_VAL(break_info.level, 1);
1336 CHECK_VAL(break_info.failures, 0);
1337 ZERO_STRUCT(break_info);
1339 torture_comment(tctx, "write should trigger a break to none on both\n");
1340 tree1->session->transport->oplock.handler =
1341 torture_oplock_handler_level2_to_none;
1342 tree2->session->transport->oplock.handler =
1343 torture_oplock_handler_level2_to_none;
1344 smb2_util_write(tree1, h1, &c, 0, 1);
1346 /* We expect two breaks */
1347 torture_wait_for_oplock_break(tctx);
1348 torture_wait_for_oplock_break(tctx);
1350 CHECK_VAL(break_info.count, 2);
1351 CHECK_VAL(break_info.level, 0);
1352 CHECK_VAL(break_info.failures, 0);
1354 smb2_util_close(tree1, h1);
1355 smb2_util_close(tree2, h2);
1356 smb2_util_close(tree1, h);
1358 smb2_deltree(tree1, BASEDIR);
1362 static bool test_smb2_oplock_batch7(struct torture_context *tctx,
1363 struct smb2_tree *tree1,
1364 struct smb2_tree *tree2)
1366 const char *fname = BASEDIR "\\test_batch7.dat";
1370 struct smb2_handle h, h1, h2;
1372 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1373 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1376 smb2_util_unlink(tree1, fname);
1378 tree1->session->transport->oplock.handler = torture_oplock_handler;
1379 tree1->session->transport->oplock.private_data = tree1;
1382 base ntcreatex parms
1384 ZERO_STRUCT(io.smb2);
1385 io.generic.level = RAW_OPEN_SMB2;
1386 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1387 io.smb2.in.alloc_size = 0;
1388 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1389 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1390 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1391 io.smb2.in.create_options = 0;
1392 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1393 io.smb2.in.security_flags = 0;
1394 io.smb2.in.fname = fname;
1396 torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when "
1397 "we close instead of ack\n");
1398 ZERO_STRUCT(break_info);
1399 tree1->session->transport->oplock.handler =
1400 torture_oplock_handler_close;
1401 tree1->session->transport->oplock.private_data = tree1;
1403 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1404 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1405 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1406 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1407 status = smb2_create(tree1, tctx, &(io.smb2));
1408 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1409 h2 = io.smb2.out.file.handle;
1410 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1412 ZERO_STRUCT(break_info);
1414 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1415 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1416 status = smb2_create(tree2, tctx, &(io.smb2));
1417 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1418 h1 = io.smb2.out.file.handle;
1419 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1421 torture_wait_for_oplock_break(tctx);
1422 CHECK_VAL(break_info.count, 1);
1423 CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1424 CHECK_VAL(break_info.level, 1);
1425 CHECK_VAL(break_info.failures, 0);
1427 smb2_util_close(tree2, h1);
1428 smb2_util_close(tree2, h);
1430 smb2_deltree(tree1, BASEDIR);
1434 static bool test_smb2_oplock_batch8(struct torture_context *tctx,
1435 struct smb2_tree *tree1,
1436 struct smb2_tree *tree2)
1438 const char *fname = BASEDIR "\\test_batch8.dat";
1442 struct smb2_handle h, h1, h2;
1444 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1445 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1448 smb2_util_unlink(tree1, fname);
1450 tree1->session->transport->oplock.handler = torture_oplock_handler;
1451 tree1->session->transport->oplock.private_data = tree1;
1454 base ntcreatex parms
1456 ZERO_STRUCT(io.smb2);
1457 io.generic.level = RAW_OPEN_SMB2;
1458 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1459 io.smb2.in.alloc_size = 0;
1460 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1461 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1462 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1463 io.smb2.in.create_options = 0;
1464 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1465 io.smb2.in.security_flags = 0;
1466 io.smb2.in.fname = fname;
1468 torture_comment(tctx, "BATCH8: open with batch oplock\n");
1469 ZERO_STRUCT(break_info);
1471 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1472 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1473 status = smb2_create(tree1, tctx, &(io.smb2));
1474 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1475 h1 = io.smb2.out.file.handle;
1476 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1478 ZERO_STRUCT(break_info);
1479 torture_comment(tctx, "second open with attributes only shouldn't "
1480 "cause oplock break\n");
1482 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1483 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1484 SEC_FILE_WRITE_ATTRIBUTE |
1485 SEC_STD_SYNCHRONIZE;
1486 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1487 status = smb2_create(tree2, tctx, &(io.smb2));
1488 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1489 h2 = io.smb2.out.file.handle;
1490 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1491 torture_wait_for_oplock_break(tctx);
1492 CHECK_VAL(break_info.count, 0);
1493 CHECK_VAL(break_info.failures, 0);
1495 smb2_util_close(tree1, h1);
1496 smb2_util_close(tree2, h2);
1497 smb2_util_close(tree1, h);
1499 smb2_deltree(tree1, BASEDIR);
1503 static bool test_smb2_oplock_batch9(struct torture_context *tctx,
1504 struct smb2_tree *tree1,
1505 struct smb2_tree *tree2)
1507 const char *fname = BASEDIR "\\test_batch9.dat";
1511 struct smb2_handle h, h1, h2;
1514 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1515 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1518 smb2_util_unlink(tree1, fname);
1520 tree1->session->transport->oplock.handler = torture_oplock_handler;
1521 tree1->session->transport->oplock.private_data = tree1;
1524 base ntcreatex parms
1526 ZERO_STRUCT(io.smb2);
1527 io.generic.level = RAW_OPEN_SMB2;
1528 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1529 io.smb2.in.alloc_size = 0;
1530 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1531 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1532 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1533 io.smb2.in.create_options = 0;
1534 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1535 io.smb2.in.security_flags = 0;
1536 io.smb2.in.fname = fname;
1538 torture_comment(tctx, "BATCH9: open with attributes only can create "
1541 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1542 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1543 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1544 SEC_FILE_WRITE_ATTRIBUTE |
1545 SEC_STD_SYNCHRONIZE;
1546 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1547 status = smb2_create(tree1, tctx, &(io.smb2));
1548 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1549 h1 = io.smb2.out.file.handle;
1550 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1552 torture_comment(tctx, "Subsequent normal open should break oplock on "
1553 "attribute only open to level II\n");
1555 ZERO_STRUCT(break_info);
1557 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1558 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1559 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1560 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1561 status = smb2_create(tree2, tctx, &(io.smb2));
1562 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1563 h2 = io.smb2.out.file.handle;
1564 torture_wait_for_oplock_break(tctx);
1565 CHECK_VAL(break_info.count, 1);
1566 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1567 CHECK_VAL(break_info.failures, 0);
1568 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
1569 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1570 smb2_util_close(tree2, h2);
1572 torture_comment(tctx, "third oplocked open should grant level2 without "
1574 ZERO_STRUCT(break_info);
1576 tree2->session->transport->oplock.handler = torture_oplock_handler;
1577 tree2->session->transport->oplock.private_data = tree2;
1579 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1580 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1581 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1582 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1583 status = smb2_create(tree2, tctx, &(io.smb2));
1584 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1585 h2 = io.smb2.out.file.handle;
1586 torture_wait_for_oplock_break(tctx);
1587 CHECK_VAL(break_info.count, 0);
1588 CHECK_VAL(break_info.failures, 0);
1589 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1591 ZERO_STRUCT(break_info);
1593 torture_comment(tctx, "write should trigger a break to none on both\n");
1594 tree1->session->transport->oplock.handler =
1595 torture_oplock_handler_level2_to_none;
1596 tree2->session->transport->oplock.handler =
1597 torture_oplock_handler_level2_to_none;
1598 smb2_util_write(tree2, h2, &c, 0, 1);
1600 /* We expect two breaks */
1601 torture_wait_for_oplock_break(tctx);
1602 torture_wait_for_oplock_break(tctx);
1604 CHECK_VAL(break_info.count, 2);
1605 CHECK_VAL(break_info.level, 0);
1606 CHECK_VAL(break_info.failures, 0);
1608 smb2_util_close(tree1, h1);
1609 smb2_util_close(tree2, h2);
1610 smb2_util_close(tree1, h);
1612 smb2_deltree(tree1, BASEDIR);
1616 static bool test_smb2_oplock_batch9a(struct torture_context *tctx,
1617 struct smb2_tree *tree1,
1618 struct smb2_tree *tree2)
1620 const char *fname = BASEDIR "\\test_batch9a.dat";
1624 struct smb2_handle h, h1, h2, h3;
1627 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1628 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1631 smb2_util_unlink(tree1, fname);
1633 tree1->session->transport->oplock.handler = torture_oplock_handler;
1634 tree1->session->transport->oplock.private_data = tree1;
1637 base ntcreatex parms
1639 ZERO_STRUCT(io.smb2);
1640 io.generic.level = RAW_OPEN_SMB2;
1641 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1642 io.smb2.in.alloc_size = 0;
1643 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1644 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1645 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1646 io.smb2.in.create_options = 0;
1647 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1648 io.smb2.in.security_flags = 0;
1649 io.smb2.in.fname = fname;
1651 torture_comment(tctx, "BATCH9: open with attributes only can create "
1654 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1655 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1656 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1657 SEC_FILE_WRITE_ATTRIBUTE |
1658 SEC_STD_SYNCHRONIZE;
1659 status = smb2_create(tree1, tctx, &(io.smb2));
1660 torture_assert_ntstatus_ok(tctx, status, "Error creating the file");
1661 h1 = io.smb2.out.file.handle;
1662 CHECK_VAL(io.smb2.out.create_action, FILE_WAS_CREATED);
1663 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1665 torture_comment(tctx, "Subsequent attributes open should not break\n");
1667 ZERO_STRUCT(break_info);
1669 status = smb2_create(tree2, tctx, &(io.smb2));
1670 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1671 h3 = io.smb2.out.file.handle;
1672 torture_wait_for_oplock_break(tctx);
1673 CHECK_VAL(break_info.count, 0);
1674 CHECK_VAL(io.smb2.out.create_action, FILE_WAS_OPENED);
1675 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1676 smb2_util_close(tree2, h3);
1678 torture_comment(tctx, "Subsequent normal open should break oplock on "
1679 "attribute only open to level II\n");
1681 ZERO_STRUCT(break_info);
1683 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1684 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1685 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1686 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1687 status = smb2_create(tree2, tctx, &(io.smb2));
1688 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1689 h2 = io.smb2.out.file.handle;
1690 torture_wait_for_oplock_break(tctx);
1691 CHECK_VAL(break_info.count, 1);
1692 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1693 CHECK_VAL(break_info.failures, 0);
1694 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
1695 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1696 smb2_util_close(tree2, h2);
1698 torture_comment(tctx, "third oplocked open should grant level2 without "
1700 ZERO_STRUCT(break_info);
1702 tree2->session->transport->oplock.handler = torture_oplock_handler;
1703 tree2->session->transport->oplock.private_data = tree2;
1705 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1706 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1707 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1708 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1709 status = smb2_create(tree2, tctx, &(io.smb2));
1710 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1711 h2 = io.smb2.out.file.handle;
1712 torture_wait_for_oplock_break(tctx);
1713 CHECK_VAL(break_info.count, 0);
1714 CHECK_VAL(break_info.failures, 0);
1715 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1717 ZERO_STRUCT(break_info);
1719 torture_comment(tctx, "write should trigger a break to none on both\n");
1720 tree1->session->transport->oplock.handler =
1721 torture_oplock_handler_level2_to_none;
1722 tree2->session->transport->oplock.handler =
1723 torture_oplock_handler_level2_to_none;
1724 smb2_util_write(tree2, h2, &c, 0, 1);
1726 /* We expect two breaks */
1727 torture_wait_for_oplock_break(tctx);
1728 torture_wait_for_oplock_break(tctx);
1730 CHECK_VAL(break_info.count, 2);
1731 CHECK_VAL(break_info.level, 0);
1732 CHECK_VAL(break_info.failures, 0);
1734 smb2_util_close(tree1, h1);
1735 smb2_util_close(tree2, h2);
1736 smb2_util_close(tree1, h);
1738 smb2_deltree(tree1, BASEDIR);
1743 static bool test_smb2_oplock_batch10(struct torture_context *tctx,
1744 struct smb2_tree *tree1,
1745 struct smb2_tree *tree2)
1747 const char *fname = BASEDIR "\\test_batch10.dat";
1751 struct smb2_handle h, h1, h2;
1753 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1754 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1757 smb2_util_unlink(tree1, fname);
1759 tree1->session->transport->oplock.handler = torture_oplock_handler;
1760 tree1->session->transport->oplock.private_data = tree1;
1763 base ntcreatex parms
1765 ZERO_STRUCT(io.smb2);
1766 io.generic.level = RAW_OPEN_SMB2;
1767 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1768 io.smb2.in.alloc_size = 0;
1769 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1770 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1771 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1772 io.smb2.in.create_options = 0;
1773 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1774 io.smb2.in.security_flags = 0;
1775 io.smb2.in.fname = fname;
1777 torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock "
1778 "open should grant level2\n");
1779 ZERO_STRUCT(break_info);
1780 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1781 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1782 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1783 NTCREATEX_SHARE_ACCESS_WRITE|
1784 NTCREATEX_SHARE_ACCESS_DELETE;
1785 status = smb2_create(tree1, tctx, &(io.smb2));
1786 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1787 h1 = io.smb2.out.file.handle;
1788 torture_wait_for_oplock_break(tctx);
1789 CHECK_VAL(break_info.count, 0);
1790 CHECK_VAL(break_info.failures, 0);
1791 CHECK_VAL(io.smb2.out.oplock_level, 0);
1793 tree2->session->transport->oplock.handler =
1794 torture_oplock_handler_level2_to_none;
1795 tree2->session->transport->oplock.private_data = tree2;
1797 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1798 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1799 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1800 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1801 NTCREATEX_SHARE_ACCESS_WRITE|
1802 NTCREATEX_SHARE_ACCESS_DELETE;
1803 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1804 status = smb2_create(tree2, tctx, &(io.smb2));
1805 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1806 h2 = io.smb2.out.file.handle;
1807 torture_wait_for_oplock_break(tctx);
1808 CHECK_VAL(break_info.count, 0);
1809 CHECK_VAL(break_info.failures, 0);
1810 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1812 torture_comment(tctx, "write should trigger a break to none\n");
1814 struct smb2_write wr;
1816 data = data_blob_talloc_zero(tree1, UINT16_MAX);
1817 data.data[0] = (const uint8_t)'x';
1819 wr.in.file.handle = h1;
1822 status = smb2_write(tree1, &wr);
1823 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1826 torture_wait_for_oplock_break(tctx);
1828 CHECK_VAL(break_info.count, 1);
1829 CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1830 CHECK_VAL(break_info.level, 0);
1831 CHECK_VAL(break_info.failures, 0);
1833 smb2_util_close(tree1, h1);
1834 smb2_util_close(tree2, h2);
1835 smb2_util_close(tree1, h);
1837 smb2_deltree(tree1, BASEDIR);
1841 static bool test_smb2_oplock_batch11(struct torture_context *tctx,
1842 struct smb2_tree *tree1,
1843 struct smb2_tree *tree2)
1845 const char *fname = BASEDIR "\\test_batch11.dat";
1849 union smb_setfileinfo sfi;
1850 struct smb2_handle h, h1;
1852 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1853 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1856 smb2_util_unlink(tree1, fname);
1858 tree1->session->transport->oplock.handler =
1859 torture_oplock_handler_two_notifications;
1860 tree1->session->transport->oplock.private_data = tree1;
1863 base ntcreatex parms
1865 ZERO_STRUCT(io.smb2);
1866 io.generic.level = RAW_OPEN_SMB2;
1867 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1868 io.smb2.in.alloc_size = 0;
1869 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1870 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1871 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1872 io.smb2.in.create_options = 0;
1873 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1874 io.smb2.in.security_flags = 0;
1875 io.smb2.in.fname = fname;
1877 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1878 torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks "
1881 ZERO_STRUCT(break_info);
1883 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1884 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1885 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1886 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1887 NTCREATEX_SHARE_ACCESS_WRITE|
1888 NTCREATEX_SHARE_ACCESS_DELETE;
1889 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1890 status = smb2_create(tree1, tctx, &(io.smb2));
1891 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1892 h1 = io.smb2.out.file.handle;
1893 torture_wait_for_oplock_break(tctx);
1894 CHECK_VAL(break_info.count, 0);
1895 CHECK_VAL(break_info.failures, 0);
1896 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1899 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1900 sfi.generic.in.file.path = fname;
1901 sfi.end_of_file_info.in.size = 100;
1903 status = smb2_composite_setpathinfo(tree2, &sfi);
1904 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1906 /* We expect two breaks */
1907 torture_wait_for_oplock_break(tctx);
1908 torture_wait_for_oplock_break(tctx);
1910 CHECK_VAL(break_info.count, 2);
1911 CHECK_VAL(break_info.failures, 0);
1912 CHECK_VAL(break_info.level, 0);
1914 smb2_util_close(tree1, h1);
1915 smb2_util_close(tree1, h);
1917 smb2_deltree(tree1, BASEDIR);
1921 static bool test_smb2_oplock_batch12(struct torture_context *tctx,
1922 struct smb2_tree *tree1,
1923 struct smb2_tree *tree2)
1925 const char *fname = BASEDIR "\\test_batch12.dat";
1929 union smb_setfileinfo sfi;
1930 struct smb2_handle h, h1;
1932 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1933 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1936 smb2_util_unlink(tree1, fname);
1938 tree1->session->transport->oplock.handler =
1939 torture_oplock_handler_two_notifications;
1940 tree1->session->transport->oplock.private_data = tree1;
1943 base ntcreatex parms
1945 ZERO_STRUCT(io.smb2);
1946 io.generic.level = RAW_OPEN_SMB2;
1947 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1948 io.smb2.in.alloc_size = 0;
1949 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1950 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1951 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1952 io.smb2.in.create_options = 0;
1953 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1954 io.smb2.in.security_flags = 0;
1955 io.smb2.in.fname = fname;
1957 /* Test if a set-allocation size on pathname breaks an exclusive
1959 torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size "
1960 "breaks oplocks.\n");
1962 ZERO_STRUCT(break_info);
1964 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1965 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1966 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1967 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1968 NTCREATEX_SHARE_ACCESS_WRITE|
1969 NTCREATEX_SHARE_ACCESS_DELETE;
1970 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1971 status = smb2_create(tree1, tctx, &(io.smb2));
1972 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1973 h1 = io.smb2.out.file.handle;
1974 torture_wait_for_oplock_break(tctx);
1975 CHECK_VAL(break_info.count, 0);
1976 CHECK_VAL(break_info.failures, 0);
1977 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1980 sfi.generic.level = RAW_SFILEINFO_ALLOCATION_INFORMATION;
1981 sfi.generic.in.file.path = fname;
1982 sfi.allocation_info.in.alloc_size = 65536 * 8;
1984 status = smb2_composite_setpathinfo(tree2, &sfi);
1985 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1987 /* We expect two breaks */
1988 torture_wait_for_oplock_break(tctx);
1989 torture_wait_for_oplock_break(tctx);
1991 CHECK_VAL(break_info.count, 2);
1992 CHECK_VAL(break_info.failures, 0);
1993 CHECK_VAL(break_info.level, 0);
1995 smb2_util_close(tree1, h1);
1996 smb2_util_close(tree1, h);
1998 smb2_deltree(tree1, BASEDIR);
2002 static bool test_smb2_oplock_batch13(struct torture_context *tctx,
2003 struct smb2_tree *tree1,
2004 struct smb2_tree *tree2)
2006 const char *fname = BASEDIR "\\test_batch13.dat";
2010 struct smb2_handle h, h1, h2;
2012 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2013 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2016 smb2_util_unlink(tree1, fname);
2018 tree1->session->transport->oplock.handler = torture_oplock_handler;
2019 tree1->session->transport->oplock.private_data = tree1;
2021 tree2->session->transport->oplock.handler = torture_oplock_handler;
2022 tree2->session->transport->oplock.private_data = tree2;
2025 base ntcreatex parms
2027 ZERO_STRUCT(io.smb2);
2028 io.generic.level = RAW_OPEN_SMB2;
2029 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2030 io.smb2.in.alloc_size = 0;
2031 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2032 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2033 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2034 io.smb2.in.create_options = 0;
2035 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2036 io.smb2.in.security_flags = 0;
2037 io.smb2.in.fname = fname;
2039 torture_comment(tctx, "BATCH13: open with batch oplock\n");
2040 ZERO_STRUCT(break_info);
2042 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2043 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2044 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2045 NTCREATEX_SHARE_ACCESS_WRITE|
2046 NTCREATEX_SHARE_ACCESS_DELETE;
2047 status = smb2_create(tree1, tctx, &(io.smb2));
2048 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2049 h1 = io.smb2.out.file.handle;
2050 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2052 ZERO_STRUCT(break_info);
2054 torture_comment(tctx, "second open with attributes only and "
2055 "NTCREATEX_DISP_OVERWRITE dispostion causes "
2058 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2059 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2060 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2061 SEC_FILE_WRITE_ATTRIBUTE |
2062 SEC_STD_SYNCHRONIZE;
2063 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2064 NTCREATEX_SHARE_ACCESS_WRITE|
2065 NTCREATEX_SHARE_ACCESS_DELETE;
2066 io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2067 status = smb2_create(tree2, tctx, &(io.smb2));
2068 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2069 h2 = io.smb2.out.file.handle;
2070 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2071 torture_wait_for_oplock_break(tctx);
2072 CHECK_VAL(break_info.count, 1);
2073 CHECK_VAL(break_info.failures, 0);
2075 smb2_util_close(tree1, h1);
2076 smb2_util_close(tree2, h2);
2077 smb2_util_close(tree1, h);
2079 smb2_deltree(tree1, BASEDIR);
2084 static bool test_smb2_oplock_batch14(struct torture_context *tctx,
2085 struct smb2_tree *tree1,
2086 struct smb2_tree *tree2)
2088 const char *fname = BASEDIR "\\test_batch14.dat";
2092 struct smb2_handle h, h1, h2;
2094 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2095 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2098 smb2_util_unlink(tree1, fname);
2100 tree1->session->transport->oplock.handler = torture_oplock_handler;
2101 tree1->session->transport->oplock.private_data = tree1;
2104 base ntcreatex parms
2106 ZERO_STRUCT(io.smb2);
2107 io.generic.level = RAW_OPEN_SMB2;
2108 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2109 io.smb2.in.alloc_size = 0;
2110 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2111 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2112 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2113 io.smb2.in.create_options = 0;
2114 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2115 io.smb2.in.security_flags = 0;
2116 io.smb2.in.fname = fname;
2118 torture_comment(tctx, "BATCH14: open with batch oplock\n");
2119 ZERO_STRUCT(break_info);
2121 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2122 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2123 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2124 NTCREATEX_SHARE_ACCESS_WRITE|
2125 NTCREATEX_SHARE_ACCESS_DELETE;
2126 status = smb2_create(tree1, tctx, &(io.smb2));
2127 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2128 h1 = io.smb2.out.file.handle;
2129 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2131 ZERO_STRUCT(break_info);
2133 torture_comment(tctx, "second open with attributes only and "
2134 "NTCREATEX_DISP_SUPERSEDE dispostion causes "
2137 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2138 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2139 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2140 SEC_FILE_WRITE_ATTRIBUTE |
2141 SEC_STD_SYNCHRONIZE;
2142 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2143 NTCREATEX_SHARE_ACCESS_WRITE|
2144 NTCREATEX_SHARE_ACCESS_DELETE;
2145 io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2146 status = smb2_create(tree2, tctx, &(io.smb2));
2147 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2148 h2 = io.smb2.out.file.handle;
2149 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2151 torture_wait_for_oplock_break(tctx);
2152 CHECK_VAL(break_info.count, 1);
2153 CHECK_VAL(break_info.failures, 0);
2155 smb2_util_close(tree1, h1);
2156 smb2_util_close(tree2, h2);
2157 smb2_util_close(tree1, h);
2159 smb2_deltree(tree1, BASEDIR);
2163 static bool test_smb2_oplock_batch15(struct torture_context *tctx,
2164 struct smb2_tree *tree1,
2165 struct smb2_tree *tree2)
2167 const char *fname = BASEDIR "\\test_batch15.dat";
2171 union smb_fileinfo qfi;
2172 struct smb2_handle h, h1;
2174 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2175 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2178 smb2_util_unlink(tree1, fname);
2180 tree1->session->transport->oplock.handler = torture_oplock_handler;
2181 tree1->session->transport->oplock.private_data = tree1;
2184 base ntcreatex parms
2186 ZERO_STRUCT(io.smb2);
2187 io.generic.level = RAW_OPEN_SMB2;
2188 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2189 io.smb2.in.alloc_size = 0;
2190 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2191 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2192 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2193 io.smb2.in.create_options = 0;
2194 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2195 io.smb2.in.security_flags = 0;
2196 io.smb2.in.fname = fname;
2198 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
2199 torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks "
2200 "a batch oplock (should not).\n");
2202 ZERO_STRUCT(break_info);
2204 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2205 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2206 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2207 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2208 NTCREATEX_SHARE_ACCESS_WRITE|
2209 NTCREATEX_SHARE_ACCESS_DELETE;
2210 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2211 status = smb2_create(tree1, tctx, &(io.smb2));
2212 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2213 h1 = io.smb2.out.file.handle;
2215 torture_wait_for_oplock_break(tctx);
2216 CHECK_VAL(break_info.count, 0);
2217 CHECK_VAL(break_info.failures, 0);
2218 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2221 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2222 qfi.generic.in.file.handle = h1;
2223 status = smb2_getinfo_file(tree2, tctx, &qfi);
2225 torture_wait_for_oplock_break(tctx);
2226 CHECK_VAL(break_info.count, 0);
2228 smb2_util_close(tree1, h1);
2229 smb2_util_close(tree1, h);
2231 smb2_deltree(tree1, BASEDIR);
2235 static bool test_smb2_oplock_batch16(struct torture_context *tctx,
2236 struct smb2_tree *tree1,
2237 struct smb2_tree *tree2)
2239 const char *fname = BASEDIR "\\test_batch16.dat";
2243 struct smb2_handle h, h1, h2;
2245 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2246 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2249 smb2_util_unlink(tree1, fname);
2251 tree1->session->transport->oplock.handler = torture_oplock_handler;
2252 tree1->session->transport->oplock.private_data = tree1;
2254 tree2->session->transport->oplock.handler = torture_oplock_handler;
2255 tree2->session->transport->oplock.private_data = tree2;
2258 base ntcreatex parms
2260 ZERO_STRUCT(io.smb2);
2261 io.generic.level = RAW_OPEN_SMB2;
2262 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2263 io.smb2.in.alloc_size = 0;
2264 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2265 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2266 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2267 io.smb2.in.create_options = 0;
2268 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2269 io.smb2.in.security_flags = 0;
2270 io.smb2.in.fname = fname;
2272 torture_comment(tctx, "BATCH16: open with batch oplock\n");
2273 ZERO_STRUCT(break_info);
2275 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2276 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2277 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2278 NTCREATEX_SHARE_ACCESS_WRITE|
2279 NTCREATEX_SHARE_ACCESS_DELETE;
2280 status = smb2_create(tree1, tctx, &(io.smb2));
2281 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2282 h1 = io.smb2.out.file.handle;
2283 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2285 ZERO_STRUCT(break_info);
2287 torture_comment(tctx, "second open with attributes only and "
2288 "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
2291 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2292 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2293 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2294 SEC_FILE_WRITE_ATTRIBUTE |
2295 SEC_STD_SYNCHRONIZE;
2296 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2297 NTCREATEX_SHARE_ACCESS_WRITE|
2298 NTCREATEX_SHARE_ACCESS_DELETE;
2299 io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2300 status = smb2_create(tree2, tctx, &(io.smb2));
2301 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2302 h2 = io.smb2.out.file.handle;
2303 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2305 torture_wait_for_oplock_break(tctx);
2306 CHECK_VAL(break_info.count, 1);
2307 CHECK_VAL(break_info.failures, 0);
2309 smb2_util_close(tree1, h1);
2310 smb2_util_close(tree2, h2);
2311 smb2_util_close(tree1, h);
2313 smb2_deltree(tree1, BASEDIR);
2317 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH17 test. Since
2318 * SMB2 doesn't have a RENAME command this test isn't applicable. However,
2319 * it's much less confusing, when comparing test, to keep the SMB1 and SMB2
2320 * test numbers in sync. */
2322 static bool test_raw_oplock_batch17(struct torture_context *tctx,
2323 struct smb2_tree *tree1,
2324 struct smb2_tree *tree2)
2330 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH18 test. Since
2331 * SMB2 doesn't have an NTRENAME command this test isn't applicable. However,
2332 * it's much less confusing, when comparing tests, to keep the SMB1 and SMB2
2333 * test numbers in sync. */
2335 static bool test_raw_oplock_batch18(struct torture_context *tctx,
2336 struct smb2_tree *tree1,
2337 struct smb2_tree *tree2)
2343 static bool test_smb2_oplock_batch19(struct torture_context *tctx,
2344 struct smb2_tree *tree1)
2346 const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2347 const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2351 union smb_fileinfo qfi;
2352 union smb_setfileinfo sfi;
2353 struct smb2_handle h, h1;
2355 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2356 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2359 smb2_util_unlink(tree1, fname1);
2360 smb2_util_unlink(tree1, fname2);
2362 tree1->session->transport->oplock.handler = torture_oplock_handler;
2363 tree1->session->transport->oplock.private_data = tree1;
2366 base ntcreatex parms
2368 ZERO_STRUCT(io.smb2);
2369 io.generic.level = RAW_OPEN_SMB2;
2370 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2371 io.smb2.in.alloc_size = 0;
2372 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2373 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2374 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2375 io.smb2.in.create_options = 0;
2376 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2377 io.smb2.in.security_flags = 0;
2378 io.smb2.in.fname = fname1;
2380 torture_comment(tctx, "BATCH19: open a file with an batch oplock "
2381 "(share mode: none)\n");
2382 ZERO_STRUCT(break_info);
2383 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2384 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2385 status = smb2_create(tree1, tctx, &(io.smb2));
2386 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2387 h1 = io.smb2.out.file.handle;
2388 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2390 torture_comment(tctx, "setfileinfo rename info should not trigger "
2391 "a break but should cause a sharing violation\n");
2393 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2394 sfi.generic.in.file.path = fname1;
2395 sfi.rename_information.in.file.handle = h1;
2396 sfi.rename_information.in.overwrite = 0;
2397 sfi.rename_information.in.root_fid = 0;
2398 sfi.rename_information.in.new_name = fname2;
2400 status = smb2_setinfo_file(tree1, &sfi);
2402 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2403 "Incorrect status");
2405 torture_wait_for_oplock_break(tctx);
2406 CHECK_VAL(break_info.count, 0);
2409 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2410 qfi.generic.in.file.handle = h1;
2412 status = smb2_getinfo_file(tree1, tctx, &qfi);
2413 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2414 CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2416 smb2_util_close(tree1, h1);
2417 smb2_util_close(tree1, h);
2419 smb2_deltree(tree1, fname1);
2420 smb2_deltree(tree1, fname2);
2424 static bool test_smb2_oplock_batch20(struct torture_context *tctx,
2425 struct smb2_tree *tree1,
2426 struct smb2_tree *tree2)
2428 const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2429 const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2433 union smb_fileinfo qfi;
2434 union smb_setfileinfo sfi;
2435 struct smb2_handle h, h1, h2;
2437 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2438 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2441 smb2_util_unlink(tree1, fname1);
2442 smb2_util_unlink(tree1, fname2);
2444 tree1->session->transport->oplock.handler = torture_oplock_handler;
2445 tree1->session->transport->oplock.private_data = tree1;
2448 base ntcreatex parms
2450 ZERO_STRUCT(io.smb2);
2451 io.generic.level = RAW_OPEN_SMB2;
2452 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2453 io.smb2.in.alloc_size = 0;
2454 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2455 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2456 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2457 io.smb2.in.create_options = 0;
2458 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2459 io.smb2.in.security_flags = 0;
2460 io.smb2.in.fname = fname1;
2462 torture_comment(tctx, "BATCH20: open a file with an batch oplock "
2463 "(share mode: all)\n");
2464 ZERO_STRUCT(break_info);
2465 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2466 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2467 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2468 NTCREATEX_SHARE_ACCESS_WRITE|
2469 NTCREATEX_SHARE_ACCESS_DELETE;
2470 status = smb2_create(tree1, tctx, &(io.smb2));
2471 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2472 h1 = io.smb2.out.file.handle;
2473 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2475 torture_comment(tctx, "setfileinfo rename info should not trigger "
2476 "a break but should cause a sharing violation\n");
2478 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2479 sfi.rename_information.in.file.handle = h1;
2480 sfi.rename_information.in.overwrite = 0;
2481 sfi.rename_information.in.new_name = fname2;
2483 status = smb2_setinfo_file(tree1, &sfi);
2484 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2485 "Incorrect status");
2487 torture_wait_for_oplock_break(tctx);
2488 CHECK_VAL(break_info.count, 0);
2491 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2492 qfi.generic.in.file.handle = h1;
2494 status = smb2_getinfo_file(tree1, tctx, &qfi);
2495 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2496 CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2498 torture_comment(tctx, "open the file a second time requesting batch "
2499 "(share mode: all)\n");
2500 ZERO_STRUCT(break_info);
2501 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2502 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2503 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2504 NTCREATEX_SHARE_ACCESS_WRITE|
2505 NTCREATEX_SHARE_ACCESS_DELETE;
2506 io.smb2.in.fname = fname1;
2507 status = smb2_create(tree2, tctx, &(io.smb2));
2508 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2509 h2 = io.smb2.out.file.handle;
2510 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2512 torture_wait_for_oplock_break(tctx);
2513 CHECK_VAL(break_info.count, 1);
2514 CHECK_VAL(break_info.failures, 0);
2515 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2517 torture_comment(tctx, "setfileinfo rename info should not trigger "
2518 "a break but should cause a sharing violation\n");
2519 ZERO_STRUCT(break_info);
2521 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2522 sfi.rename_information.in.file.handle = h2;
2523 sfi.rename_information.in.overwrite = 0;
2524 sfi.rename_information.in.new_name = fname2;
2526 status = smb2_setinfo_file(tree2, &sfi);
2527 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2528 "Incorrect status");
2530 torture_wait_for_oplock_break(tctx);
2531 CHECK_VAL(break_info.count, 0);
2534 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2535 qfi.generic.in.file.handle = h1;
2537 status = smb2_getinfo_file(tree1, tctx, &qfi);
2538 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2539 CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2542 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2543 qfi.generic.in.file.handle = h2;
2545 status = smb2_getinfo_file(tree2, tctx, &qfi);
2546 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2547 CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2549 smb2_util_close(tree1, h1);
2550 smb2_util_close(tree2, h2);
2551 smb2_util_close(tree1, h);
2553 smb2_deltree(tree1, fname1);
2557 static bool test_smb2_oplock_batch21(struct torture_context *tctx,
2558 struct smb2_tree *tree1)
2560 const char *fname = BASEDIR "\\test_batch21.dat";
2564 struct smb2_handle h, h1;
2567 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2568 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2571 smb2_util_unlink(tree1, fname);
2573 tree1->session->transport->oplock.handler = torture_oplock_handler;
2574 tree1->session->transport->oplock.private_data = tree1;
2577 base ntcreatex parms
2579 ZERO_STRUCT(io.smb2);
2580 io.generic.level = RAW_OPEN_SMB2;
2581 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2582 io.smb2.in.alloc_size = 0;
2583 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2584 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2585 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2586 io.smb2.in.create_options = 0;
2587 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2588 io.smb2.in.security_flags = 0;
2589 io.smb2.in.fname = fname;
2592 with a batch oplock we get a break
2594 torture_comment(tctx, "BATCH21: open with batch oplock\n");
2595 ZERO_STRUCT(break_info);
2596 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2597 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2598 status = smb2_create(tree1, tctx, &(io.smb2));
2599 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2600 h1 = io.smb2.out.file.handle;
2601 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2603 torture_comment(tctx, "writing should not generate a break\n");
2604 status = smb2_util_write(tree1, h1, &c, 0, 1);
2605 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2607 torture_wait_for_oplock_break(tctx);
2608 CHECK_VAL(break_info.count, 0);
2610 smb2_util_close(tree1, h1);
2611 smb2_util_close(tree1, h);
2613 smb2_deltree(tree1, BASEDIR);
2617 static bool test_smb2_oplock_batch22(struct torture_context *tctx,
2618 struct smb2_tree *tree1)
2620 const char *fname = BASEDIR "\\test_batch22.dat";
2624 struct smb2_handle h, h1, h2;
2626 int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2629 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2630 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2633 smb2_util_unlink(tree1, fname);
2635 tree1->session->transport->oplock.handler = torture_oplock_handler;
2636 tree1->session->transport->oplock.private_data = tree1;
2638 base ntcreatex parms
2640 ZERO_STRUCT(io.smb2);
2641 io.generic.level = RAW_OPEN_SMB2;
2642 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2643 io.smb2.in.alloc_size = 0;
2644 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2645 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2646 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2647 io.smb2.in.create_options = 0;
2648 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2649 io.smb2.in.security_flags = 0;
2650 io.smb2.in.fname = fname;
2653 with a batch oplock we get a break
2655 torture_comment(tctx, "BATCH22: open with batch oplock\n");
2656 ZERO_STRUCT(break_info);
2657 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2658 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2659 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2660 NTCREATEX_SHARE_ACCESS_WRITE|
2661 NTCREATEX_SHARE_ACCESS_DELETE;
2662 status = smb2_create(tree1, tctx, &(io.smb2));
2663 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2664 h1 = io.smb2.out.file.handle;
2665 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2667 torture_comment(tctx, "a 2nd open should succeed after the oplock "
2669 tv = timeval_current();
2670 tree1->session->transport->oplock.handler =
2671 torture_oplock_handler_timeout;
2672 status = smb2_create(tree1, tctx, &(io.smb2));
2673 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2674 h2 = io.smb2.out.file.handle;
2675 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2677 torture_wait_for_oplock_break(tctx);
2678 te = (int)timeval_elapsed(&tv);
2679 CHECK_RANGE(te, timeout - 1, timeout + 15);
2680 torture_comment(tctx, "waited %d seconds for oplock timeout\n", te);
2682 CHECK_VAL(break_info.count, 1);
2683 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2684 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2685 CHECK_VAL(break_info.failures, 0);
2687 smb2_util_close(tree1, h1);
2688 smb2_util_close(tree1, h2);
2689 smb2_util_close(tree1, h);
2691 smb2_deltree(tree1, BASEDIR);
2695 static bool test_smb2_oplock_batch23(struct torture_context *tctx,
2696 struct smb2_tree *tree1,
2697 struct smb2_tree *tree2)
2699 const char *fname = BASEDIR "\\test_batch23.dat";
2703 struct smb2_handle h, h1, h2, h3;
2704 struct smb2_tree *tree3 = NULL;
2706 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2707 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2710 smb2_util_unlink(tree1, fname);
2712 ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2713 CHECK_VAL(ret, true);
2715 tree1->session->transport->oplock.handler = torture_oplock_handler;
2716 tree1->session->transport->oplock.private_data = tree1;
2718 tree2->session->transport->oplock.handler = torture_oplock_handler;
2719 tree2->session->transport->oplock.private_data = tree2;
2721 tree3->session->transport->oplock.handler = torture_oplock_handler;
2722 tree3->session->transport->oplock.private_data = tree3;
2725 base ntcreatex parms
2727 ZERO_STRUCT(io.smb2);
2728 io.generic.level = RAW_OPEN_SMB2;
2729 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2730 io.smb2.in.alloc_size = 0;
2731 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2732 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2733 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2734 io.smb2.in.create_options = 0;
2735 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2736 io.smb2.in.security_flags = 0;
2737 io.smb2.in.fname = fname;
2739 torture_comment(tctx, "BATCH23: an open and ask for a batch oplock\n");
2740 ZERO_STRUCT(break_info);
2742 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2743 SEC_RIGHTS_FILE_WRITE;
2744 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2745 NTCREATEX_SHARE_ACCESS_WRITE;
2746 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2747 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2748 status = smb2_create(tree1, tctx, &(io.smb2));
2749 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2750 h1 = io.smb2.out.file.handle;
2751 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2753 ZERO_STRUCT(break_info);
2755 torture_comment(tctx, "a 2nd open without level2 oplock support "
2756 "should generate a break to level2\n");
2757 status = smb2_create(tree3, tctx, &(io.smb2));
2758 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2759 h3 = io.smb2.out.file.handle;
2761 torture_wait_for_oplock_break(tctx);
2762 CHECK_VAL(break_info.count, 1);
2763 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2764 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2765 CHECK_VAL(break_info.failures, 0);
2767 ZERO_STRUCT(break_info);
2769 torture_comment(tctx, "a 3rd open with level2 oplock support should "
2770 "not generate a break\n");
2771 status = smb2_create(tree2, tctx, &(io.smb2));
2772 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2773 h2 = io.smb2.out.file.handle;
2774 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2776 torture_wait_for_oplock_break(tctx);
2777 CHECK_VAL(break_info.count, 0);
2779 smb2_util_close(tree1, h1);
2780 smb2_util_close(tree2, h2);
2781 smb2_util_close(tree3, h3);
2782 smb2_util_close(tree1, h);
2784 smb2_deltree(tree1, BASEDIR);
2788 static bool test_smb2_oplock_batch24(struct torture_context *tctx,
2789 struct smb2_tree *tree1,
2790 struct smb2_tree *tree2)
2792 const char *fname = BASEDIR "\\test_batch24.dat";
2796 struct smb2_handle h, h1, h2;
2797 struct smb2_tree *tree3 = NULL;
2799 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2800 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2803 smb2_util_unlink(tree1, fname);
2805 ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2806 CHECK_VAL(ret, true);
2808 tree1->session->transport->oplock.handler = torture_oplock_handler;
2809 tree1->session->transport->oplock.private_data = tree1;
2811 tree2->session->transport->oplock.handler = torture_oplock_handler;
2812 tree2->session->transport->oplock.private_data = tree2;
2814 tree3->session->transport->oplock.handler = torture_oplock_handler;
2815 tree3->session->transport->oplock.private_data = tree3;
2818 base ntcreatex parms
2820 ZERO_STRUCT(io.smb2);
2821 io.generic.level = RAW_OPEN_SMB2;
2822 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2823 io.smb2.in.alloc_size = 0;
2824 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2825 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2826 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2827 io.smb2.in.create_options = 0;
2828 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2829 io.smb2.in.security_flags = 0;
2830 io.smb2.in.fname = fname;
2832 torture_comment(tctx, "BATCH24: a open without level support and "
2833 "ask for a batch oplock\n");
2834 ZERO_STRUCT(break_info);
2836 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2837 SEC_RIGHTS_FILE_WRITE;
2838 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2839 NTCREATEX_SHARE_ACCESS_WRITE;
2840 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2841 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2843 status = smb2_create(tree3, tctx, &(io.smb2));
2844 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2845 h2 = io.smb2.out.file.handle;
2846 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2848 ZERO_STRUCT(break_info);
2850 torture_comment(tctx, "a 2nd open with level2 oplock support should "
2851 "generate a break\n");
2852 status = smb2_create(tree2, tctx, &(io.smb2));
2853 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2854 h1 = io.smb2.out.file.handle;
2855 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2857 torture_wait_for_oplock_break(tctx);
2858 CHECK_VAL(break_info.count, 1);
2859 CHECK_VAL(break_info.handle.data[0], h2.data[0]);
2860 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2861 CHECK_VAL(break_info.failures, 0);
2863 smb2_util_close(tree3, h2);
2864 smb2_util_close(tree2, h1);
2865 smb2_util_close(tree1, h);
2867 smb2_deltree(tree1, BASEDIR);
2871 static bool test_smb2_oplock_batch25(struct torture_context *tctx,
2872 struct smb2_tree *tree1)
2874 const char *fname = BASEDIR "\\test_batch25.dat";
2878 struct smb2_handle h, h1;
2880 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2881 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2884 smb2_util_unlink(tree1, fname);
2886 tree1->session->transport->oplock.handler = torture_oplock_handler;
2887 tree1->session->transport->oplock.private_data = tree1;
2890 base ntcreatex parms
2892 ZERO_STRUCT(io.smb2);
2893 io.generic.level = RAW_OPEN_SMB2;
2894 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2895 io.smb2.in.alloc_size = 0;
2896 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2897 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2898 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2899 io.smb2.in.create_options = 0;
2900 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2901 io.smb2.in.security_flags = 0;
2902 io.smb2.in.fname = fname;
2904 torture_comment(tctx, "BATCH25: open a file with an batch oplock "
2905 "(share mode: none)\n");
2907 ZERO_STRUCT(break_info);
2908 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2909 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2911 status = smb2_create(tree1, tctx, &(io.smb2));
2912 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2913 h1 = io.smb2.out.file.handle;
2914 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2916 torture_comment(tctx, "changing the file attribute info should trigger "
2917 "a break and a violation\n");
2919 status = smb2_util_setatr(tree1, fname, FILE_ATTRIBUTE_HIDDEN);
2920 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2921 "Incorrect status");
2923 torture_wait_for_oplock_break(tctx);
2924 CHECK_VAL(break_info.count, 1);
2926 smb2_util_close(tree1, h1);
2927 smb2_util_close(tree1, h);
2929 smb2_deltree(tree1, fname);
2933 static bool test_smb2_oplock_batch26(struct torture_context *tctx,
2934 struct smb2_tree *tree1)
2940 struct smb2_handle h, h1, h2, h3;
2941 const char *fname_base = BASEDIR "\\test_oplock.txt";
2942 const char *stream = "Stream One:$DATA";
2943 const char *fname_stream;
2945 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2946 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2948 tree1->session->transport->oplock.handler = torture_oplock_handler;
2949 tree1->session->transport->oplock.private_data = tree1;
2951 fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
2954 base ntcreatex parms
2956 ZERO_STRUCT(io.smb2);
2957 io.generic.level = RAW_OPEN_SMB2;
2958 io.smb2.in.desired_access = 0x120089;
2959 io.smb2.in.alloc_size = 0;
2960 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2961 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_DELETE |
2962 NTCREATEX_SHARE_ACCESS_WRITE;
2963 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2964 io.smb2.in.create_options = 0;
2965 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2966 io.smb2.in.security_flags = 0;
2967 io.smb2.in.fname = fname_base;
2970 Open base file with a batch oplock.
2972 torture_comment(tctx, "Open the base file with batch oplock\n");
2973 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2974 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2976 status = smb2_create(tree1, tctx, &(io.smb2));
2977 torture_assert_ntstatus_ok(tctx, status, "Error opening base file");
2978 h1 = io.smb2.out.file.handle;
2979 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2981 torture_comment(tctx, "Got batch oplock on base file\n");
2983 torture_comment(tctx, "Opening stream file with batch oplock..\n");
2985 io.smb2.in.fname = fname_stream;
2987 status = smb2_create(tree1, tctx, &(io.smb2));
2988 torture_assert_ntstatus_ok(tctx, status, "Error opening stream file");
2989 h2 = io.smb2.out.file.handle;
2990 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2992 torture_comment(tctx, "Got batch oplock on stream file\n");
2994 torture_comment(tctx, "Open base file again with batch oplock\n");
2996 io.smb2.in.fname = fname_base;
2998 status = smb2_create(tree1, tctx, &(io.smb2));
2999 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3000 h3 = io.smb2.out.file.handle;
3001 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
3003 smb2_util_close(tree1, h1);
3004 smb2_util_close(tree1, h2);
3005 smb2_util_close(tree1, h3);
3006 smb2_util_close(tree1, h);
3007 smb2_deltree(tree1, BASEDIR);
3012 /* Test how oplocks work on streams. */
3013 static bool test_raw_oplock_stream1(struct torture_context *tctx,
3014 struct smb2_tree *tree1,
3015 struct smb2_tree *tree2)
3019 const char *fname_base = BASEDIR "\\test_stream1.txt";
3020 const char *fname_stream, *fname_default_stream;
3021 const char *default_stream = "::$DATA";
3022 const char *stream = "Stream One:$DATA";
3024 struct smb2_handle h, h_base, h_stream;
3027 #define NSTREAM_OPLOCK_RESULTS 8
3030 bool open_base_file;
3031 uint32_t oplock_req;
3032 uint32_t oplock_granted;
3033 } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
3034 /* Request oplock on stream without the base file open. */
3035 {&fname_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
3036 {&fname_default_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
3037 {&fname_stream, false, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
3038 {&fname_default_stream, false, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
3040 /* Request oplock on stream with the base file open. */
3041 {&fname_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
3042 {&fname_default_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_II},
3043 {&fname_stream, true, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
3044 {&fname_default_stream, true, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_II},
3047 fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
3048 fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
3051 status = torture_smb2_testdir(tree1, BASEDIR, &h);
3052 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3054 /* Initialize handles to "closed". Using -1 in the first 64-bytes
3055 * as the sentry for this */
3056 h_stream.data[0] = -1;
3059 smb2_util_unlink(tree1, fname_base);
3061 tree1->session->transport->oplock.handler = torture_oplock_handler;
3062 tree1->session->transport->oplock.private_data = tree1;
3064 tree2->session->transport->oplock.handler = torture_oplock_handler;
3065 tree2->session->transport->oplock.private_data = tree2;
3067 /* Setup generic open parameters. */
3068 ZERO_STRUCT(io.smb2);
3069 io.generic.level = RAW_OPEN_SMB2;
3070 io.smb2.in.desired_access = (SEC_FILE_READ_DATA |
3071 SEC_FILE_WRITE_DATA |
3072 SEC_FILE_APPEND_DATA |
3073 SEC_STD_READ_CONTROL);
3074 io.smb2.in.alloc_size = 0;
3075 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3076 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3077 NTCREATEX_SHARE_ACCESS_WRITE;
3078 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3079 io.smb2.in.create_options = 0;
3080 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3081 io.smb2.in.security_flags = 0;
3083 /* Create the file with a stream */
3084 io.smb2.in.fname = fname_stream;
3085 io.smb2.in.create_flags = 0;
3086 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
3087 status = smb2_create(tree1, tctx, &(io.smb2));
3088 torture_assert_ntstatus_ok(tctx, status, "Error creating file");
3089 smb2_util_close(tree1, io.smb2.out.file.handle);
3091 /* Change the disposition to open now that the file has been created. */
3092 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
3094 /* Try some permutations of taking oplocks on streams. */
3095 for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
3096 const char *fname = *stream_oplock_results[i].fname;
3097 bool open_base_file = stream_oplock_results[i].open_base_file;
3098 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
3099 uint32_t oplock_granted =
3100 stream_oplock_results[i].oplock_granted;
3102 if (open_base_file) {
3103 torture_comment(tctx, "Opening base file: %s with "
3104 "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
3105 io.smb2.in.fname = fname_base;
3106 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3107 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3108 status = smb2_create(tree2, tctx, &(io.smb2));
3109 torture_assert_ntstatus_ok(tctx, status,
3110 "Error opening file");
3111 CHECK_VAL(io.smb2.out.oplock_level,
3112 SMB2_OPLOCK_LEVEL_BATCH);
3113 h_base = io.smb2.out.file.handle;
3116 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
3118 io.smb2.in.fname = fname;
3119 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3120 io.smb2.in.oplock_level = oplock_req;
3122 /* Do the open with the desired oplock on the stream. */
3123 status = smb2_create(tree1, tctx, &(io.smb2));
3124 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
3125 CHECK_VAL(io.smb2.out.oplock_level, oplock_granted);
3126 smb2_util_close(tree1, io.smb2.out.file.handle);
3128 /* Cleanup the base file if it was opened. */
3130 smb2_util_close(tree2, h_base);
3133 /* Open the stream with an exclusive oplock. */
3134 torture_comment(tctx, "Opening stream: %s with %d\n",
3135 fname_stream, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
3136 io.smb2.in.fname = fname_stream;
3137 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3138 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
3139 status = smb2_create(tree1, tctx, &(io.smb2));
3140 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
3141 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
3142 h_stream = io.smb2.out.file.handle;
3144 /* Open the base file and see if it contends. */
3145 ZERO_STRUCT(break_info);
3146 torture_comment(tctx, "Opening base file: %s with %d\n",
3147 fname_base, SMB2_OPLOCK_LEVEL_BATCH);
3148 io.smb2.in.fname = fname_base;
3149 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3150 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3151 status = smb2_create(tree2, tctx, &(io.smb2));
3152 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
3153 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3154 smb2_util_close(tree2, io.smb2.out.file.handle);
3156 torture_wait_for_oplock_break(tctx);
3157 CHECK_VAL(break_info.count, 0);
3158 CHECK_VAL(break_info.failures, 0);
3160 /* Open the stream again to see if it contends. */
3161 ZERO_STRUCT(break_info);
3162 torture_comment(tctx, "Opening stream again: %s with "
3163 "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
3164 io.smb2.in.fname = fname_stream;
3165 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3166 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
3167 status = smb2_create(tree2, tctx, &(io.smb2));
3168 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
3169 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
3170 smb2_util_close(tree2, io.smb2.out.file.handle);
3172 torture_wait_for_oplock_break(tctx);
3173 CHECK_VAL(break_info.count, 1);
3174 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3175 CHECK_VAL(break_info.failures, 0);
3177 /* Close the stream. */
3178 if (h_stream.data[0] != -1) {
3179 smb2_util_close(tree1, h_stream);
3182 smb2_util_close(tree1, h);
3184 smb2_deltree(tree1, BASEDIR);
3188 static bool test_smb2_oplock_doc(struct torture_context *tctx, struct smb2_tree *tree,
3189 struct smb2_tree *tree2)
3191 const char *fname = BASEDIR "\\test_oplock_doc.dat";
3195 struct smb2_handle h, h1;
3196 union smb_setfileinfo sfinfo;
3198 status = torture_smb2_testdir(tree, BASEDIR, &h);
3199 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3200 smb2_util_close(tree, h);
3203 smb2_util_unlink(tree, fname);
3204 tree->session->transport->oplock.handler = torture_oplock_handler;
3205 tree->session->transport->oplock.private_data = tree;
3208 base ntcreatex parms
3210 ZERO_STRUCT(io.smb2);
3211 io.generic.level = RAW_OPEN_SMB2;
3212 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3213 io.smb2.in.alloc_size = 0;
3214 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3215 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
3216 NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
3217 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3218 io.smb2.in.create_options = 0;
3219 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3220 io.smb2.in.security_flags = 0;
3221 io.smb2.in.fname = fname;
3223 torture_comment(tctx, "open a file with a batch oplock\n");
3224 ZERO_STRUCT(break_info);
3225 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3226 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3228 status = smb2_create(tree, tctx, &(io.smb2));
3229 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3230 h1 = io.smb2.out.file.handle;
3231 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3233 torture_comment(tctx, "Set delete on close\n");
3234 ZERO_STRUCT(sfinfo);
3235 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3236 sfinfo.generic.in.file.handle = h1;
3237 sfinfo.disposition_info.in.delete_on_close = 1;
3238 status = smb2_setinfo_file(tree, &sfinfo);
3239 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3241 torture_comment(tctx, "2nd open should not break and get "
3242 "DELETE_PENDING\n");
3243 ZERO_STRUCT(break_info);
3244 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
3245 io.smb2.in.create_options = 0;
3246 io.smb2.in.desired_access = SEC_FILE_READ_DATA;
3247 status = smb2_create(tree2, tctx, &io.smb2);
3248 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DELETE_PENDING,
3249 "Incorrect status");
3250 CHECK_VAL(break_info.count, 0);
3252 smb2_util_close(tree, h1);
3254 smb2_util_unlink(tree, fname);
3255 smb2_deltree(tree, BASEDIR);
3259 /* Open a file with a batch oplock, then open it again from a second client
3260 * requesting no oplock. Having two open file handles should break our own
3261 * oplock during BRL acquisition.
3263 static bool test_smb2_oplock_brl1(struct torture_context *tctx,
3264 struct smb2_tree *tree1,
3265 struct smb2_tree *tree2)
3267 const char *fname = BASEDIR "\\test_batch_brl.dat";
3273 struct smb2_lock lck;
3274 struct smb2_lock_element lock[1];
3275 struct smb2_handle h, h1, h2;
3277 status = torture_smb2_testdir(tree1, BASEDIR, &h);
3278 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3281 smb2_util_unlink(tree1, fname);
3283 tree1->session->transport->oplock.handler =
3284 torture_oplock_handler_two_notifications;
3285 tree1->session->transport->oplock.private_data = tree1;
3288 base ntcreatex parms
3290 ZERO_STRUCT(io.smb2);
3291 io.generic.level = RAW_OPEN_SMB2;
3292 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3293 SEC_RIGHTS_FILE_WRITE;
3294 io.smb2.in.alloc_size = 0;
3295 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3296 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3297 NTCREATEX_SHARE_ACCESS_WRITE;
3298 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3299 io.smb2.in.create_options = 0;
3300 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3301 io.smb2.in.security_flags = 0;
3302 io.smb2.in.fname = fname;
3305 with a batch oplock we get a break
3307 torture_comment(tctx, "open with batch oplock\n");
3308 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3309 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3311 status = smb2_create(tree1, tctx, &(io.smb2));
3312 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3313 h1 = io.smb2.out.file.handle;
3314 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3316 /* create a file with bogus data */
3317 memset(buf, 0, sizeof(buf));
3319 status = smb2_util_write(tree1, h1,buf, 0, sizeof(buf));
3320 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3321 torture_comment(tctx, "Failed to create file\n");
3326 torture_comment(tctx, "a 2nd open should give a break\n");
3327 ZERO_STRUCT(break_info);
3329 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3330 io.smb2.in.oplock_level = 0;
3331 status = smb2_create(tree2, tctx, &(io.smb2));
3332 h2 = io.smb2.out.file.handle;
3333 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3335 torture_wait_for_oplock_break(tctx);
3336 CHECK_VAL(break_info.count, 1);
3337 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3338 CHECK_VAL(break_info.failures, 0);
3339 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3341 ZERO_STRUCT(break_info);
3343 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3349 lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3350 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3353 lck.in.file.handle = h1;
3354 lck.in.locks = &lock[0];
3355 lck.in.lock_count = 1;
3356 status = smb2_lock(tree1, &lck);
3357 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3359 torture_wait_for_oplock_break(tctx);
3360 CHECK_VAL(break_info.count, 1);
3361 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3362 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3363 CHECK_VAL(break_info.failures, 0);
3365 /* expect no oplock break */
3366 ZERO_STRUCT(break_info);
3368 status = smb2_lock(tree1, &lck);
3369 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3370 "Incorrect status");
3372 torture_wait_for_oplock_break(tctx);
3373 CHECK_VAL(break_info.count, 0);
3374 CHECK_VAL(break_info.level, 0);
3375 CHECK_VAL(break_info.failures, 0);
3377 smb2_util_close(tree1, h1);
3378 smb2_util_close(tree2, h2);
3379 smb2_util_close(tree1, h);
3382 smb2_deltree(tree1, BASEDIR);
3387 /* Open a file with a batch oplock on one tree and then acquire a brl.
3388 * We should not contend our own oplock.
3390 static bool test_smb2_oplock_brl2(struct torture_context *tctx, struct smb2_tree *tree1)
3392 const char *fname = BASEDIR "\\test_batch_brl.dat";
3398 struct smb2_handle h, h1;
3399 struct smb2_lock lck;
3400 struct smb2_lock_element lock[1];
3402 status = torture_smb2_testdir(tree1, BASEDIR, &h);
3403 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3406 smb2_util_unlink(tree1, fname);
3408 tree1->session->transport->oplock.handler = torture_oplock_handler;
3409 tree1->session->transport->oplock.private_data = tree1;
3412 base ntcreatex parms
3414 ZERO_STRUCT(io.smb2);
3415 io.generic.level = RAW_OPEN_SMB2;
3416 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3417 SEC_RIGHTS_FILE_WRITE;
3418 io.smb2.in.alloc_size = 0;
3419 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3420 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3421 NTCREATEX_SHARE_ACCESS_WRITE;
3422 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3423 io.smb2.in.create_options = 0;
3424 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3425 io.smb2.in.security_flags = 0;
3426 io.smb2.in.fname = fname;
3429 with a batch oplock we get a break
3431 torture_comment(tctx, "open with batch oplock\n");
3432 ZERO_STRUCT(break_info);
3433 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3434 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3436 status = smb2_create(tree1, tctx, &(io.smb2));
3437 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3438 h1 = io.smb2.out.file.handle;
3439 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3441 /* create a file with bogus data */
3442 memset(buf, 0, sizeof(buf));
3444 status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3445 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3446 torture_comment(tctx, "Failed to create file\n");
3451 ZERO_STRUCT(break_info);
3453 torture_comment(tctx, "a self BRL acquisition should not break to "
3460 lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3461 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3464 lck.in.file.handle = h1;
3465 lck.in.locks = &lock[0];
3466 lck.in.lock_count = 1;
3467 status = smb2_lock(tree1, &lck);
3468 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3471 status = smb2_lock(tree1, &lck);
3472 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3473 "Incorrect status");
3475 /* With one file handle open a BRL should not contend our oplock.
3476 * Thus, no oplock break will be received and the entire break_info
3477 * struct will be 0 */
3478 torture_wait_for_oplock_break(tctx);
3479 CHECK_VAL(break_info.count, 0);
3480 CHECK_VAL(break_info.level, 0);
3481 CHECK_VAL(break_info.failures, 0);
3483 smb2_util_close(tree1, h1);
3484 smb2_util_close(tree1, h);
3487 smb2_deltree(tree1, BASEDIR);
3491 /* Open a file with a batch oplock twice from one tree and then acquire a
3492 * brl. BRL acquisition should break our own oplock.
3494 static bool test_smb2_oplock_brl3(struct torture_context *tctx, struct smb2_tree *tree1)
3496 const char *fname = BASEDIR "\\test_batch_brl.dat";
3501 struct smb2_handle h, h1, h2;
3502 struct smb2_lock lck;
3503 struct smb2_lock_element lock[1];
3505 status = torture_smb2_testdir(tree1, BASEDIR, &h);
3506 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3509 smb2_util_unlink(tree1, fname);
3510 tree1->session->transport->oplock.handler =
3511 torture_oplock_handler_two_notifications;
3512 tree1->session->transport->oplock.private_data = tree1;
3515 base ntcreatex parms
3517 ZERO_STRUCT(io.smb2);
3518 io.generic.level = RAW_OPEN_SMB2;
3519 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3520 SEC_RIGHTS_FILE_WRITE;
3521 io.smb2.in.alloc_size = 0;
3522 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3523 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3524 NTCREATEX_SHARE_ACCESS_WRITE;
3525 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3526 io.smb2.in.create_options = 0;
3527 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3528 io.smb2.in.security_flags = 0;
3529 io.smb2.in.fname = fname;
3532 with a batch oplock we get a break
3534 torture_comment(tctx, "open with batch oplock\n");
3535 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3536 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3538 status = smb2_create(tree1, tctx, &(io.smb2));
3539 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3540 h1 = io.smb2.out.file.handle;
3541 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3543 /* create a file with bogus data */
3544 memset(buf, 0, sizeof(buf));
3545 status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3547 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3548 torture_comment(tctx, "Failed to create file\n");
3553 torture_comment(tctx, "a 2nd open should give a break\n");
3554 ZERO_STRUCT(break_info);
3556 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3557 io.smb2.in.oplock_level = 0;
3558 status = smb2_create(tree1, tctx, &(io.smb2));
3559 h2 = io.smb2.out.file.handle;
3560 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3561 CHECK_VAL(break_info.count, 1);
3562 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3563 CHECK_VAL(break_info.failures, 0);
3564 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3566 ZERO_STRUCT(break_info);
3568 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3574 lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3575 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3578 lck.in.file.handle = h1;
3579 lck.in.locks = &lock[0];
3580 lck.in.lock_count = 1;
3581 status = smb2_lock(tree1, &lck);
3582 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3584 torture_wait_for_oplock_break(tctx);
3585 CHECK_VAL(break_info.count, 1);
3586 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3587 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3588 CHECK_VAL(break_info.failures, 0);
3590 /* expect no oplock break */
3591 ZERO_STRUCT(break_info);
3593 status = smb2_lock(tree1, &lck);
3594 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3595 "Incorrect status");
3597 torture_wait_for_oplock_break(tctx);
3598 CHECK_VAL(break_info.count, 0);
3599 CHECK_VAL(break_info.level, 0);
3600 CHECK_VAL(break_info.failures, 0);
3602 smb2_util_close(tree1, h1);
3603 smb2_util_close(tree1, h2);
3604 smb2_util_close(tree1, h);
3607 smb2_deltree(tree1, BASEDIR);
3612 /* Starting the SMB2 specific oplock tests at 500 so we can keep the SMB1
3613 * tests in sync with an identically numbered SMB2 test */
3615 /* Test whether the server correctly returns an error when we send
3616 * a response to a levelII to none oplock notification. */
3617 static bool test_smb2_oplock_levelII500(struct torture_context *tctx,
3618 struct smb2_tree *tree1)
3620 const char *fname = BASEDIR "\\test_levelII500.dat";
3624 struct smb2_handle h, h1;
3627 status = torture_smb2_testdir(tree1, BASEDIR, &h);
3628 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3631 smb2_util_unlink(tree1, fname);
3633 tree1->session->transport->oplock.handler = torture_oplock_handler;
3634 tree1->session->transport->oplock.private_data = tree1;
3637 base ntcreatex parms
3639 ZERO_STRUCT(io.smb2);
3640 io.generic.level = RAW_OPEN_SMB2;
3641 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3642 io.smb2.in.alloc_size = 0;
3643 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3644 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3645 io.smb2.in.create_options = 0;
3646 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3647 io.smb2.in.security_flags = 0;
3648 io.smb2.in.fname = fname;
3650 torture_comment(tctx, "LEVELII500: acknowledging a break from II to "
3651 "none should return an error\n");
3652 ZERO_STRUCT(break_info);
3654 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3655 SEC_RIGHTS_FILE_WRITE;
3656 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3657 NTCREATEX_SHARE_ACCESS_WRITE;
3658 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3659 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
3660 status = smb2_create(tree1, tctx, &(io.smb2));
3661 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3662 h1 = io.smb2.out.file.handle;
3663 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
3665 ZERO_STRUCT(break_info);
3667 torture_comment(tctx, "write should trigger a break to none and when "
3668 "we reply, an oplock break failure\n");
3669 smb2_util_write(tree1, h1, &c, 0, 1);
3671 /* Wait several times to receive both the break notification, and the
3672 * NT_STATUS_INVALID_OPLOCK_PROTOCOL error in the break response */
3673 torture_wait_for_oplock_break(tctx);
3674 torture_wait_for_oplock_break(tctx);
3675 torture_wait_for_oplock_break(tctx);
3676 torture_wait_for_oplock_break(tctx);
3678 /* There appears to be a race condition in W2K8 and W2K8R2 where
3679 * sometimes the server will happily reply to our break response with
3680 * NT_STATUS_OK, and sometimes it will return the OPLOCK_PROTOCOL
3681 * error. As the MS-SMB2 doc states that a client should not reply to
3682 * a level2 to none break notification, I'm leaving the protocol error
3683 * as the expected behavior. */
3684 CHECK_VAL(break_info.count, 1);
3685 CHECK_VAL(break_info.level, 0);
3686 CHECK_VAL(break_info.failures, 1);
3687 torture_assert_ntstatus_equal(tctx, break_info.failure_status,
3688 NT_STATUS_INVALID_OPLOCK_PROTOCOL,
3689 "Incorrect status");
3691 smb2_util_close(tree1, h1);
3692 smb2_util_close(tree1, h);
3694 smb2_deltree(tree1, BASEDIR);
3699 * Test a double-break. Open a file with exclusive. Send off a second open
3700 * request with OPEN_IF, triggering a break to level2. This should respond
3701 * with level2. Before replying to the break to level2, fire off a third open
3702 * with OVERWRITE_IF. The expected sequence would be that the 3rd opener gets
3703 * a level2 immediately triggered by a break to none, but that seems not the
3704 * case. Still investigating what the right behaviour should be.
3707 struct levelII501_state {
3708 struct torture_context *tctx;
3709 struct smb2_tree *tree1;
3710 struct smb2_tree *tree2;
3711 struct smb2_tree *tree3;
3712 struct smb2_handle h;
3713 struct smb2_handle h1;
3716 struct smb2_handle break_handle;
3718 struct smb2_break br;
3723 static bool torture_oplock_break_delay(struct smb2_transport *transport,
3724 const struct smb2_handle *handle,
3725 uint8_t level, void *private_data);
3726 static void levelII501_break_done(struct smb2_request *req);
3727 static void levelII501_open1_done(struct smb2_request *req);
3728 static void levelII501_open2_done(struct smb2_request *req);
3729 static void levelII501_2ndopen_cb(struct tevent_context *ev,
3730 struct tevent_timer *te,
3731 struct timeval current_time,
3732 void *private_data);
3733 static void levelII501_break_timeout_cb(struct tevent_context *ev,
3734 struct tevent_timer *te,
3735 struct timeval current_time,
3736 void *private_data);
3737 static void levelII501_timeout_cb(struct tevent_context *ev,
3738 struct tevent_timer *te,
3739 struct timeval current_time,
3740 void *private_data);
3742 static bool test_smb2_oplock_levelII501(struct torture_context *tctx,
3743 struct smb2_tree *tree1,
3744 struct smb2_tree *tree2)
3746 const char *fname = BASEDIR "\\test_levelII501.dat";
3749 struct levelII501_state *state;
3750 struct smb2_request *req;
3751 struct tevent_timer *te;
3753 state = talloc(tctx, struct levelII501_state);
3755 state->done = false;
3756 state->tree1 = tree1;
3757 state->tree2 = tree2;
3759 if (!torture_smb2_connection(tctx, &state->tree3)) {
3760 torture_fail(tctx, "Establishing SMB2 connection failed\n");
3764 status = torture_smb2_testdir(tree1, BASEDIR, &state->h);
3765 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3768 smb2_util_unlink(tree1, fname);
3771 base ntcreatex parms
3773 ZERO_STRUCT(state->io.smb2);
3774 state->io.generic.level = RAW_OPEN_SMB2;
3775 state->io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3776 state->io.smb2.in.alloc_size = 0;
3777 state->io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3778 state->io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3779 state->io.smb2.in.create_options = 0;
3780 state->io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3781 state->io.smb2.in.security_flags = 0;
3782 state->io.smb2.in.fname = fname;
3784 torture_comment(tctx, "LEVELII501: Test double break sequence\n");
3785 ZERO_STRUCT(break_info);
3787 state->io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3788 SEC_RIGHTS_FILE_WRITE;
3789 state->io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3790 NTCREATEX_SHARE_ACCESS_WRITE;
3791 state->io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3792 state->io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
3794 tree1->session->transport->oplock.handler = torture_oplock_break_delay;
3795 tree1->session->transport->oplock.private_data = state;
3797 status = smb2_create(tree1, tctx, &(state->io.smb2));
3798 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3799 state->h1 = state->io.smb2.out.file.handle;
3800 CHECK_VAL(state->io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
3803 * Trigger a break to level2
3806 req = smb2_create_send(tree2, &state->io.smb2);
3807 req->async.fn = levelII501_open1_done;
3808 req->async.private_data = state;
3810 te = tevent_add_timer(
3811 tctx->ev, tctx, tevent_timeval_current_ofs(0, 200000),
3812 levelII501_2ndopen_cb, state);
3813 torture_assert(tctx, te != NULL, "tevent_add_timer failed\n");
3815 te = tevent_add_timer(
3816 tctx->ev, tctx, tevent_timeval_current_ofs(2, 0),
3817 levelII501_timeout_cb, state);
3818 torture_assert(tctx, te != NULL, "tevent_add_timer failed\n");
3820 while (!state->done) {
3821 if (tevent_loop_once(tctx->ev) != 0) {
3822 torture_comment(tctx, "tevent_loop_once failed\n");
3830 * Fire off a second open after a little timeout
3833 static void levelII501_2ndopen_cb(struct tevent_context *ev,
3834 struct tevent_timer *te,
3835 struct timeval current_time,
3838 struct levelII501_state *state = talloc_get_type_abort(
3839 private_data, struct levelII501_state);
3840 struct smb2_request *req;
3842 state->io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
3843 req = smb2_create_send(state->tree3, &state->io.smb2);
3844 req->async.fn = levelII501_open2_done;
3845 req->async.private_data = state;
3849 * Postpone the break response by 500 msec
3851 static bool torture_oplock_break_delay(struct smb2_transport *transport,
3852 const struct smb2_handle *handle,
3853 uint8_t level, void *private_data)
3855 struct levelII501_state *state = talloc_get_type_abort(
3856 private_data, struct levelII501_state);
3858 struct tevent_timer *te;
3860 break_info.handle = *handle;
3861 break_info.level = level;
3864 state->break_handle = *handle;
3865 state->break_to = level;
3868 case SMB2_OPLOCK_LEVEL_II:
3871 case SMB2_OPLOCK_LEVEL_NONE:
3878 printf("Got break to %s [0x%02X] in oplock handler, postponing "
3879 "break response for 500msec\n", name, level);
3881 te = tevent_add_timer(
3882 state->tctx->ev, state->tctx,
3883 tevent_timeval_current_ofs(0, 500000),
3884 levelII501_break_timeout_cb, state);
3885 torture_assert(state->tctx, te != NULL, "tevent_add_timer failed\n");
3890 static void levelII501_break_timeout_cb(struct tevent_context *ev,
3891 struct tevent_timer *te,
3892 struct timeval current_time,
3895 struct levelII501_state *state = talloc_get_type_abort(
3896 private_data, struct levelII501_state);
3897 struct smb2_request *req;
3901 ZERO_STRUCT(state->br);
3902 state->br.in.file.handle = state->break_handle;
3903 state->br.in.oplock_level = state->break_to;
3905 req = smb2_break_send(state->tree1, &state->br);
3906 req->async.fn = levelII501_break_done;
3907 req->async.private_data = state;
3910 static void levelII501_break_done(struct smb2_request *req)
3912 struct smb2_break io;
3915 status = smb2_break_recv(req, &io);
3916 printf("break done: %s\n", nt_errstr(status));
3919 static void levelII501_open1_done(struct smb2_request *req)
3921 struct levelII501_state *state = talloc_get_type_abort(
3922 req->async.private_data, struct levelII501_state);
3923 struct smb2_create io;
3926 status = smb2_create_recv(req, state, &io);
3927 printf("open1 done: %s\n", nt_errstr(status));
3930 static void levelII501_open2_done(struct smb2_request *req)
3932 struct levelII501_state *state = talloc_get_type_abort(
3933 req->async.private_data, struct levelII501_state);
3934 struct smb2_create io;
3937 status = smb2_create_recv(req, state, &io);
3938 printf("open2 done: %s\n", nt_errstr(status));
3941 static void levelII501_timeout_cb(struct tevent_context *ev,
3942 struct tevent_timer *te,
3943 struct timeval current_time,
3946 struct levelII501_state *state = talloc_get_type_abort(
3947 private_data, struct levelII501_state);
3952 struct torture_suite *torture_smb2_oplocks_init(TALLOC_CTX *ctx)
3954 struct torture_suite *suite =
3955 torture_suite_create(ctx, "oplock");
3957 torture_suite_add_2smb2_test(suite, "exclusive1", test_smb2_oplock_exclusive1);
3958 torture_suite_add_2smb2_test(suite, "exclusive2", test_smb2_oplock_exclusive2);
3959 torture_suite_add_2smb2_test(suite, "exclusive3", test_smb2_oplock_exclusive3);
3960 torture_suite_add_2smb2_test(suite, "exclusive4", test_smb2_oplock_exclusive4);
3961 torture_suite_add_2smb2_test(suite, "exclusive5", test_smb2_oplock_exclusive5);
3962 torture_suite_add_2smb2_test(suite, "exclusive6", test_smb2_oplock_exclusive6);
3963 torture_suite_add_2smb2_test(suite, "exclusive9",
3964 test_smb2_oplock_exclusive9);
3965 torture_suite_add_2smb2_test(suite, "batch1", test_smb2_oplock_batch1);
3966 torture_suite_add_2smb2_test(suite, "batch2", test_smb2_oplock_batch2);
3967 torture_suite_add_2smb2_test(suite, "batch3", test_smb2_oplock_batch3);
3968 torture_suite_add_2smb2_test(suite, "batch4", test_smb2_oplock_batch4);
3969 torture_suite_add_2smb2_test(suite, "batch5", test_smb2_oplock_batch5);
3970 torture_suite_add_2smb2_test(suite, "batch6", test_smb2_oplock_batch6);
3971 torture_suite_add_2smb2_test(suite, "batch7", test_smb2_oplock_batch7);
3972 torture_suite_add_2smb2_test(suite, "batch8", test_smb2_oplock_batch8);
3973 torture_suite_add_2smb2_test(suite, "batch9", test_smb2_oplock_batch9);
3974 torture_suite_add_2smb2_test(suite, "batch9a", test_smb2_oplock_batch9a);
3975 torture_suite_add_2smb2_test(suite, "batch10", test_smb2_oplock_batch10);
3976 torture_suite_add_2smb2_test(suite, "batch11", test_smb2_oplock_batch11);
3977 torture_suite_add_2smb2_test(suite, "batch12", test_smb2_oplock_batch12);
3978 torture_suite_add_2smb2_test(suite, "batch13", test_smb2_oplock_batch13);
3979 torture_suite_add_2smb2_test(suite, "batch14", test_smb2_oplock_batch14);
3980 torture_suite_add_2smb2_test(suite, "batch15", test_smb2_oplock_batch15);
3981 torture_suite_add_2smb2_test(suite, "batch16", test_smb2_oplock_batch16);
3982 torture_suite_add_1smb2_test(suite, "batch19", test_smb2_oplock_batch19);
3983 torture_suite_add_2smb2_test(suite, "batch20", test_smb2_oplock_batch20);
3984 torture_suite_add_1smb2_test(suite, "batch21", test_smb2_oplock_batch21);
3985 torture_suite_add_1smb2_test(suite, "batch22", test_smb2_oplock_batch22);
3986 torture_suite_add_2smb2_test(suite, "batch23", test_smb2_oplock_batch23);
3987 torture_suite_add_2smb2_test(suite, "batch24", test_smb2_oplock_batch24);
3988 torture_suite_add_1smb2_test(suite, "batch25", test_smb2_oplock_batch25);
3989 torture_suite_add_1smb2_test(suite, "batch26", test_smb2_oplock_batch26);
3990 torture_suite_add_2smb2_test(suite, "stream1", test_raw_oplock_stream1);
3991 torture_suite_add_2smb2_test(suite, "doc", test_smb2_oplock_doc);
3992 torture_suite_add_2smb2_test(suite, "brl1", test_smb2_oplock_brl1);
3993 torture_suite_add_1smb2_test(suite, "brl2", test_smb2_oplock_brl2);
3994 torture_suite_add_1smb2_test(suite, "brl3", test_smb2_oplock_brl3);
3995 torture_suite_add_1smb2_test(suite, "levelii500", test_smb2_oplock_levelII500);
3996 torture_suite_add_2smb2_test(suite, "levelii501",
3997 test_smb2_oplock_levelII501);
3998 suite->description = talloc_strdup(suite, "SMB2-OPLOCK tests");
4004 stress testing of oplocks
4006 bool test_smb2_bench_oplock(struct torture_context *tctx,
4007 struct smb2_tree *tree)
4009 struct smb2_tree **trees;
4012 TALLOC_CTX *mem_ctx = talloc_new(tctx);
4013 int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
4015 int timelimit = torture_setting_int(tctx, "timelimit", 10);
4018 struct smb2_handle h;
4020 trees = talloc_array(mem_ctx, struct smb2_tree *, torture_nprocs);
4022 torture_comment(tctx, "Opening %d connections\n", torture_nprocs);
4023 for (i=0;i<torture_nprocs;i++) {
4024 if (!torture_smb2_connection(tctx, &trees[i])) {
4027 talloc_steal(mem_ctx, trees[i]);
4028 trees[i]->session->transport->oplock.handler =
4029 torture_oplock_handler_close;
4030 trees[i]->session->transport->oplock.private_data = trees[i];
4033 status = torture_smb2_testdir(trees[0], BASEDIR, &h);
4034 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
4036 ZERO_STRUCT(io.smb2);
4037 io.smb2.level = RAW_OPEN_SMB2;
4038 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
4039 io.smb2.in.alloc_size = 0;
4040 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4041 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
4042 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4043 io.smb2.in.create_options = 0;
4044 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4045 io.smb2.in.security_flags = 0;
4046 io.smb2.in.fname = BASEDIR "\\test.dat";
4047 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
4048 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
4050 tv = timeval_current();
4053 we open the same file with SHARE_ACCESS_NONE from all the
4054 connections in a round robin fashion. Each open causes an
4055 oplock break on the previous connection, which is answered
4056 by the oplock_handler_close() to close the file.
4058 This measures how fast we can pass on oplocks, and stresses
4059 the oplock handling code
4061 torture_comment(tctx, "Running for %d seconds\n", timelimit);
4062 while (timeval_elapsed(&tv) < timelimit) {
4063 for (i=0;i<torture_nprocs;i++) {
4064 status = smb2_create(trees[i], mem_ctx, &(io.smb2));
4065 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
4069 if (torture_setting_bool(tctx, "progress", true)) {
4070 torture_comment(tctx, "%.2f ops/second\r",
4071 count/timeval_elapsed(&tv));
4075 torture_comment(tctx, "%.2f ops/second\n", count/timeval_elapsed(&tv));
4076 smb2_util_close(trees[0], io.smb2.out.file.handle);
4077 smb2_util_unlink(trees[0], BASEDIR "\\test.dat");
4078 smb2_deltree(trees[0], BASEDIR);
4079 talloc_free(mem_ctx);
4083 static struct hold_oplock_info {
4085 bool close_on_break;
4086 uint32_t share_access;
4087 struct smb2_handle handle;
4089 { BASEDIR "\\notshared_close", true,
4090 NTCREATEX_SHARE_ACCESS_NONE, },
4091 { BASEDIR "\\notshared_noclose", false,
4092 NTCREATEX_SHARE_ACCESS_NONE, },
4093 { BASEDIR "\\shared_close", true,
4094 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
4095 { BASEDIR "\\shared_noclose", false,
4096 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
4099 static bool torture_oplock_handler_hold(struct smb2_transport *transport,
4100 const struct smb2_handle *handle,
4101 uint8_t level, void *private_data)
4103 struct hold_oplock_info *info;
4106 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4107 if (smb2_util_handle_equal(hold_info[i].handle, *handle))
4111 if (i == ARRAY_SIZE(hold_info)) {
4112 printf("oplock break for unknown handle 0x%llx%llx\n",
4113 (unsigned long long) handle->data[0],
4114 (unsigned long long) handle->data[1]);
4118 info = &hold_info[i];
4120 if (info->close_on_break) {
4121 printf("oplock break on %s - closing\n", info->fname);
4122 torture_oplock_handler_close(transport, handle,
4123 level, private_data);
4127 printf("oplock break on %s - acking break\n", info->fname);
4128 printf("Acking to none in oplock handler\n");
4130 torture_oplock_handler_ack_to_none(transport, handle,
4131 level, private_data);
4136 used for manual testing of oplocks - especially interaction with
4137 other filesystems (such as NFS and local access)
4139 bool test_smb2_hold_oplock(struct torture_context *tctx,
4140 struct smb2_tree *tree)
4142 struct torture_context *mem_ctx = talloc_new(tctx);
4143 struct tevent_context *ev = tctx->ev;
4145 struct smb2_handle h;
4148 torture_comment(tctx, "Setting up open files with oplocks in %s\n",
4151 status = torture_smb2_testdir(tree, BASEDIR, &h);
4152 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
4154 tree->session->transport->oplock.handler = torture_oplock_handler_hold;
4155 tree->session->transport->oplock.private_data = tree;
4157 /* setup the files */
4158 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4162 ZERO_STRUCT(io.smb2);
4163 io.generic.level = RAW_OPEN_SMB2;
4164 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
4165 io.smb2.in.alloc_size = 0;
4166 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4167 io.smb2.in.share_access = hold_info[i].share_access;
4168 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4169 io.smb2.in.create_options = 0;
4170 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4171 io.smb2.in.security_flags = 0;
4172 io.smb2.in.fname = hold_info[i].fname;
4173 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
4174 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
4176 torture_comment(tctx, "opening %s\n", hold_info[i].fname);
4178 status = smb2_create(tree, mem_ctx, &(io.smb2));
4179 if (!NT_STATUS_IS_OK(status)) {
4180 torture_comment(tctx, "Failed to open %s - %s\n",
4181 hold_info[i].fname, nt_errstr(status));
4185 if (io.smb2.out.oplock_level != SMB2_OPLOCK_LEVEL_BATCH) {
4186 torture_comment(tctx, "Oplock not granted for %s - "
4187 "expected %d but got %d\n",
4189 SMB2_OPLOCK_LEVEL_BATCH,
4190 io.smb2.out.oplock_level);
4193 hold_info[i].handle = io.smb2.out.file.handle;
4195 /* make the file non-zero size */
4196 status = smb2_util_write(tree, hold_info[i].handle, &c, 0, 1);
4197 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
4198 torture_comment(tctx, "Failed to write to file\n");
4203 torture_comment(tctx, "Waiting for oplock events\n");
4204 tevent_loop_wait(ev);
4205 smb2_deltree(tree, BASEDIR);
4206 talloc_free(mem_ctx);
4211 static bool test_smb2_kernel_oplocks1(struct torture_context *tctx,
4212 struct smb2_tree *tree)
4214 const char *fname = "test_kernel_oplock1.dat";
4217 struct smb2_create create;
4218 struct smb2_handle h1 = {{0}}, h2 = {{0}};
4220 smb2_util_unlink(tree, fname);
4222 tree->session->transport->oplock.handler = torture_oplock_handler;
4223 tree->session->transport->oplock.private_data = tree;
4224 ZERO_STRUCT(break_info);
4226 ZERO_STRUCT(create);
4227 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4228 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4229 create.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
4230 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4231 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4232 create.in.fname = fname;
4233 create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
4235 status = smb2_create(tree, tctx, &create);
4236 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4237 h1 = create.out.file.handle;
4239 torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done,
4240 "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n");
4242 ZERO_STRUCT(create);
4243 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4244 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4245 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4246 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4247 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4248 create.in.fname = fname;
4250 status = smb2_create(tree, tctx, &create);
4251 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done,
4252 "Open didn't return NT_STATUS_SHARING_VIOLATION\n");
4253 h2 = create.out.file.handle;
4255 torture_wait_for_oplock_break(tctx);
4256 if (break_info.count != 0) {
4257 torture_warning(tctx, "Open caused oplock break\n");
4260 smb2_util_close(tree, h1);
4261 smb2_util_close(tree, h2);
4264 if (!smb2_util_handle_empty(h1)) {
4265 smb2_util_close(tree, h1);
4267 if (!smb2_util_handle_empty(h2)) {
4268 smb2_util_close(tree, h2);
4270 smb2_util_unlink(tree, fname);
4274 static bool test_smb2_kernel_oplocks2(struct torture_context *tctx,
4275 struct smb2_tree *tree)
4277 const char *fname = "test_kernel_oplock2.dat";
4278 const char *sname = "test_kernel_oplock2.dat:foo";
4281 struct smb2_create create;
4282 struct smb2_handle h1 = {{0}}, h2 = {{0}};
4284 smb2_util_unlink(tree, fname);
4286 tree->session->transport->oplock.handler = torture_oplock_handler;
4287 tree->session->transport->oplock.private_data = tree;
4288 ZERO_STRUCT(break_info);
4290 ZERO_STRUCT(create);
4291 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4292 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4293 create.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
4294 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4295 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4296 create.in.fname = fname;
4297 create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
4299 status = smb2_create(tree, tctx, &create);
4300 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4301 h1 = create.out.file.handle;
4303 torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done,
4304 "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n");
4306 ZERO_STRUCT(create);
4307 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4308 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4309 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4310 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4311 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4312 create.in.fname = sname;
4314 status = smb2_create(tree, tctx, &create);
4315 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4316 h2 = create.out.file.handle;
4318 torture_wait_for_oplock_break(tctx);
4319 if (break_info.count != 0) {
4320 torture_warning(tctx, "Stream open caused oplock break\n");
4323 smb2_util_close(tree, h1);
4324 smb2_util_close(tree, h2);
4327 if (!smb2_util_handle_empty(h1)) {
4328 smb2_util_close(tree, h1);
4330 if (!smb2_util_handle_empty(h2)) {
4331 smb2_util_close(tree, h2);
4333 smb2_util_unlink(tree, fname);
4338 * 1. 1st client opens file with oplock
4339 * 2. 2nd client opens file
4341 * Verify 2 triggers an oplock break
4343 static bool test_smb2_kernel_oplocks3(struct torture_context *tctx,
4344 struct smb2_tree *tree,
4345 struct smb2_tree *tree2)
4347 const char *fname = "test_kernel_oplock3.dat";
4350 struct smb2_create create;
4351 struct smb2_handle h1 = {{0}}, h2 = {{0}};
4353 smb2_util_unlink(tree, fname);
4354 status = torture_smb2_testfile(tree, fname, &h1);
4355 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4356 "Error creating testfile\n");
4357 smb2_util_close(tree, h1);
4360 tree->session->transport->oplock.handler = torture_oplock_handler;
4361 tree->session->transport->oplock.private_data = tree;
4362 ZERO_STRUCT(break_info);
4365 ZERO_STRUCT(create);
4366 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4367 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4368 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4369 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4370 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4371 create.in.fname = fname;
4372 create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
4374 status = smb2_create(tree, tctx, &create);
4375 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4376 h1 = create.out.file.handle;
4378 torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done,
4379 "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n");
4382 ZERO_STRUCT(create);
4383 create.in.desired_access = SEC_RIGHTS_FILE_READ;
4384 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4385 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4386 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4387 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4388 create.in.fname = fname;
4390 status = smb2_create(tree2, tctx, &create);
4391 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4392 h2 = create.out.file.handle;
4394 torture_wait_for_oplock_break(tctx);
4395 torture_assert_goto(tctx, break_info.count == 1, ret, done, "Expected 1 oplock break\n");
4398 if (!smb2_util_handle_empty(h1)) {
4399 smb2_util_close(tree, h1);
4401 if (!smb2_util_handle_empty(h2)) {
4402 smb2_util_close(tree, h2);
4404 smb2_util_unlink(tree, fname);
4409 * 1) create testfile with stream
4410 * 2) open file r/w with batch oplock, sharing read/delete
4411 * 3) open stream on file for reading
4413 * Verify 3) doesn't trigger an oplock break
4415 static bool test_smb2_kernel_oplocks4(struct torture_context *tctx,
4416 struct smb2_tree *tree)
4418 const char *fname = "test_kernel_oplock4.dat";
4419 const char *sname = "test_kernel_oplock4.dat:foo";
4422 struct smb2_create create;
4423 struct smb2_handle h1 = {{0}}, h2 = {{0}};
4425 tree->session->transport->oplock.handler = torture_oplock_handler;
4426 tree->session->transport->oplock.private_data = tree;
4427 ZERO_STRUCT(break_info);
4428 smb2_util_unlink(tree, fname);
4431 status = torture_smb2_testfile(tree, fname, &h1);
4432 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4433 "Error creating testfile\n");
4434 smb2_util_close(tree, h1);
4437 ZERO_STRUCT(create);
4438 create.in.desired_access = SEC_RIGHTS_FILE_READ;
4439 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4440 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4441 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4442 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4443 create.in.fname = sname;
4445 status = smb2_create(tree, tctx, &create);
4446 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4447 h1 = create.out.file.handle;
4448 smb2_util_close(tree, h1);
4452 ZERO_STRUCT(create);
4453 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4454 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4455 create.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
4456 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4457 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4458 create.in.fname = fname;
4459 create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
4461 status = smb2_create(tree, tctx, &create);
4462 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4463 h1 = create.out.file.handle;
4465 torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_BATCH, ret, done,
4466 "Oplock level is not SMB2_OPLOCK_LEVEL_BATCH\n");
4468 ZERO_STRUCT(create);
4469 create.in.desired_access = SEC_RIGHTS_FILE_READ;
4470 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4471 create.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
4472 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4473 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4474 create.in.fname = sname;
4476 status = smb2_create(tree, tctx, &create);
4477 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4478 h2 = create.out.file.handle;
4480 torture_wait_for_oplock_break(tctx);
4481 if (break_info.count != 0) {
4482 torture_warning(tctx, "Stream open caused oplock break\n");
4486 if (!smb2_util_handle_empty(h1)) {
4487 smb2_util_close(tree, h1);
4489 if (!smb2_util_handle_empty(h2)) {
4490 smb2_util_close(tree, h2);
4492 smb2_util_unlink(tree, fname);
4497 * 1) create testfile with stream
4498 * 2) open stream r/w with batch oplock -> batch oplock granted
4499 * 3) open stream r/o with batch oplock
4501 * Verify 3) does trigger an oplock break
4503 static bool test_smb2_kernel_oplocks5(struct torture_context *tctx,
4504 struct smb2_tree *tree)
4506 const char *fname = "test_kernel_oplock4.dat";
4507 const char *sname = "test_kernel_oplock4.dat:foo";
4510 struct smb2_create create;
4511 struct smb2_handle h1 = {{0}}, h2 = {{0}};
4513 tree->session->transport->oplock.handler = torture_oplock_handler;
4514 tree->session->transport->oplock.private_data = tree;
4515 ZERO_STRUCT(break_info);
4516 smb2_util_unlink(tree, fname);
4519 status = torture_smb2_testfile(tree, fname, &h1);
4520 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4521 "Error creating testfile\n");
4522 smb2_util_close(tree, h1);
4525 ZERO_STRUCT(create);
4526 create.in.desired_access = SEC_RIGHTS_FILE_READ;
4527 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4528 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4529 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4530 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4531 create.in.fname = sname;
4533 status = smb2_create(tree, tctx, &create);
4534 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4535 h1 = create.out.file.handle;
4536 smb2_util_close(tree, h1);
4540 ZERO_STRUCT(create);
4541 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4542 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4543 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4544 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4545 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4546 create.in.fname = sname;
4547 create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
4549 status = smb2_create(tree, tctx, &create);
4550 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4551 h1 = create.out.file.handle;
4553 torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_BATCH, ret, done,
4554 "Oplock level is not SMB2_OPLOCK_LEVEL_BATCH\n");
4556 ZERO_STRUCT(create);
4557 create.in.desired_access = SEC_RIGHTS_FILE_READ;
4558 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4559 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4560 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4561 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4562 create.in.fname = sname;
4563 create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
4565 status = smb2_create(tree, tctx, &create);
4566 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4567 h2 = create.out.file.handle;
4569 torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_NONE, ret, done,
4570 "Oplock level is not SMB2_OPLOCK_LEVEL_NONE\n");
4572 torture_wait_for_oplock_break(tctx);
4573 if (break_info.count != 1) {
4574 torture_warning(tctx, "Stream open didn't cause oplock break\n");
4578 if (!smb2_util_handle_empty(h1)) {
4579 smb2_util_close(tree, h1);
4581 if (!smb2_util_handle_empty(h2)) {
4582 smb2_util_close(tree, h2);
4584 smb2_util_unlink(tree, fname);
4589 * 1) create testfile with stream
4590 * 2) 1st client opens stream r/w with batch oplock -> batch oplock granted
4591 * 3) 2nd client opens stream r/o with batch oplock
4593 * Verify 3) does trigger an oplock break
4595 static bool test_smb2_kernel_oplocks6(struct torture_context *tctx,
4596 struct smb2_tree *tree,
4597 struct smb2_tree *tree2)
4599 const char *fname = "test_kernel_oplock6.dat";
4600 const char *sname = "test_kernel_oplock6.dat:foo";
4603 struct smb2_create create;
4604 struct smb2_handle h1 = {{0}}, h2 = {{0}};
4606 smb2_util_unlink(tree, fname);
4607 status = torture_smb2_testfile(tree, fname, &h1);
4608 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4609 "Error creating testfile\n");
4610 smb2_util_close(tree, h1);
4613 tree->session->transport->oplock.handler = torture_oplock_handler;
4614 tree->session->transport->oplock.private_data = tree;
4615 ZERO_STRUCT(break_info);
4618 ZERO_STRUCT(create);
4619 create.in.desired_access = SEC_RIGHTS_FILE_READ;
4620 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4621 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4622 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4623 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4624 create.in.fname = sname;
4626 status = smb2_create(tree, tctx, &create);
4627 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4628 h1 = create.out.file.handle;
4629 smb2_util_close(tree, h1);
4633 ZERO_STRUCT(create);
4634 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4635 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4636 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4637 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4638 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4639 create.in.fname = fname;
4640 create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
4642 status = smb2_create(tree, tctx, &create);
4643 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4644 h1 = create.out.file.handle;
4646 torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done,
4647 "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n");
4650 ZERO_STRUCT(create);
4651 create.in.desired_access = SEC_RIGHTS_FILE_READ;
4652 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4653 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4654 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4655 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4656 create.in.fname = fname;
4658 status = smb2_create(tree2, tctx, &create);
4659 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
4660 h2 = create.out.file.handle;
4662 torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_NONE, ret, done,
4663 "Oplock level is not SMB2_OPLOCK_LEVEL_NONE\n");
4665 torture_wait_for_oplock_break(tctx);
4666 torture_assert_goto(tctx, break_info.count == 1, ret, done, "Expected 1 oplock break\n");
4669 if (!smb2_util_handle_empty(h1)) {
4670 smb2_util_close(tree, h1);
4672 if (!smb2_util_handle_empty(h2)) {
4673 smb2_util_close(tree, h2);
4675 smb2_util_unlink(tree, fname);
4680 * Recreate regression test from bug:
4682 * https://bugzilla.samba.org/show_bug.cgi?id=13058
4684 * 1. smbd-1 opens the file and sets the oplock
4685 * 2. smbd-2 tries to open the file. open() fails(EAGAIN) and open is deferred.
4686 * 3. smbd-1 sends oplock break request to the client.
4687 * 4. smbd-1 closes the file.
4688 * 5. smbd-1 opens the file and sets the oplock.
4689 * 6. smbd-2 calls defer_open_done(), and should re-break the oplock.
4692 static bool test_smb2_kernel_oplocks7(struct torture_context *tctx,
4693 struct smb2_tree *tree,
4694 struct smb2_tree *tree2)
4696 const char *fname = "test_kernel_oplock7.dat";
4699 struct smb2_create create;
4700 struct smb2_handle h1 = {{0}}, h2 = {{0}};
4701 struct smb2_create create_2;
4702 struct smb2_create io;
4703 struct smb2_request *req;
4705 smb2_util_unlink(tree, fname);
4706 status = torture_smb2_testfile(tree, fname, &h1);
4707 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4708 "Error creating testfile\n");
4709 smb2_util_close(tree, h1);
4712 /* Close the open file on break. */
4713 tree->session->transport->oplock.handler = torture_oplock_handler_close;
4714 tree->session->transport->oplock.private_data = tree;
4715 ZERO_STRUCT(break_info);
4717 /* 1 - open file with oplock */
4718 ZERO_STRUCT(create);
4719 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
4720 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4721 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4722 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4723 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4724 create.in.fname = fname;
4725 create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
4727 status = smb2_create(tree, tctx, &create);
4728 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4729 "Error opening the file\n");
4730 CHECK_VAL(create.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
4732 /* 2 - open file to break oplock */
4733 ZERO_STRUCT(create_2);
4734 create_2.in.desired_access = SEC_RIGHTS_FILE_ALL;
4735 create_2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4736 create_2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4737 create_2.in.create_disposition = NTCREATEX_DISP_OPEN;
4738 create_2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4739 create_2.in.fname = fname;
4740 create_2.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
4742 /* Open on tree2 - should cause a break on tree */
4743 req = smb2_create_send(tree2, &create_2);
4744 torture_assert(tctx, req != NULL, "smb2_create_send");
4746 /* The oplock break handler should close the file. */
4748 torture_wait_for_oplock_break(tctx);
4750 tree->session->transport->oplock.handler = torture_oplock_handler;
4753 * 5 - re-open on tree. NB. There is a race here
4754 * depending on which smbd goes first. We either get
4755 * an oplock level of SMB2_OPLOCK_LEVEL_EXCLUSIVE if
4756 * the close and re-open on tree is processed first, or
4757 * SMB2_OPLOCK_LEVEL_NONE if the pending create on
4758 * tree2 is processed first.
4760 status = smb2_create(tree, tctx, &create);
4761 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4762 "Error opening the file\n");
4764 h1 = create.out.file.handle;
4765 if (create.out.oplock_level != SMB2_OPLOCK_LEVEL_EXCLUSIVE &&
4766 create.out.oplock_level != SMB2_OPLOCK_LEVEL_NONE) {
4767 torture_result(tctx,
4769 "(%s): wrong value for oplock got 0x%x\n",
4771 (unsigned int)create.out.oplock_level);
4777 /* 6 - retrieve the second open. */
4778 status = smb2_create_recv(req, tctx, &io);
4779 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4780 "Error opening the file\n");
4781 h2 = io.out.file.handle;
4782 CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
4785 if (!smb2_util_handle_empty(h1)) {
4786 smb2_util_close(tree, h1);
4788 if (!smb2_util_handle_empty(h2)) {
4789 smb2_util_close(tree2, h2);
4791 smb2_util_unlink(tree, fname);
4795 #if HAVE_KERNEL_OPLOCKS_LINUX
4798 #define F_SETLEASE 1024
4801 #ifndef RT_SIGNAL_LEASE
4802 #define RT_SIGNAL_LEASE (SIGRTMIN+1)
4809 static int got_break;
4815 static void got_rt_break(int sig)
4821 * Child process function.
4824 static int do_child_process(int pipefd, const char *name)
4829 struct sigaction act;
4831 /* Set up a signal handler for RT_SIGNAL_LEASE. */
4833 act.sa_handler = got_rt_break;
4834 ret = sigaction(RT_SIGNAL_LEASE, &act, NULL);
4838 /* Open the passed in file and get a kernel oplock. */
4839 fd = open(name, O_RDWR, 0666);
4844 ret = fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE);
4849 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
4854 /* Tell the parent we're ready. */
4855 ret = sys_write(pipefd, &c, 1);
4860 /* Wait for RT_SIGNAL_LEASE. */
4862 if (ret != -1 || errno != EINTR) {
4866 if (got_break != 1) {
4870 /* Force the server to wait for 3 seconds. */
4873 /* Remove our lease. */
4874 ret = fcntl(fd, F_SETLEASE, F_UNLCK);
4888 static bool wait_for_child_oplock(struct torture_context *tctx,
4889 const char *localdir,
4895 char *name = talloc_asprintf(tctx,
4900 torture_assert(tctx, name != NULL, "talloc failed");
4903 torture_assert(tctx, ret != -1, "pipe failed");
4906 torture_assert(tctx, pid != (pid_t)-1, "fork failed");
4908 if (pid != (pid_t)0) {
4912 ret = sys_read(fds[0], &c, 1);
4913 torture_assert(tctx, ret == 1, "read failed");
4917 /* Child process. */
4918 ret = do_child_process(fds[1], name);
4923 static bool wait_for_child_oplock(struct torture_context *tctx,
4924 const char *localdir,
4932 * Deal with a non-smbd process holding a kernel oplock.
4935 static bool test_smb2_kernel_oplocks8(struct torture_context *tctx,
4936 struct smb2_tree *tree)
4938 const char *fname = "test_kernel_oplock8.dat";
4939 const char *fname1 = "tmp_test_kernel_oplock8.dat";
4942 struct smb2_create io;
4943 struct smb2_request *req = NULL;
4944 struct smb2_handle h1 = {{0}};
4945 struct smb2_handle h2 = {{0}};
4946 const char *localdir = torture_setting_string(tctx, "localdir", NULL);
4950 #ifndef HAVE_KERNEL_OPLOCKS_LINUX
4951 torture_skip(tctx, "Need kernel oplocks for test");
4954 if (localdir == NULL) {
4955 torture_skip(tctx, "Need localdir for test");
4958 smb2_util_unlink(tree, fname);
4959 smb2_util_unlink(tree, fname1);
4960 status = torture_smb2_testfile(tree, fname, &h1);
4961 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4962 "Error creating testfile\n");
4963 smb2_util_close(tree, h1);
4966 /* Take the oplock locally in a sub-process. */
4967 ret = wait_for_child_oplock(tctx, localdir, fname);
4968 torture_assert_goto(tctx, ret = true, ret, done,
4969 "Wait for child process failed.\n");
4972 * Now try and open. This should block for 3 seconds.
4973 * while the child process is still alive.
4977 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
4978 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4979 io.in.create_disposition = NTCREATEX_DISP_OPEN;
4980 io.in.share_access =
4981 NTCREATEX_SHARE_ACCESS_DELETE|
4982 NTCREATEX_SHARE_ACCESS_READ|
4983 NTCREATEX_SHARE_ACCESS_WRITE;
4984 io.in.create_options = 0;
4985 io.in.fname = fname;
4987 req = smb2_create_send(tree, &io);
4988 torture_assert(tctx, req != NULL, "smb2_create_send");
4990 /* Ensure while the open is blocked the smbd is
4991 still serving other requests. */
4992 io.in.fname = fname1;
4993 io.in.create_disposition = NTCREATEX_DISP_CREATE;
4995 /* Time the start -> end of the request. */
4997 status = smb2_create(tree, tctx, &io);
5000 /* Should succeed. */
5001 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5002 "Error opening the second file\n");
5003 h1 = io.out.file.handle;
5005 /* in less than 2 seconds. Otherwise the server blocks. */
5006 torture_assert(tctx, end - start < 2, "server was blocked !");
5008 /* Pick up the return for the initial blocking open. */
5009 status = smb2_create_recv(req, tctx, &io);
5011 /* Which should also have succeeded. */
5012 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5013 "Error opening the file\n");
5014 h2 = io.out.file.handle;
5017 if (!smb2_util_handle_empty(h1)) {
5018 smb2_util_close(tree, h1);
5020 if (!smb2_util_handle_empty(h2)) {
5021 smb2_util_close(tree, h2);
5023 smb2_util_unlink(tree, fname);
5024 smb2_util_unlink(tree, fname1);
5028 struct torture_suite *torture_smb2_kernel_oplocks_init(TALLOC_CTX *ctx)
5030 struct torture_suite *suite =
5031 torture_suite_create(ctx, "kernel-oplocks");
5033 torture_suite_add_1smb2_test(suite, "kernel_oplocks1", test_smb2_kernel_oplocks1);
5034 torture_suite_add_1smb2_test(suite, "kernel_oplocks2", test_smb2_kernel_oplocks2);
5035 torture_suite_add_2smb2_test(suite, "kernel_oplocks3", test_smb2_kernel_oplocks3);
5036 torture_suite_add_1smb2_test(suite, "kernel_oplocks4", test_smb2_kernel_oplocks4);
5037 torture_suite_add_1smb2_test(suite, "kernel_oplocks5", test_smb2_kernel_oplocks5);
5038 torture_suite_add_2smb2_test(suite, "kernel_oplocks6", test_smb2_kernel_oplocks6);
5039 torture_suite_add_2smb2_test(suite, "kernel_oplocks7", test_smb2_kernel_oplocks7);
5040 torture_suite_add_1smb2_test(suite, "kernel_oplocks8", test_smb2_kernel_oplocks8);
5042 suite->description = talloc_strdup(suite, "SMB2-KERNEL-OPLOCK tests");