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 #define CHECK_RANGE(v, min, max) do { \
40 if ((v) < (min) || (v) > (max)) { \
41 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s " \
42 "got %d - should be between %d and %d\n", \
43 __location__, #v, (int)v, (int)min, (int)max); \
47 #define CHECK_STRMATCH(v, correct) do { \
48 if (!v || strstr((v),(correct)) == NULL) { \
49 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s "\
50 "got '%s' - should be '%s'\n", \
51 __location__, #v, v?v:"NULL", correct); \
55 #define CHECK_VAL(v, correct) do { \
56 if ((v) != (correct)) { \
57 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s " \
58 "got 0x%x - should be 0x%x\n", \
59 __location__, #v, (int)v, (int)correct); \
63 #define BASEDIR "oplock_test"
66 struct smb2_handle handle;
71 NTSTATUS failure_status;
74 static void torture_oplock_break_callback(struct smb2_request *req)
80 status = smb2_break_recv(req, &break_info.br);
81 if (!NT_STATUS_IS_OK(status)) {
82 break_info.failures++;
83 break_info.failure_status = status;
89 /* A general oplock break notification handler. This should be used when a
90 * test expects to break from batch or exclusive to a lower level. */
91 static bool torture_oplock_handler(struct smb2_transport *transport,
92 const struct smb2_handle *handle,
96 struct smb2_tree *tree = private_data;
98 struct smb2_request *req;
99 ZERO_STRUCT(break_info.br);
101 break_info.handle = *handle;
102 break_info.level = level;
106 case SMB2_OPLOCK_LEVEL_II:
109 case SMB2_OPLOCK_LEVEL_NONE:
114 break_info.failures++;
116 printf("Acking to %s [0x%02X] in oplock handler\n", name, level);
118 break_info.br.in.file.handle = *handle;
119 break_info.br.in.oplock_level = level;
120 break_info.br.in.reserved = 0;
121 break_info.br.in.reserved2 = 0;
123 req = smb2_break_send(tree, &break_info.br);
124 req->async.fn = torture_oplock_break_callback;
125 req->async.private_data = NULL;
130 A handler function for oplock break notifications. Send a break to none
133 static bool torture_oplock_handler_ack_to_none(struct smb2_transport *transport,
134 const struct smb2_handle *handle,
138 struct smb2_tree *tree = private_data;
139 struct smb2_request *req;
141 break_info.handle = *handle;
142 break_info.level = level;
145 printf("Acking to none in oplock handler\n");
147 ZERO_STRUCT(break_info.br);
148 break_info.br.in.file.handle = *handle;
149 break_info.br.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
150 break_info.br.in.reserved = 0;
151 break_info.br.in.reserved2 = 0;
153 req = smb2_break_send(tree, &break_info.br);
154 req->async.fn = torture_oplock_break_callback;
155 req->async.private_data = NULL;
161 A handler function for oplock break notifications. Break from level II to
162 none. SMB2 requires that the client does not send an oplock break request to
163 the server in this case.
165 static bool torture_oplock_handler_level2_to_none(
166 struct smb2_transport *transport,
167 const struct smb2_handle *handle,
171 break_info.handle = *handle;
172 break_info.level = level;
175 printf("Break from level II to none in oplock handler\n");
180 /* A handler function for oplock break notifications. This should be used when
181 * test expects two break notifications, first to level II, then to none. */
182 static bool torture_oplock_handler_two_notifications(
183 struct smb2_transport *transport,
184 const struct smb2_handle *handle,
188 struct smb2_tree *tree = private_data;
190 struct smb2_request *req;
191 ZERO_STRUCT(break_info.br);
193 break_info.handle = *handle;
194 break_info.level = level;
198 case SMB2_OPLOCK_LEVEL_II:
201 case SMB2_OPLOCK_LEVEL_NONE:
206 break_info.failures++;
208 printf("Breaking to %s [0x%02X] in oplock handler\n", name, level);
210 if (level == SMB2_OPLOCK_LEVEL_NONE)
213 break_info.br.in.file.handle = *handle;
214 break_info.br.in.oplock_level = level;
215 break_info.br.in.reserved = 0;
216 break_info.br.in.reserved2 = 0;
218 req = smb2_break_send(tree, &break_info.br);
219 req->async.fn = torture_oplock_break_callback;
220 req->async.private_data = NULL;
223 static void torture_oplock_handler_close_recv(struct smb2_request *req)
225 if (!smb2_request_receive(req)) {
226 printf("close failed in oplock_handler_close\n");
227 break_info.failures++;
232 a handler function for oplock break requests - close the file
234 static bool torture_oplock_handler_close(struct smb2_transport *transport,
235 const struct smb2_handle *handle,
239 struct smb2_close io;
240 struct smb2_tree *tree = private_data;
241 struct smb2_request *req;
243 break_info.handle = *handle;
244 break_info.level = level;
248 io.in.file.handle = *handle;
249 io.in.flags = RAW_CLOSE_SMB2;
250 req = smb2_close_send(tree, &io);
252 printf("failed to send close in oplock_handler_close\n");
256 req->async.fn = torture_oplock_handler_close_recv;
257 req->async.private_data = NULL;
263 a handler function for oplock break requests. Let it timeout
265 static bool torture_oplock_handler_timeout(struct smb2_transport *transport,
266 const struct smb2_handle *handle,
270 break_info.handle = *handle;
271 break_info.level = level;
274 printf("Let oplock break timeout\n");
278 static bool open_smb2_connection_no_level2_oplocks(struct torture_context *tctx,
279 struct smb2_tree **tree)
282 const char *host = torture_setting_string(tctx, "host", NULL);
283 const char *share = torture_setting_string(tctx, "share", NULL);
284 struct cli_credentials *credentials = cmdline_credentials;
285 struct smbcli_options options;
287 lpcfg_smbcli_options(tctx->lp_ctx, &options);
288 options.use_level2_oplocks = false;
290 status = smb2_connect(tctx, host,
291 lpcfg_smb_ports(tctx->lp_ctx), share,
292 lpcfg_resolve_context(tctx->lp_ctx),
293 credentials, tree, tctx->ev, &options,
294 lpcfg_socket_options(tctx->lp_ctx),
295 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
296 if (!NT_STATUS_IS_OK(status)) {
297 torture_comment(tctx, "Failed to connect to SMB2 share "
298 "\\\\%s\\%s - %s\n", host, share,
306 Timer handler function notifies the registering function that time is up
308 static void timeout_cb(struct tevent_context *ev,
309 struct tevent_timer *te,
310 struct timeval current_time,
313 bool *timesup = (bool *)private_data;
319 Wait a short period of time to receive a single oplock break request
321 static void torture_wait_for_oplock_break(struct torture_context *tctx)
323 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
324 struct tevent_timer *te = NULL;
326 bool timesup = false;
327 int old_count = break_info.count;
329 /* Wait .1 seconds for an oplock break */
330 ne = tevent_timeval_current_ofs(0, 100000);
332 if ((te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, ×up))
335 torture_comment(tctx, "Failed to wait for an oplock break. "
336 "test results may not be accurate.");
340 while (!timesup && break_info.count < old_count + 1) {
341 if (tevent_loop_once(tctx->ev) != 0) {
342 torture_comment(tctx, "Failed to wait for an oplock "
343 "break. test results may not be "
350 /* We don't know if the timed event fired and was freed, we received
351 * our oplock break, or some other event triggered the loop. Thus,
352 * we create a tmp_ctx to be able to safely free/remove the timed
353 * event in all 3 cases. */
354 talloc_free(tmp_ctx);
359 static bool test_smb2_oplock_exclusive1(struct torture_context *tctx,
360 struct smb2_tree *tree1,
361 struct smb2_tree *tree2)
363 const char *fname = BASEDIR "\\test_exclusive1.dat";
367 struct smb2_handle h1;
368 struct smb2_handle h;
370 status = torture_smb2_testdir(tree1, BASEDIR, &h);
371 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
374 smb2_util_unlink(tree1, fname);
376 tree1->session->transport->oplock.handler = torture_oplock_handler;
377 tree1->session->transport->oplock.private_data = tree1;
382 ZERO_STRUCT(io.smb2);
383 io.generic.level = RAW_OPEN_SMB2;
384 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
385 io.smb2.in.alloc_size = 0;
386 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
387 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
388 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
389 io.smb2.in.create_options = 0;
390 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
391 io.smb2.in.security_flags = 0;
392 io.smb2.in.fname = fname;
394 torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive "
395 "oplock (share mode: none)\n");
396 ZERO_STRUCT(break_info);
397 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
399 status = smb2_create(tree1, tctx, &(io.smb2));
400 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
401 h1 = io.smb2.out.file.handle;
402 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
404 torture_comment(tctx, "a 2nd open should not cause a break\n");
405 status = smb2_create(tree2, tctx, &(io.smb2));
406 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
408 torture_wait_for_oplock_break(tctx);
409 CHECK_VAL(break_info.count, 0);
410 CHECK_VAL(break_info.failures, 0);
412 torture_comment(tctx, "unlink it - should also be no break\n");
413 status = smb2_util_unlink(tree2, fname);
414 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
416 torture_wait_for_oplock_break(tctx);
417 CHECK_VAL(break_info.count, 0);
418 CHECK_VAL(break_info.failures, 0);
420 smb2_util_close(tree1, h1);
421 smb2_util_close(tree1, h);
423 smb2_deltree(tree1, BASEDIR);
427 static bool test_smb2_oplock_exclusive2(struct torture_context *tctx,
428 struct smb2_tree *tree1,
429 struct smb2_tree *tree2)
431 const char *fname = BASEDIR "\\test_exclusive2.dat";
435 struct smb2_handle h, h1, h2;
437 status = torture_smb2_testdir(tree1, BASEDIR, &h);
438 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
441 smb2_util_unlink(tree1, fname);
443 tree1->session->transport->oplock.handler = torture_oplock_handler;
444 tree1->session->transport->oplock.private_data = tree1;
449 ZERO_STRUCT(io.smb2);
450 io.generic.level = RAW_OPEN_SMB2;
451 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
452 io.smb2.in.alloc_size = 0;
453 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
454 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
455 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
456 io.smb2.in.create_options = 0;
457 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
458 io.smb2.in.security_flags = 0;
459 io.smb2.in.fname = fname;
461 torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive "
462 "oplock (share mode: all)\n");
463 ZERO_STRUCT(break_info);
464 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
465 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
466 NTCREATEX_SHARE_ACCESS_WRITE|
467 NTCREATEX_SHARE_ACCESS_DELETE;
468 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
470 status = smb2_create(tree1, tctx, &(io.smb2));
471 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
472 h1 = io.smb2.out.file.handle;
473 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
475 torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
476 status = smb2_create(tree2, tctx, &(io.smb2));
477 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
478 h2 = io.smb2.out.file.handle;
479 torture_wait_for_oplock_break(tctx);
480 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
481 CHECK_VAL(break_info.count, 1);
482 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
483 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
484 CHECK_VAL(break_info.failures, 0);
485 ZERO_STRUCT(break_info);
487 /* now we have 2 level II oplocks... */
488 torture_comment(tctx, "try to unlink it - should cause a break\n");
489 status = smb2_util_unlink(tree2, fname);
490 torture_assert_ntstatus_ok(tctx, status, "Error unlinking the file");
491 torture_wait_for_oplock_break(tctx);
492 CHECK_VAL(break_info.count, 0);
493 CHECK_VAL(break_info.failures, 0);
495 torture_comment(tctx, "close both handles\n");
496 smb2_util_close(tree1, h1);
497 smb2_util_close(tree1, h2);
498 smb2_util_close(tree1, h);
500 smb2_deltree(tree1, BASEDIR);
504 static bool test_smb2_oplock_exclusive3(struct torture_context *tctx,
505 struct smb2_tree *tree1,
506 struct smb2_tree *tree2)
508 const char *fname = BASEDIR "\\test_exclusive3.dat";
512 union smb_setfileinfo sfi;
513 struct smb2_handle h, h1;
515 status = torture_smb2_testdir(tree1, BASEDIR, &h);
516 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
519 smb2_util_unlink(tree1, fname);
521 tree1->session->transport->oplock.handler = torture_oplock_handler;
522 tree1->session->transport->oplock.private_data = tree1;
527 ZERO_STRUCT(io.smb2);
528 io.generic.level = RAW_OPEN_SMB2;
529 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
530 io.smb2.in.alloc_size = 0;
531 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
532 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
533 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
534 io.smb2.in.create_options = 0;
535 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
536 io.smb2.in.security_flags = 0;
537 io.smb2.in.fname = fname;
539 torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive "
540 "oplock (share mode: none)\n");
542 ZERO_STRUCT(break_info);
543 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
544 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
546 status = smb2_create(tree1, tctx, &(io.smb2));
547 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
548 h1 = io.smb2.out.file.handle;
549 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
551 torture_comment(tctx, "setpathinfo EOF should trigger a break to "
554 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
555 sfi.generic.in.file.path = fname;
556 sfi.end_of_file_info.in.size = 100;
558 status = smb2_composite_setpathinfo(tree2, &sfi);
560 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
562 torture_wait_for_oplock_break(tctx);
563 CHECK_VAL(break_info.count, 0);
564 CHECK_VAL(break_info.failures, 0);
565 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
567 smb2_util_close(tree1, h1);
568 smb2_util_close(tree1, h);
570 smb2_deltree(tree1, BASEDIR);
574 static bool test_smb2_oplock_exclusive4(struct torture_context *tctx,
575 struct smb2_tree *tree1,
576 struct smb2_tree *tree2)
578 const char *fname = BASEDIR "\\test_exclusive4.dat";
582 struct smb2_handle h, h1, h2;
584 status = torture_smb2_testdir(tree1, BASEDIR, &h);
585 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
588 smb2_util_unlink(tree1, fname);
590 tree1->session->transport->oplock.handler = torture_oplock_handler;
591 tree1->session->transport->oplock.private_data = tree1;
596 ZERO_STRUCT(io.smb2);
597 io.generic.level = RAW_OPEN_SMB2;
598 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
599 io.smb2.in.alloc_size = 0;
600 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
601 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
602 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
603 io.smb2.in.create_options = 0;
604 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
605 io.smb2.in.security_flags = 0;
606 io.smb2.in.fname = fname;
608 torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
609 ZERO_STRUCT(break_info);
611 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
612 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
613 status = smb2_create(tree1, tctx, &(io.smb2));
614 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
615 h1 = io.smb2.out.file.handle;
616 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
618 ZERO_STRUCT(break_info);
619 torture_comment(tctx, "second open with attributes only shouldn't "
620 "cause oplock break\n");
622 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
623 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
624 SEC_FILE_WRITE_ATTRIBUTE |
626 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
627 status = smb2_create(tree2, tctx, &(io.smb2));
628 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
629 h2 = io.smb2.out.file.handle;
630 CHECK_VAL(io.smb2.out.oplock_level, NO_OPLOCK_RETURN);
631 torture_wait_for_oplock_break(tctx);
632 CHECK_VAL(break_info.count, 0);
633 CHECK_VAL(break_info.failures, 0);
635 smb2_util_close(tree1, h1);
636 smb2_util_close(tree2, h2);
637 smb2_util_close(tree1, h);
639 smb2_deltree(tree1, BASEDIR);
643 static bool test_smb2_oplock_exclusive5(struct torture_context *tctx,
644 struct smb2_tree *tree1,
645 struct smb2_tree *tree2)
647 const char *fname = BASEDIR "\\test_exclusive5.dat";
651 struct smb2_handle h, h1, h2;
653 status = torture_smb2_testdir(tree1, BASEDIR, &h);
654 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
657 smb2_util_unlink(tree1, fname);
659 tree1->session->transport->oplock.handler = torture_oplock_handler;
660 tree1->session->transport->oplock.private_data = tree1;
662 tree2->session->transport->oplock.handler = torture_oplock_handler;
663 tree2->session->transport->oplock.private_data = tree2;
668 ZERO_STRUCT(io.smb2);
669 io.generic.level = RAW_OPEN_SMB2;
670 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
671 io.smb2.in.alloc_size = 0;
672 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
673 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
674 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
675 io.smb2.in.create_options = 0;
676 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
677 io.smb2.in.security_flags = 0;
678 io.smb2.in.fname = fname;
680 torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
681 ZERO_STRUCT(break_info);
683 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
684 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
685 NTCREATEX_SHARE_ACCESS_WRITE|
686 NTCREATEX_SHARE_ACCESS_DELETE;
687 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
688 status = smb2_create(tree1, tctx, &(io.smb2));
689 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
690 h1 = io.smb2.out.file.handle;
691 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
693 ZERO_STRUCT(break_info);
695 torture_comment(tctx, "second open with attributes only and "
696 "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
699 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
700 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
701 SEC_FILE_WRITE_ATTRIBUTE |
703 io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
704 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
705 status = smb2_create(tree2, tctx, &(io.smb2));
706 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
707 h2 = io.smb2.out.file.handle;
708 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
709 torture_wait_for_oplock_break(tctx);
710 CHECK_VAL(break_info.count, 1);
711 CHECK_VAL(break_info.failures, 0);
713 smb2_util_close(tree1, h1);
714 smb2_util_close(tree2, h2);
715 smb2_util_close(tree1, h);
717 smb2_deltree(tree1, BASEDIR);
721 static bool test_smb2_oplock_exclusive6(struct torture_context *tctx,
722 struct smb2_tree *tree1,
723 struct smb2_tree *tree2)
725 const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
726 const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
730 union smb_setfileinfo sinfo;
731 struct smb2_close closeio;
732 struct smb2_handle h, h1;
734 status = torture_smb2_testdir(tree1, BASEDIR, &h);
735 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
738 smb2_util_unlink(tree1, fname1);
739 smb2_util_unlink(tree2, fname2);
741 tree1->session->transport->oplock.handler = torture_oplock_handler;
742 tree1->session->transport->oplock.private_data = tree1;
747 ZERO_STRUCT(io.smb2);
748 io.generic.level = RAW_OPEN_SMB2;
749 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
750 io.smb2.in.alloc_size = 0;
751 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
752 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
753 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
754 io.smb2.in.create_options = 0;
755 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
756 io.smb2.in.security_flags = 0;
757 io.smb2.in.fname = fname1;
759 torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
760 "oplock (share mode: none)\n");
761 ZERO_STRUCT(break_info);
762 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
763 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
765 status = smb2_create(tree1, tctx, &(io.smb2));
766 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
767 h1 = io.smb2.out.file.handle;
768 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
770 torture_comment(tctx, "rename with the parent directory handle open "
771 "for DELETE should not generate a break but get "
772 "a sharing violation\n");
774 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
775 sinfo.rename_information.in.file.handle = h1;
776 sinfo.rename_information.in.overwrite = true;
777 sinfo.rename_information.in.new_name = fname2;
778 status = smb2_setinfo_file(tree1, &sinfo);
780 torture_comment(tctx, "trying rename while parent handle open for delete.\n");
781 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
783 torture_wait_for_oplock_break(tctx);
784 CHECK_VAL(break_info.count, 0);
785 CHECK_VAL(break_info.failures, 0);
787 /* Close the parent directory handle. */
788 ZERO_STRUCT(closeio);
789 closeio.in.file.handle = h;
790 status = smb2_close(tree1, &closeio);
791 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
794 /* Re-open without DELETE access. */
796 io.smb2.in.oplock_level = 0;
797 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL & (~SEC_STD_DELETE);
798 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
799 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
800 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
801 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
802 io.smb2.in.fname = BASEDIR;
804 status = smb2_create(tree1, tctx, &(io.smb2));
805 torture_assert_ntstatus_ok(tctx, status, "Error opening the base directory");
807 torture_comment(tctx, "rename with the parent directory handle open "
808 "without DELETE should succeed without a break\n");
810 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
811 sinfo.rename_information.in.file.handle = h1;
812 sinfo.rename_information.in.overwrite = true;
813 sinfo.rename_information.in.new_name = fname2;
814 status = smb2_setinfo_file(tree1, &sinfo);
816 torture_comment(tctx, "trying rename while parent handle open without delete\n");
817 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
819 torture_wait_for_oplock_break(tctx);
820 CHECK_VAL(break_info.count, 0);
821 CHECK_VAL(break_info.failures, 0);
823 smb2_util_close(tree1, h1);
824 smb2_util_close(tree1, h);
826 smb2_deltree(tree1, BASEDIR);
830 static bool test_smb2_oplock_exclusive9(struct torture_context *tctx,
831 struct smb2_tree *tree1,
832 struct smb2_tree *tree2)
834 const char *fname = BASEDIR "\\test_exclusive9.dat";
838 struct smb2_handle h1, h2;
842 uint32_t create_disposition;
843 uint32_t break_level;
845 { NTCREATEX_DISP_SUPERSEDE, SMB2_OPLOCK_LEVEL_NONE },
846 { NTCREATEX_DISP_OPEN, SMB2_OPLOCK_LEVEL_II },
847 { NTCREATEX_DISP_OVERWRITE_IF, SMB2_OPLOCK_LEVEL_NONE },
848 { NTCREATEX_DISP_OPEN_IF, SMB2_OPLOCK_LEVEL_II },
852 status = torture_smb2_testdir(tree1, BASEDIR, &h1);
853 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
854 smb2_util_close(tree1, h1);
857 smb2_util_unlink(tree1, fname);
859 tree1->session->transport->oplock.handler = torture_oplock_handler;
860 tree1->session->transport->oplock.private_data = tree1;
865 ZERO_STRUCT(io.smb2);
866 io.generic.level = RAW_OPEN_SMB2;
867 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
868 io.smb2.in.alloc_size = 0;
869 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
870 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
871 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
872 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
873 io.smb2.in.create_options = 0;
874 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
875 io.smb2.in.security_flags = 0;
876 io.smb2.in.fname = fname;
878 for (i=0; i<ARRAY_SIZE(levels); i++) {
880 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
881 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
883 status = smb2_create(tree1, tctx, &(io.smb2));
884 torture_assert_ntstatus_ok(tctx, status,
885 "Error opening the file");
886 h1 = io.smb2.out.file.handle;
887 CHECK_VAL(io.smb2.out.oplock_level,
888 SMB2_OPLOCK_LEVEL_EXCLUSIVE);
890 ZERO_STRUCT(break_info);
892 io.smb2.in.create_disposition = levels[i].create_disposition;
893 status = smb2_create(tree2, tctx, &(io.smb2));
894 torture_assert_ntstatus_ok(tctx, status,
895 "Error opening the file");
896 h2 = io.smb2.out.file.handle;
897 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
899 CHECK_VAL(break_info.count, 1);
900 CHECK_VAL(break_info.level, levels[i].break_level);
901 CHECK_VAL(break_info.failures, 0);
903 smb2_util_close(tree2, h2);
904 smb2_util_close(tree1, h1);
907 smb2_deltree(tree1, BASEDIR);
911 static bool test_smb2_oplock_batch1(struct torture_context *tctx,
912 struct smb2_tree *tree1,
913 struct smb2_tree *tree2)
915 const char *fname = BASEDIR "\\test_batch1.dat";
919 struct smb2_handle h, h1;
922 status = torture_smb2_testdir(tree1, BASEDIR, &h);
923 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
926 smb2_util_unlink(tree1, fname);
928 tree1->session->transport->oplock.handler = torture_oplock_handler;
929 tree1->session->transport->oplock.private_data = tree1;
934 ZERO_STRUCT(io.smb2);
935 io.generic.level = RAW_OPEN_SMB2;
936 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
937 io.smb2.in.alloc_size = 0;
938 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
939 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
940 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
941 io.smb2.in.create_options = 0;
942 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
943 io.smb2.in.security_flags = 0;
944 io.smb2.in.fname = fname;
947 with a batch oplock we get a break
949 torture_comment(tctx, "BATCH1: open with batch oplock\n");
950 ZERO_STRUCT(break_info);
951 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
952 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
953 status = smb2_create(tree1, tctx, &(io.smb2));
954 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
955 h1 = io.smb2.out.file.handle;
956 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
958 torture_comment(tctx, "unlink should generate a break\n");
959 status = smb2_util_unlink(tree2, fname);
960 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
963 torture_wait_for_oplock_break(tctx);
964 CHECK_VAL(break_info.count, 1);
965 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
966 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
967 CHECK_VAL(break_info.failures, 0);
969 torture_comment(tctx, "2nd unlink should not generate a break\n");
970 ZERO_STRUCT(break_info);
971 status = smb2_util_unlink(tree2, fname);
972 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
975 torture_wait_for_oplock_break(tctx);
976 CHECK_VAL(break_info.count, 0);
978 torture_comment(tctx, "writing should generate a self break to none\n");
979 tree1->session->transport->oplock.handler =
980 torture_oplock_handler_level2_to_none;
981 smb2_util_write(tree1, h1, &c, 0, 1);
983 torture_wait_for_oplock_break(tctx);
985 CHECK_VAL(break_info.count, 1);
986 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
987 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
988 CHECK_VAL(break_info.failures, 0);
990 smb2_util_close(tree1, h1);
991 smb2_util_close(tree1, h);
993 smb2_deltree(tree1, BASEDIR);
997 static bool test_smb2_oplock_batch2(struct torture_context *tctx,
998 struct smb2_tree *tree1,
999 struct smb2_tree *tree2)
1001 const char *fname = BASEDIR "\\test_batch2.dat";
1006 struct smb2_handle h, h1;
1008 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1009 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1012 smb2_util_unlink(tree1, fname);
1014 tree1->session->transport->oplock.handler = torture_oplock_handler;
1015 tree1->session->transport->oplock.private_data = tree1;
1018 base ntcreatex parms
1020 ZERO_STRUCT(io.smb2);
1021 io.generic.level = RAW_OPEN_SMB2;
1022 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1023 io.smb2.in.alloc_size = 0;
1024 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1025 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1026 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1027 io.smb2.in.create_options = 0;
1028 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1029 io.smb2.in.security_flags = 0;
1030 io.smb2.in.fname = fname;
1032 torture_comment(tctx, "BATCH2: open with batch oplock\n");
1033 ZERO_STRUCT(break_info);
1034 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1035 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1036 status = smb2_create(tree1, tctx, &(io.smb2));
1037 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1038 h1 = io.smb2.out.file.handle;
1039 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1041 torture_comment(tctx, "unlink should generate a break, which we ack "
1042 "as break to none\n");
1043 tree1->session->transport->oplock.handler =
1044 torture_oplock_handler_ack_to_none;
1045 tree1->session->transport->oplock.private_data = tree1;
1046 status = smb2_util_unlink(tree2, fname);
1047 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
1048 "Incorrect status");
1050 torture_wait_for_oplock_break(tctx);
1051 CHECK_VAL(break_info.count, 1);
1052 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1053 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
1054 CHECK_VAL(break_info.failures, 0);
1056 torture_comment(tctx, "2nd unlink should not generate a break\n");
1057 ZERO_STRUCT(break_info);
1058 status = smb2_util_unlink(tree2, fname);
1059 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
1060 "Incorrect status");
1062 torture_wait_for_oplock_break(tctx);
1063 CHECK_VAL(break_info.count, 0);
1065 torture_comment(tctx, "writing should not generate a break\n");
1066 smb2_util_write(tree1, h1, &c, 0, 1);
1068 torture_wait_for_oplock_break(tctx);
1069 CHECK_VAL(break_info.count, 0);
1071 smb2_util_close(tree1, h1);
1072 smb2_util_close(tree1, h);
1074 smb2_deltree(tree1, BASEDIR);
1078 static bool test_smb2_oplock_batch3(struct torture_context *tctx,
1079 struct smb2_tree *tree1,
1080 struct smb2_tree *tree2)
1082 const char *fname = BASEDIR "\\test_batch3.dat";
1086 struct smb2_handle h, h1;
1088 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1089 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1092 smb2_util_unlink(tree1, fname);
1093 tree1->session->transport->oplock.handler = torture_oplock_handler;
1094 tree1->session->transport->oplock.private_data = tree1;
1097 base ntcreatex parms
1099 ZERO_STRUCT(io.smb2);
1100 io.generic.level = RAW_OPEN_SMB2;
1101 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1102 io.smb2.in.alloc_size = 0;
1103 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1104 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1105 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1106 io.smb2.in.create_options = 0;
1107 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1108 io.smb2.in.security_flags = 0;
1109 io.smb2.in.fname = fname;
1111 torture_comment(tctx, "BATCH3: if we close on break then the unlink "
1113 ZERO_STRUCT(break_info);
1114 tree1->session->transport->oplock.handler =
1115 torture_oplock_handler_close;
1116 tree1->session->transport->oplock.private_data = tree1;
1118 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1119 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1120 status = smb2_create(tree1, tctx, &(io.smb2));
1121 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1122 h1 = io.smb2.out.file.handle;
1123 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1125 ZERO_STRUCT(break_info);
1126 status = smb2_util_unlink(tree2, fname);
1127 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1129 torture_wait_for_oplock_break(tctx);
1130 CHECK_VAL(break_info.count, 1);
1131 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1132 CHECK_VAL(break_info.level, 1);
1133 CHECK_VAL(break_info.failures, 0);
1135 smb2_util_close(tree1, h1);
1136 smb2_util_close(tree1, h);
1138 smb2_deltree(tree1, BASEDIR);
1142 static bool test_smb2_oplock_batch4(struct torture_context *tctx,
1143 struct smb2_tree *tree1,
1144 struct smb2_tree *tree2)
1146 const char *fname = BASEDIR "\\test_batch4.dat";
1151 struct smb2_handle h, h1;
1153 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1154 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1157 smb2_util_unlink(tree1, fname);
1159 tree1->session->transport->oplock.handler = torture_oplock_handler;
1160 tree1->session->transport->oplock.private_data = tree1;
1163 base ntcreatex parms
1165 ZERO_STRUCT(io.smb2);
1166 io.generic.level = RAW_OPEN_SMB2;
1167 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1168 io.smb2.in.alloc_size = 0;
1169 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1170 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1171 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1172 io.smb2.in.create_options = 0;
1173 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1174 io.smb2.in.security_flags = 0;
1175 io.smb2.in.fname = fname;
1177 torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
1178 ZERO_STRUCT(break_info);
1180 tree1->session->transport->oplock.handler = torture_oplock_handler;
1181 tree1->session->transport->oplock.private_data = tree1;
1183 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1184 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1185 status = smb2_create(tree1, tctx, &(io.smb2));
1186 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1187 h1 = io.smb2.out.file.handle;
1188 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1191 r.in.file.handle = h1;
1194 status = smb2_read(tree1, tree1, &r);
1195 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1196 torture_wait_for_oplock_break(tctx);
1197 CHECK_VAL(break_info.count, 0);
1198 CHECK_VAL(break_info.failures, 0);
1200 smb2_util_close(tree1, h1);
1201 smb2_util_close(tree1, h);
1203 smb2_deltree(tree1, BASEDIR);
1207 static bool test_smb2_oplock_batch5(struct torture_context *tctx,
1208 struct smb2_tree *tree1,
1209 struct smb2_tree *tree2)
1211 const char *fname = BASEDIR "\\test_batch5.dat";
1215 struct smb2_handle h, h1;
1217 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1218 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1221 smb2_util_unlink(tree1, fname);
1223 tree1->session->transport->oplock.handler = torture_oplock_handler;
1224 tree1->session->transport->oplock.private_data = tree1;
1227 base ntcreatex parms
1229 ZERO_STRUCT(io.smb2);
1230 io.generic.level = RAW_OPEN_SMB2;
1231 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1232 io.smb2.in.alloc_size = 0;
1233 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1234 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1235 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1236 io.smb2.in.create_options = 0;
1237 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1238 io.smb2.in.security_flags = 0;
1239 io.smb2.in.fname = fname;
1241 torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1242 ZERO_STRUCT(break_info);
1244 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1245 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1246 status = smb2_create(tree1, tctx, &(io.smb2));
1247 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1248 h1 = io.smb2.out.file.handle;
1249 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1251 ZERO_STRUCT(break_info);
1253 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1254 status = smb2_create(tree2, tctx, &(io.smb2));
1255 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
1256 "Incorrect status");
1258 torture_wait_for_oplock_break(tctx);
1259 CHECK_VAL(break_info.count, 1);
1260 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1261 CHECK_VAL(break_info.level, 1);
1262 CHECK_VAL(break_info.failures, 0);
1264 smb2_util_close(tree1, h1);
1265 smb2_util_close(tree1, h);
1267 smb2_deltree(tree1, BASEDIR);
1271 static bool test_smb2_oplock_batch6(struct torture_context *tctx,
1272 struct smb2_tree *tree1,
1273 struct smb2_tree *tree2)
1275 const char *fname = BASEDIR "\\test_batch6.dat";
1279 struct smb2_handle h, h1, h2;
1282 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1283 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1286 smb2_util_unlink(tree1, fname);
1288 tree1->session->transport->oplock.handler = torture_oplock_handler;
1289 tree1->session->transport->oplock.private_data = tree1;
1292 base ntcreatex parms
1294 ZERO_STRUCT(io.smb2);
1295 io.generic.level = RAW_OPEN_SMB2;
1296 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1297 io.smb2.in.alloc_size = 0;
1298 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1299 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1300 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1301 io.smb2.in.create_options = 0;
1302 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1303 io.smb2.in.security_flags = 0;
1304 io.smb2.in.fname = fname;
1306 torture_comment(tctx, "BATCH6: a 2nd open should give a break to "
1307 "level II if the first open allowed shared read\n");
1308 ZERO_STRUCT(break_info);
1309 tree2->session->transport->oplock.handler = torture_oplock_handler;
1310 tree2->session->transport->oplock.private_data = tree2;
1312 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
1313 SEC_RIGHTS_FILE_WRITE;
1314 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1315 NTCREATEX_SHARE_ACCESS_WRITE;
1316 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1317 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1318 status = smb2_create(tree1, tctx, &(io.smb2));
1319 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1320 h1 = io.smb2.out.file.handle;
1321 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1323 ZERO_STRUCT(break_info);
1325 status = smb2_create(tree2, tctx, &(io.smb2));
1326 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1327 h2 = io.smb2.out.file.handle;
1328 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1330 torture_wait_for_oplock_break(tctx);
1331 CHECK_VAL(break_info.count, 1);
1332 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1333 CHECK_VAL(break_info.level, 1);
1334 CHECK_VAL(break_info.failures, 0);
1335 ZERO_STRUCT(break_info);
1337 torture_comment(tctx, "write should trigger a break to none on both\n");
1338 tree1->session->transport->oplock.handler =
1339 torture_oplock_handler_level2_to_none;
1340 tree2->session->transport->oplock.handler =
1341 torture_oplock_handler_level2_to_none;
1342 smb2_util_write(tree1, h1, &c, 0, 1);
1344 /* We expect two breaks */
1345 torture_wait_for_oplock_break(tctx);
1346 torture_wait_for_oplock_break(tctx);
1348 CHECK_VAL(break_info.count, 2);
1349 CHECK_VAL(break_info.level, 0);
1350 CHECK_VAL(break_info.failures, 0);
1352 smb2_util_close(tree1, h1);
1353 smb2_util_close(tree2, h2);
1354 smb2_util_close(tree1, h);
1356 smb2_deltree(tree1, BASEDIR);
1360 static bool test_smb2_oplock_batch7(struct torture_context *tctx,
1361 struct smb2_tree *tree1,
1362 struct smb2_tree *tree2)
1364 const char *fname = BASEDIR "\\test_batch7.dat";
1368 struct smb2_handle h, h1, h2;
1370 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1371 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1374 smb2_util_unlink(tree1, fname);
1376 tree1->session->transport->oplock.handler = torture_oplock_handler;
1377 tree1->session->transport->oplock.private_data = tree1;
1380 base ntcreatex parms
1382 ZERO_STRUCT(io.smb2);
1383 io.generic.level = RAW_OPEN_SMB2;
1384 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1385 io.smb2.in.alloc_size = 0;
1386 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1387 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1388 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1389 io.smb2.in.create_options = 0;
1390 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1391 io.smb2.in.security_flags = 0;
1392 io.smb2.in.fname = fname;
1394 torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when "
1395 "we close instead of ack\n");
1396 ZERO_STRUCT(break_info);
1397 tree1->session->transport->oplock.handler =
1398 torture_oplock_handler_close;
1399 tree1->session->transport->oplock.private_data = tree1;
1401 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1402 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1403 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1404 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1405 status = smb2_create(tree1, tctx, &(io.smb2));
1406 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1407 h2 = io.smb2.out.file.handle;
1408 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1410 ZERO_STRUCT(break_info);
1412 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1413 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1414 status = smb2_create(tree2, tctx, &(io.smb2));
1415 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1416 h1 = io.smb2.out.file.handle;
1417 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1419 torture_wait_for_oplock_break(tctx);
1420 CHECK_VAL(break_info.count, 1);
1421 CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1422 CHECK_VAL(break_info.level, 1);
1423 CHECK_VAL(break_info.failures, 0);
1425 smb2_util_close(tree2, h1);
1426 smb2_util_close(tree2, h);
1428 smb2_deltree(tree1, BASEDIR);
1432 static bool test_smb2_oplock_batch8(struct torture_context *tctx,
1433 struct smb2_tree *tree1,
1434 struct smb2_tree *tree2)
1436 const char *fname = BASEDIR "\\test_batch8.dat";
1440 struct smb2_handle h, h1, h2;
1442 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1443 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1446 smb2_util_unlink(tree1, fname);
1448 tree1->session->transport->oplock.handler = torture_oplock_handler;
1449 tree1->session->transport->oplock.private_data = tree1;
1452 base ntcreatex parms
1454 ZERO_STRUCT(io.smb2);
1455 io.generic.level = RAW_OPEN_SMB2;
1456 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1457 io.smb2.in.alloc_size = 0;
1458 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1459 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1460 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1461 io.smb2.in.create_options = 0;
1462 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1463 io.smb2.in.security_flags = 0;
1464 io.smb2.in.fname = fname;
1466 torture_comment(tctx, "BATCH8: open with batch oplock\n");
1467 ZERO_STRUCT(break_info);
1469 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1470 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1471 status = smb2_create(tree1, tctx, &(io.smb2));
1472 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1473 h1 = io.smb2.out.file.handle;
1474 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1476 ZERO_STRUCT(break_info);
1477 torture_comment(tctx, "second open with attributes only shouldn't "
1478 "cause oplock break\n");
1480 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1481 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1482 SEC_FILE_WRITE_ATTRIBUTE |
1483 SEC_STD_SYNCHRONIZE;
1484 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1485 status = smb2_create(tree2, tctx, &(io.smb2));
1486 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1487 h2 = io.smb2.out.file.handle;
1488 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1489 torture_wait_for_oplock_break(tctx);
1490 CHECK_VAL(break_info.count, 0);
1491 CHECK_VAL(break_info.failures, 0);
1493 smb2_util_close(tree1, h1);
1494 smb2_util_close(tree2, h2);
1495 smb2_util_close(tree1, h);
1497 smb2_deltree(tree1, BASEDIR);
1501 static bool test_smb2_oplock_batch9(struct torture_context *tctx,
1502 struct smb2_tree *tree1,
1503 struct smb2_tree *tree2)
1505 const char *fname = BASEDIR "\\test_batch9.dat";
1509 struct smb2_handle h, h1, h2;
1512 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1513 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1516 smb2_util_unlink(tree1, fname);
1518 tree1->session->transport->oplock.handler = torture_oplock_handler;
1519 tree1->session->transport->oplock.private_data = tree1;
1522 base ntcreatex parms
1524 ZERO_STRUCT(io.smb2);
1525 io.generic.level = RAW_OPEN_SMB2;
1526 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1527 io.smb2.in.alloc_size = 0;
1528 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1529 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1530 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1531 io.smb2.in.create_options = 0;
1532 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1533 io.smb2.in.security_flags = 0;
1534 io.smb2.in.fname = fname;
1536 torture_comment(tctx, "BATCH9: open with attributes only can create "
1539 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1540 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1541 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1542 SEC_FILE_WRITE_ATTRIBUTE |
1543 SEC_STD_SYNCHRONIZE;
1544 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1545 status = smb2_create(tree1, tctx, &(io.smb2));
1546 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1547 h1 = io.smb2.out.file.handle;
1548 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1550 torture_comment(tctx, "Subsequent normal open should break oplock on "
1551 "attribute only open to level II\n");
1553 ZERO_STRUCT(break_info);
1555 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1556 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1557 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1558 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1559 status = smb2_create(tree2, tctx, &(io.smb2));
1560 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1561 h2 = io.smb2.out.file.handle;
1562 torture_wait_for_oplock_break(tctx);
1563 CHECK_VAL(break_info.count, 1);
1564 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1565 CHECK_VAL(break_info.failures, 0);
1566 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
1567 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1568 smb2_util_close(tree2, h2);
1570 torture_comment(tctx, "third oplocked open should grant level2 without "
1572 ZERO_STRUCT(break_info);
1574 tree2->session->transport->oplock.handler = torture_oplock_handler;
1575 tree2->session->transport->oplock.private_data = tree2;
1577 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1578 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1579 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1580 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1581 status = smb2_create(tree2, tctx, &(io.smb2));
1582 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1583 h2 = io.smb2.out.file.handle;
1584 torture_wait_for_oplock_break(tctx);
1585 CHECK_VAL(break_info.count, 0);
1586 CHECK_VAL(break_info.failures, 0);
1587 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1589 ZERO_STRUCT(break_info);
1591 torture_comment(tctx, "write should trigger a break to none on both\n");
1592 tree1->session->transport->oplock.handler =
1593 torture_oplock_handler_level2_to_none;
1594 tree2->session->transport->oplock.handler =
1595 torture_oplock_handler_level2_to_none;
1596 smb2_util_write(tree2, h2, &c, 0, 1);
1598 /* We expect two breaks */
1599 torture_wait_for_oplock_break(tctx);
1600 torture_wait_for_oplock_break(tctx);
1602 CHECK_VAL(break_info.count, 2);
1603 CHECK_VAL(break_info.level, 0);
1604 CHECK_VAL(break_info.failures, 0);
1606 smb2_util_close(tree1, h1);
1607 smb2_util_close(tree2, h2);
1608 smb2_util_close(tree1, h);
1610 smb2_deltree(tree1, BASEDIR);
1614 static bool test_smb2_oplock_batch10(struct torture_context *tctx,
1615 struct smb2_tree *tree1,
1616 struct smb2_tree *tree2)
1618 const char *fname = BASEDIR "\\test_batch10.dat";
1622 struct smb2_handle h, h1, h2;
1624 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1625 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1628 smb2_util_unlink(tree1, fname);
1630 tree1->session->transport->oplock.handler = torture_oplock_handler;
1631 tree1->session->transport->oplock.private_data = tree1;
1634 base ntcreatex parms
1636 ZERO_STRUCT(io.smb2);
1637 io.generic.level = RAW_OPEN_SMB2;
1638 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1639 io.smb2.in.alloc_size = 0;
1640 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1641 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1642 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1643 io.smb2.in.create_options = 0;
1644 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1645 io.smb2.in.security_flags = 0;
1646 io.smb2.in.fname = fname;
1648 torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock "
1649 "open should grant level2\n");
1650 ZERO_STRUCT(break_info);
1651 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1652 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1653 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1654 NTCREATEX_SHARE_ACCESS_WRITE|
1655 NTCREATEX_SHARE_ACCESS_DELETE;
1656 status = smb2_create(tree1, tctx, &(io.smb2));
1657 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1658 h1 = io.smb2.out.file.handle;
1659 torture_wait_for_oplock_break(tctx);
1660 CHECK_VAL(break_info.count, 0);
1661 CHECK_VAL(break_info.failures, 0);
1662 CHECK_VAL(io.smb2.out.oplock_level, 0);
1664 tree2->session->transport->oplock.handler =
1665 torture_oplock_handler_level2_to_none;
1666 tree2->session->transport->oplock.private_data = tree2;
1668 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1669 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1670 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1671 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1672 NTCREATEX_SHARE_ACCESS_WRITE|
1673 NTCREATEX_SHARE_ACCESS_DELETE;
1674 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1675 status = smb2_create(tree2, tctx, &(io.smb2));
1676 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1677 h2 = io.smb2.out.file.handle;
1678 torture_wait_for_oplock_break(tctx);
1679 CHECK_VAL(break_info.count, 0);
1680 CHECK_VAL(break_info.failures, 0);
1681 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1683 torture_comment(tctx, "write should trigger a break to none\n");
1685 struct smb2_write wr;
1687 data = data_blob_talloc(tree1, NULL, UINT16_MAX);
1688 data.data[0] = (const uint8_t)'x';
1690 wr.in.file.handle = h1;
1693 status = smb2_write(tree1, &wr);
1694 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1697 torture_wait_for_oplock_break(tctx);
1699 CHECK_VAL(break_info.count, 1);
1700 CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1701 CHECK_VAL(break_info.level, 0);
1702 CHECK_VAL(break_info.failures, 0);
1704 smb2_util_close(tree1, h1);
1705 smb2_util_close(tree2, h2);
1706 smb2_util_close(tree1, h);
1708 smb2_deltree(tree1, BASEDIR);
1712 static bool test_smb2_oplock_batch11(struct torture_context *tctx,
1713 struct smb2_tree *tree1,
1714 struct smb2_tree *tree2)
1716 const char *fname = BASEDIR "\\test_batch11.dat";
1720 union smb_setfileinfo sfi;
1721 struct smb2_handle h, h1;
1723 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1724 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1727 smb2_util_unlink(tree1, fname);
1729 tree1->session->transport->oplock.handler =
1730 torture_oplock_handler_two_notifications;
1731 tree1->session->transport->oplock.private_data = tree1;
1734 base ntcreatex parms
1736 ZERO_STRUCT(io.smb2);
1737 io.generic.level = RAW_OPEN_SMB2;
1738 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1739 io.smb2.in.alloc_size = 0;
1740 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1741 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1742 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1743 io.smb2.in.create_options = 0;
1744 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1745 io.smb2.in.security_flags = 0;
1746 io.smb2.in.fname = fname;
1748 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1749 torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks "
1752 ZERO_STRUCT(break_info);
1754 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1755 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1756 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1757 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1758 NTCREATEX_SHARE_ACCESS_WRITE|
1759 NTCREATEX_SHARE_ACCESS_DELETE;
1760 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1761 status = smb2_create(tree1, tctx, &(io.smb2));
1762 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1763 h1 = io.smb2.out.file.handle;
1764 torture_wait_for_oplock_break(tctx);
1765 CHECK_VAL(break_info.count, 0);
1766 CHECK_VAL(break_info.failures, 0);
1767 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1770 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1771 sfi.generic.in.file.path = fname;
1772 sfi.end_of_file_info.in.size = 100;
1774 status = smb2_composite_setpathinfo(tree2, &sfi);
1775 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1777 /* We expect two breaks */
1778 torture_wait_for_oplock_break(tctx);
1779 torture_wait_for_oplock_break(tctx);
1781 CHECK_VAL(break_info.count, 2);
1782 CHECK_VAL(break_info.failures, 0);
1783 CHECK_VAL(break_info.level, 0);
1785 smb2_util_close(tree1, h1);
1786 smb2_util_close(tree1, h);
1788 smb2_deltree(tree1, BASEDIR);
1792 static bool test_smb2_oplock_batch12(struct torture_context *tctx,
1793 struct smb2_tree *tree1,
1794 struct smb2_tree *tree2)
1796 const char *fname = BASEDIR "\\test_batch12.dat";
1800 union smb_setfileinfo sfi;
1801 struct smb2_handle h, h1;
1803 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1804 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1807 smb2_util_unlink(tree1, fname);
1809 tree1->session->transport->oplock.handler =
1810 torture_oplock_handler_two_notifications;
1811 tree1->session->transport->oplock.private_data = tree1;
1814 base ntcreatex parms
1816 ZERO_STRUCT(io.smb2);
1817 io.generic.level = RAW_OPEN_SMB2;
1818 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1819 io.smb2.in.alloc_size = 0;
1820 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1821 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1822 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1823 io.smb2.in.create_options = 0;
1824 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1825 io.smb2.in.security_flags = 0;
1826 io.smb2.in.fname = fname;
1828 /* Test if a set-allocation size on pathname breaks an exclusive
1830 torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size "
1831 "breaks oplocks.\n");
1833 ZERO_STRUCT(break_info);
1835 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1836 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1837 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1838 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1839 NTCREATEX_SHARE_ACCESS_WRITE|
1840 NTCREATEX_SHARE_ACCESS_DELETE;
1841 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1842 status = smb2_create(tree1, tctx, &(io.smb2));
1843 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1844 h1 = io.smb2.out.file.handle;
1845 torture_wait_for_oplock_break(tctx);
1846 CHECK_VAL(break_info.count, 0);
1847 CHECK_VAL(break_info.failures, 0);
1848 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1851 sfi.generic.level = RAW_SFILEINFO_ALLOCATION_INFORMATION;
1852 sfi.generic.in.file.path = fname;
1853 sfi.allocation_info.in.alloc_size = 65536 * 8;
1855 status = smb2_composite_setpathinfo(tree2, &sfi);
1856 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1858 /* We expect two breaks */
1859 torture_wait_for_oplock_break(tctx);
1860 torture_wait_for_oplock_break(tctx);
1862 CHECK_VAL(break_info.count, 2);
1863 CHECK_VAL(break_info.failures, 0);
1864 CHECK_VAL(break_info.level, 0);
1866 smb2_util_close(tree1, h1);
1867 smb2_util_close(tree1, h);
1869 smb2_deltree(tree1, BASEDIR);
1873 static bool test_smb2_oplock_batch13(struct torture_context *tctx,
1874 struct smb2_tree *tree1,
1875 struct smb2_tree *tree2)
1877 const char *fname = BASEDIR "\\test_batch13.dat";
1881 struct smb2_handle h, h1, h2;
1883 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1884 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1887 smb2_util_unlink(tree1, fname);
1889 tree1->session->transport->oplock.handler = torture_oplock_handler;
1890 tree1->session->transport->oplock.private_data = tree1;
1892 tree2->session->transport->oplock.handler = torture_oplock_handler;
1893 tree2->session->transport->oplock.private_data = tree2;
1896 base ntcreatex parms
1898 ZERO_STRUCT(io.smb2);
1899 io.generic.level = RAW_OPEN_SMB2;
1900 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1901 io.smb2.in.alloc_size = 0;
1902 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1903 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1904 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1905 io.smb2.in.create_options = 0;
1906 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1907 io.smb2.in.security_flags = 0;
1908 io.smb2.in.fname = fname;
1910 torture_comment(tctx, "BATCH13: open with batch oplock\n");
1911 ZERO_STRUCT(break_info);
1913 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1914 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1915 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1916 NTCREATEX_SHARE_ACCESS_WRITE|
1917 NTCREATEX_SHARE_ACCESS_DELETE;
1918 status = smb2_create(tree1, tctx, &(io.smb2));
1919 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1920 h1 = io.smb2.out.file.handle;
1921 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1923 ZERO_STRUCT(break_info);
1925 torture_comment(tctx, "second open with attributes only and "
1926 "NTCREATEX_DISP_OVERWRITE dispostion causes "
1929 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1930 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1931 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1932 SEC_FILE_WRITE_ATTRIBUTE |
1933 SEC_STD_SYNCHRONIZE;
1934 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1935 NTCREATEX_SHARE_ACCESS_WRITE|
1936 NTCREATEX_SHARE_ACCESS_DELETE;
1937 io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
1938 status = smb2_create(tree2, tctx, &(io.smb2));
1939 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1940 h2 = io.smb2.out.file.handle;
1941 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1942 torture_wait_for_oplock_break(tctx);
1943 CHECK_VAL(break_info.count, 1);
1944 CHECK_VAL(break_info.failures, 0);
1946 smb2_util_close(tree1, h1);
1947 smb2_util_close(tree2, h2);
1948 smb2_util_close(tree1, h);
1950 smb2_deltree(tree1, BASEDIR);
1955 static bool test_smb2_oplock_batch14(struct torture_context *tctx,
1956 struct smb2_tree *tree1,
1957 struct smb2_tree *tree2)
1959 const char *fname = BASEDIR "\\test_batch14.dat";
1963 struct smb2_handle h, h1, h2;
1965 status = torture_smb2_testdir(tree1, BASEDIR, &h);
1966 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1969 smb2_util_unlink(tree1, fname);
1971 tree1->session->transport->oplock.handler = torture_oplock_handler;
1972 tree1->session->transport->oplock.private_data = tree1;
1975 base ntcreatex parms
1977 ZERO_STRUCT(io.smb2);
1978 io.generic.level = RAW_OPEN_SMB2;
1979 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1980 io.smb2.in.alloc_size = 0;
1981 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1982 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1983 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1984 io.smb2.in.create_options = 0;
1985 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1986 io.smb2.in.security_flags = 0;
1987 io.smb2.in.fname = fname;
1989 torture_comment(tctx, "BATCH14: open with batch oplock\n");
1990 ZERO_STRUCT(break_info);
1992 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1993 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1994 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1995 NTCREATEX_SHARE_ACCESS_WRITE|
1996 NTCREATEX_SHARE_ACCESS_DELETE;
1997 status = smb2_create(tree1, tctx, &(io.smb2));
1998 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1999 h1 = io.smb2.out.file.handle;
2000 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2002 ZERO_STRUCT(break_info);
2004 torture_comment(tctx, "second open with attributes only and "
2005 "NTCREATEX_DISP_SUPERSEDE dispostion causes "
2008 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2009 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2010 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2011 SEC_FILE_WRITE_ATTRIBUTE |
2012 SEC_STD_SYNCHRONIZE;
2013 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2014 NTCREATEX_SHARE_ACCESS_WRITE|
2015 NTCREATEX_SHARE_ACCESS_DELETE;
2016 io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2017 status = smb2_create(tree2, tctx, &(io.smb2));
2018 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2019 h2 = io.smb2.out.file.handle;
2020 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2022 torture_wait_for_oplock_break(tctx);
2023 CHECK_VAL(break_info.count, 1);
2024 CHECK_VAL(break_info.failures, 0);
2026 smb2_util_close(tree1, h1);
2027 smb2_util_close(tree2, h2);
2028 smb2_util_close(tree1, h);
2030 smb2_deltree(tree1, BASEDIR);
2034 static bool test_smb2_oplock_batch15(struct torture_context *tctx,
2035 struct smb2_tree *tree1,
2036 struct smb2_tree *tree2)
2038 const char *fname = BASEDIR "\\test_batch15.dat";
2042 union smb_fileinfo qfi;
2043 struct smb2_handle h, h1;
2045 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2046 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2049 smb2_util_unlink(tree1, fname);
2051 tree1->session->transport->oplock.handler = torture_oplock_handler;
2052 tree1->session->transport->oplock.private_data = tree1;
2055 base ntcreatex parms
2057 ZERO_STRUCT(io.smb2);
2058 io.generic.level = RAW_OPEN_SMB2;
2059 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2060 io.smb2.in.alloc_size = 0;
2061 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2062 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2063 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2064 io.smb2.in.create_options = 0;
2065 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2066 io.smb2.in.security_flags = 0;
2067 io.smb2.in.fname = fname;
2069 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
2070 torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks "
2071 "a batch oplock (should not).\n");
2073 ZERO_STRUCT(break_info);
2075 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2076 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2077 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2078 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2079 NTCREATEX_SHARE_ACCESS_WRITE|
2080 NTCREATEX_SHARE_ACCESS_DELETE;
2081 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2082 status = smb2_create(tree1, tctx, &(io.smb2));
2083 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2084 h1 = io.smb2.out.file.handle;
2086 torture_wait_for_oplock_break(tctx);
2087 CHECK_VAL(break_info.count, 0);
2088 CHECK_VAL(break_info.failures, 0);
2089 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2092 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2093 qfi.generic.in.file.handle = h1;
2094 status = smb2_getinfo_file(tree2, tctx, &qfi);
2096 torture_wait_for_oplock_break(tctx);
2097 CHECK_VAL(break_info.count, 0);
2099 smb2_util_close(tree1, h1);
2100 smb2_util_close(tree1, h);
2102 smb2_deltree(tree1, BASEDIR);
2106 static bool test_smb2_oplock_batch16(struct torture_context *tctx,
2107 struct smb2_tree *tree1,
2108 struct smb2_tree *tree2)
2110 const char *fname = BASEDIR "\\test_batch16.dat";
2114 struct smb2_handle h, h1, h2;
2116 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2117 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2120 smb2_util_unlink(tree1, fname);
2122 tree1->session->transport->oplock.handler = torture_oplock_handler;
2123 tree1->session->transport->oplock.private_data = tree1;
2125 tree2->session->transport->oplock.handler = torture_oplock_handler;
2126 tree2->session->transport->oplock.private_data = tree2;
2129 base ntcreatex parms
2131 ZERO_STRUCT(io.smb2);
2132 io.generic.level = RAW_OPEN_SMB2;
2133 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2134 io.smb2.in.alloc_size = 0;
2135 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2136 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2137 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2138 io.smb2.in.create_options = 0;
2139 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2140 io.smb2.in.security_flags = 0;
2141 io.smb2.in.fname = fname;
2143 torture_comment(tctx, "BATCH16: open with batch oplock\n");
2144 ZERO_STRUCT(break_info);
2146 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2147 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2148 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2149 NTCREATEX_SHARE_ACCESS_WRITE|
2150 NTCREATEX_SHARE_ACCESS_DELETE;
2151 status = smb2_create(tree1, tctx, &(io.smb2));
2152 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2153 h1 = io.smb2.out.file.handle;
2154 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2156 ZERO_STRUCT(break_info);
2158 torture_comment(tctx, "second open with attributes only and "
2159 "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
2162 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2163 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2164 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2165 SEC_FILE_WRITE_ATTRIBUTE |
2166 SEC_STD_SYNCHRONIZE;
2167 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2168 NTCREATEX_SHARE_ACCESS_WRITE|
2169 NTCREATEX_SHARE_ACCESS_DELETE;
2170 io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2171 status = smb2_create(tree2, tctx, &(io.smb2));
2172 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2173 h2 = io.smb2.out.file.handle;
2174 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2176 torture_wait_for_oplock_break(tctx);
2177 CHECK_VAL(break_info.count, 1);
2178 CHECK_VAL(break_info.failures, 0);
2180 smb2_util_close(tree1, h1);
2181 smb2_util_close(tree2, h2);
2182 smb2_util_close(tree1, h);
2184 smb2_deltree(tree1, BASEDIR);
2188 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH17 test. Since
2189 * SMB2 doesn't have a RENAME command this test isn't applicable. However,
2190 * it's much less confusing, when comparing test, to keep the SMB1 and SMB2
2191 * test numbers in sync. */
2193 static bool test_raw_oplock_batch17(struct torture_context *tctx,
2194 struct smb2_tree *tree1,
2195 struct smb2_tree *tree2)
2201 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH18 test. Since
2202 * SMB2 doesn't have an NTRENAME command this test isn't applicable. However,
2203 * it's much less confusing, when comparing tests, to keep the SMB1 and SMB2
2204 * test numbers in sync. */
2206 static bool test_raw_oplock_batch18(struct torture_context *tctx,
2207 struct smb2_tree *tree1,
2208 struct smb2_tree *tree2)
2214 static bool test_smb2_oplock_batch19(struct torture_context *tctx,
2215 struct smb2_tree *tree1)
2217 const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2218 const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2222 union smb_fileinfo qfi;
2223 union smb_setfileinfo sfi;
2224 struct smb2_handle h, h1;
2226 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2227 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2230 smb2_util_unlink(tree1, fname1);
2231 smb2_util_unlink(tree1, fname2);
2233 tree1->session->transport->oplock.handler = torture_oplock_handler;
2234 tree1->session->transport->oplock.private_data = tree1;
2237 base ntcreatex parms
2239 ZERO_STRUCT(io.smb2);
2240 io.generic.level = RAW_OPEN_SMB2;
2241 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2242 io.smb2.in.alloc_size = 0;
2243 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2244 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2245 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2246 io.smb2.in.create_options = 0;
2247 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2248 io.smb2.in.security_flags = 0;
2249 io.smb2.in.fname = fname1;
2251 torture_comment(tctx, "BATCH19: open a file with an batch oplock "
2252 "(share mode: none)\n");
2253 ZERO_STRUCT(break_info);
2254 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2255 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2256 status = smb2_create(tree1, tctx, &(io.smb2));
2257 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2258 h1 = io.smb2.out.file.handle;
2259 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2261 torture_comment(tctx, "setfileinfo rename info should not trigger "
2262 "a break but should cause a sharing violation\n");
2264 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2265 sfi.generic.in.file.path = fname1;
2266 sfi.rename_information.in.file.handle = h1;
2267 sfi.rename_information.in.overwrite = 0;
2268 sfi.rename_information.in.root_fid = 0;
2269 sfi.rename_information.in.new_name = fname2;
2271 status = smb2_setinfo_file(tree1, &sfi);
2273 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2274 "Incorrect status");
2276 torture_wait_for_oplock_break(tctx);
2277 CHECK_VAL(break_info.count, 0);
2280 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2281 qfi.generic.in.file.handle = h1;
2283 status = smb2_getinfo_file(tree1, tctx, &qfi);
2284 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2285 CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2287 smb2_util_close(tree1, h1);
2288 smb2_util_close(tree1, h);
2290 smb2_deltree(tree1, fname1);
2291 smb2_deltree(tree1, fname2);
2295 static bool test_smb2_oplock_batch20(struct torture_context *tctx,
2296 struct smb2_tree *tree1,
2297 struct smb2_tree *tree2)
2299 const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2300 const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2304 union smb_fileinfo qfi;
2305 union smb_setfileinfo sfi;
2306 struct smb2_handle h, h1, h2;
2308 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2309 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2312 smb2_util_unlink(tree1, fname1);
2313 smb2_util_unlink(tree1, fname2);
2315 tree1->session->transport->oplock.handler = torture_oplock_handler;
2316 tree1->session->transport->oplock.private_data = tree1;
2319 base ntcreatex parms
2321 ZERO_STRUCT(io.smb2);
2322 io.generic.level = RAW_OPEN_SMB2;
2323 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2324 io.smb2.in.alloc_size = 0;
2325 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2326 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2327 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2328 io.smb2.in.create_options = 0;
2329 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2330 io.smb2.in.security_flags = 0;
2331 io.smb2.in.fname = fname1;
2333 torture_comment(tctx, "BATCH20: open a file with an batch oplock "
2334 "(share mode: all)\n");
2335 ZERO_STRUCT(break_info);
2336 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2337 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2338 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2339 NTCREATEX_SHARE_ACCESS_WRITE|
2340 NTCREATEX_SHARE_ACCESS_DELETE;
2341 status = smb2_create(tree1, tctx, &(io.smb2));
2342 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2343 h1 = io.smb2.out.file.handle;
2344 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2346 torture_comment(tctx, "setfileinfo rename info should not trigger "
2347 "a break but should cause a sharing violation\n");
2349 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2350 sfi.rename_information.in.file.handle = h1;
2351 sfi.rename_information.in.overwrite = 0;
2352 sfi.rename_information.in.new_name = fname2;
2354 status = smb2_setinfo_file(tree1, &sfi);
2355 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2356 "Incorrect status");
2358 torture_wait_for_oplock_break(tctx);
2359 CHECK_VAL(break_info.count, 0);
2362 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2363 qfi.generic.in.file.handle = h1;
2365 status = smb2_getinfo_file(tree1, tctx, &qfi);
2366 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2367 CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2369 torture_comment(tctx, "open the file a second time requesting batch "
2370 "(share mode: all)\n");
2371 ZERO_STRUCT(break_info);
2372 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2373 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2374 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2375 NTCREATEX_SHARE_ACCESS_WRITE|
2376 NTCREATEX_SHARE_ACCESS_DELETE;
2377 io.smb2.in.fname = fname1;
2378 status = smb2_create(tree2, tctx, &(io.smb2));
2379 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2380 h2 = io.smb2.out.file.handle;
2381 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2383 torture_wait_for_oplock_break(tctx);
2384 CHECK_VAL(break_info.count, 1);
2385 CHECK_VAL(break_info.failures, 0);
2386 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2388 torture_comment(tctx, "setfileinfo rename info should not trigger "
2389 "a break but should cause a sharing violation\n");
2390 ZERO_STRUCT(break_info);
2392 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2393 sfi.rename_information.in.file.handle = h2;
2394 sfi.rename_information.in.overwrite = 0;
2395 sfi.rename_information.in.new_name = fname2;
2397 status = smb2_setinfo_file(tree2, &sfi);
2398 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2399 "Incorrect status");
2401 torture_wait_for_oplock_break(tctx);
2402 CHECK_VAL(break_info.count, 0);
2405 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2406 qfi.generic.in.file.handle = h1;
2408 status = smb2_getinfo_file(tree1, tctx, &qfi);
2409 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2410 CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2413 qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2414 qfi.generic.in.file.handle = h2;
2416 status = smb2_getinfo_file(tree2, tctx, &qfi);
2417 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2418 CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2420 smb2_util_close(tree1, h1);
2421 smb2_util_close(tree2, h2);
2422 smb2_util_close(tree1, h);
2424 smb2_deltree(tree1, fname1);
2428 static bool test_smb2_oplock_batch21(struct torture_context *tctx,
2429 struct smb2_tree *tree1)
2431 const char *fname = BASEDIR "\\test_batch21.dat";
2435 struct smb2_handle h, h1;
2438 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2439 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2442 smb2_util_unlink(tree1, fname);
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 = fname;
2463 with a batch oplock we get a break
2465 torture_comment(tctx, "BATCH21: open with batch oplock\n");
2466 ZERO_STRUCT(break_info);
2467 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2468 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2469 status = smb2_create(tree1, tctx, &(io.smb2));
2470 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2471 h1 = io.smb2.out.file.handle;
2472 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2474 torture_comment(tctx, "writing should not generate a break\n");
2475 status = smb2_util_write(tree1, h1, &c, 0, 1);
2476 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2478 torture_wait_for_oplock_break(tctx);
2479 CHECK_VAL(break_info.count, 0);
2481 smb2_util_close(tree1, h1);
2482 smb2_util_close(tree1, h);
2484 smb2_deltree(tree1, BASEDIR);
2488 static bool test_smb2_oplock_batch22(struct torture_context *tctx,
2489 struct smb2_tree *tree1)
2491 const char *fname = BASEDIR "\\test_batch22.dat";
2495 struct smb2_handle h, h1, h2;
2497 int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2500 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2501 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2504 smb2_util_unlink(tree1, fname);
2506 tree1->session->transport->oplock.handler = torture_oplock_handler;
2507 tree1->session->transport->oplock.private_data = tree1;
2509 base ntcreatex parms
2511 ZERO_STRUCT(io.smb2);
2512 io.generic.level = RAW_OPEN_SMB2;
2513 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2514 io.smb2.in.alloc_size = 0;
2515 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2516 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2517 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2518 io.smb2.in.create_options = 0;
2519 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2520 io.smb2.in.security_flags = 0;
2521 io.smb2.in.fname = fname;
2524 with a batch oplock we get a break
2526 torture_comment(tctx, "BATCH22: open with batch oplock\n");
2527 ZERO_STRUCT(break_info);
2528 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2529 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2530 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2531 NTCREATEX_SHARE_ACCESS_WRITE|
2532 NTCREATEX_SHARE_ACCESS_DELETE;
2533 status = smb2_create(tree1, tctx, &(io.smb2));
2534 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2535 h1 = io.smb2.out.file.handle;
2536 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2538 torture_comment(tctx, "a 2nd open should succeed after the oplock "
2540 tv = timeval_current();
2541 tree1->session->transport->oplock.handler =
2542 torture_oplock_handler_timeout;
2543 status = smb2_create(tree1, tctx, &(io.smb2));
2544 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2545 h2 = io.smb2.out.file.handle;
2546 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2548 torture_wait_for_oplock_break(tctx);
2549 te = (int)timeval_elapsed(&tv);
2550 CHECK_RANGE(te, timeout - 1, timeout + 15);
2551 torture_comment(tctx, "waited %d seconds for oplock timeout\n", te);
2553 CHECK_VAL(break_info.count, 1);
2554 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2555 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2556 CHECK_VAL(break_info.failures, 0);
2558 smb2_util_close(tree1, h1);
2559 smb2_util_close(tree1, h2);
2560 smb2_util_close(tree1, h);
2562 smb2_deltree(tree1, BASEDIR);
2566 static bool test_smb2_oplock_batch23(struct torture_context *tctx,
2567 struct smb2_tree *tree1,
2568 struct smb2_tree *tree2)
2570 const char *fname = BASEDIR "\\test_batch23.dat";
2574 struct smb2_handle h, h1, h2, h3;
2575 struct smb2_tree *tree3 = NULL;
2577 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2578 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2581 smb2_util_unlink(tree1, fname);
2583 ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2584 CHECK_VAL(ret, true);
2586 tree1->session->transport->oplock.handler = torture_oplock_handler;
2587 tree1->session->transport->oplock.private_data = tree1;
2589 tree2->session->transport->oplock.handler = torture_oplock_handler;
2590 tree2->session->transport->oplock.private_data = tree2;
2592 tree3->session->transport->oplock.handler = torture_oplock_handler;
2593 tree3->session->transport->oplock.private_data = tree3;
2596 base ntcreatex parms
2598 ZERO_STRUCT(io.smb2);
2599 io.generic.level = RAW_OPEN_SMB2;
2600 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2601 io.smb2.in.alloc_size = 0;
2602 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2603 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2604 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2605 io.smb2.in.create_options = 0;
2606 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2607 io.smb2.in.security_flags = 0;
2608 io.smb2.in.fname = fname;
2610 torture_comment(tctx, "BATCH23: an open and ask for a batch oplock\n");
2611 ZERO_STRUCT(break_info);
2613 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2614 SEC_RIGHTS_FILE_WRITE;
2615 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2616 NTCREATEX_SHARE_ACCESS_WRITE;
2617 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2618 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2619 status = smb2_create(tree1, tctx, &(io.smb2));
2620 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2621 h1 = io.smb2.out.file.handle;
2622 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2624 ZERO_STRUCT(break_info);
2626 torture_comment(tctx, "a 2nd open without level2 oplock support "
2627 "should generate a break to level2\n");
2628 status = smb2_create(tree3, tctx, &(io.smb2));
2629 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2630 h3 = io.smb2.out.file.handle;
2632 torture_wait_for_oplock_break(tctx);
2633 CHECK_VAL(break_info.count, 1);
2634 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2635 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2636 CHECK_VAL(break_info.failures, 0);
2638 ZERO_STRUCT(break_info);
2640 torture_comment(tctx, "a 3rd open with level2 oplock support should "
2641 "not generate a break\n");
2642 status = smb2_create(tree2, tctx, &(io.smb2));
2643 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2644 h2 = io.smb2.out.file.handle;
2645 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2647 torture_wait_for_oplock_break(tctx);
2648 CHECK_VAL(break_info.count, 0);
2650 smb2_util_close(tree1, h1);
2651 smb2_util_close(tree2, h2);
2652 smb2_util_close(tree3, h3);
2653 smb2_util_close(tree1, h);
2655 smb2_deltree(tree1, BASEDIR);
2659 static bool test_smb2_oplock_batch24(struct torture_context *tctx,
2660 struct smb2_tree *tree1,
2661 struct smb2_tree *tree2)
2663 const char *fname = BASEDIR "\\test_batch24.dat";
2667 struct smb2_handle h, h1, h2;
2668 struct smb2_tree *tree3 = NULL;
2670 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2671 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2674 smb2_util_unlink(tree1, fname);
2676 ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2677 CHECK_VAL(ret, true);
2679 tree1->session->transport->oplock.handler = torture_oplock_handler;
2680 tree1->session->transport->oplock.private_data = tree1;
2682 tree2->session->transport->oplock.handler = torture_oplock_handler;
2683 tree2->session->transport->oplock.private_data = tree2;
2685 tree3->session->transport->oplock.handler = torture_oplock_handler;
2686 tree3->session->transport->oplock.private_data = tree3;
2689 base ntcreatex parms
2691 ZERO_STRUCT(io.smb2);
2692 io.generic.level = RAW_OPEN_SMB2;
2693 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2694 io.smb2.in.alloc_size = 0;
2695 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2696 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2697 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2698 io.smb2.in.create_options = 0;
2699 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2700 io.smb2.in.security_flags = 0;
2701 io.smb2.in.fname = fname;
2703 torture_comment(tctx, "BATCH24: a open without level support and "
2704 "ask for a batch oplock\n");
2705 ZERO_STRUCT(break_info);
2707 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2708 SEC_RIGHTS_FILE_WRITE;
2709 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2710 NTCREATEX_SHARE_ACCESS_WRITE;
2711 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2712 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2714 status = smb2_create(tree3, tctx, &(io.smb2));
2715 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2716 h2 = io.smb2.out.file.handle;
2717 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2719 ZERO_STRUCT(break_info);
2721 torture_comment(tctx, "a 2nd open with level2 oplock support should "
2722 "generate a break\n");
2723 status = smb2_create(tree2, tctx, &(io.smb2));
2724 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2725 h1 = io.smb2.out.file.handle;
2726 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2728 torture_wait_for_oplock_break(tctx);
2729 CHECK_VAL(break_info.count, 1);
2730 CHECK_VAL(break_info.handle.data[0], h2.data[0]);
2731 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2732 CHECK_VAL(break_info.failures, 0);
2734 smb2_util_close(tree3, h2);
2735 smb2_util_close(tree2, h1);
2736 smb2_util_close(tree1, h);
2738 smb2_deltree(tree1, BASEDIR);
2742 static bool test_smb2_oplock_batch25(struct torture_context *tctx,
2743 struct smb2_tree *tree1)
2745 const char *fname = BASEDIR "\\test_batch25.dat";
2749 struct smb2_handle h, h1;
2751 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2752 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2755 smb2_util_unlink(tree1, fname);
2757 tree1->session->transport->oplock.handler = torture_oplock_handler;
2758 tree1->session->transport->oplock.private_data = tree1;
2761 base ntcreatex parms
2763 ZERO_STRUCT(io.smb2);
2764 io.generic.level = RAW_OPEN_SMB2;
2765 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2766 io.smb2.in.alloc_size = 0;
2767 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2768 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2769 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2770 io.smb2.in.create_options = 0;
2771 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2772 io.smb2.in.security_flags = 0;
2773 io.smb2.in.fname = fname;
2775 torture_comment(tctx, "BATCH25: open a file with an batch oplock "
2776 "(share mode: none)\n");
2778 ZERO_STRUCT(break_info);
2779 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2780 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2782 status = smb2_create(tree1, tctx, &(io.smb2));
2783 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2784 h1 = io.smb2.out.file.handle;
2785 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2787 torture_comment(tctx, "changing the file attribute info should trigger "
2788 "a break and a violation\n");
2790 status = smb2_util_setatr(tree1, fname, FILE_ATTRIBUTE_HIDDEN);
2791 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2792 "Incorrect status");
2794 torture_wait_for_oplock_break(tctx);
2795 CHECK_VAL(break_info.count, 1);
2797 smb2_util_close(tree1, h1);
2798 smb2_util_close(tree1, h);
2800 smb2_deltree(tree1, fname);
2804 /* Test how oplocks work on streams. */
2805 static bool test_raw_oplock_stream1(struct torture_context *tctx,
2806 struct smb2_tree *tree1,
2807 struct smb2_tree *tree2)
2811 const char *fname_base = BASEDIR "\\test_stream1.txt";
2812 const char *fname_stream, *fname_default_stream;
2813 const char *default_stream = "::$DATA";
2814 const char *stream = "Stream One:$DATA";
2816 struct smb2_handle h, h_base, h_stream;
2819 #define NSTREAM_OPLOCK_RESULTS 8
2822 bool open_base_file;
2823 uint32_t oplock_req;
2824 uint32_t oplock_granted;
2825 } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
2826 /* Request oplock on stream without the base file open. */
2827 {&fname_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2828 {&fname_default_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2829 {&fname_stream, false, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2830 {&fname_default_stream, false, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2832 /* Request oplock on stream with the base file open. */
2833 {&fname_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2834 {&fname_default_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_II},
2835 {&fname_stream, true, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2836 {&fname_default_stream, true, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_II},
2839 fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
2840 fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
2843 status = torture_smb2_testdir(tree1, BASEDIR, &h);
2844 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2846 /* Initialize handles to "closed". Using -1 in the first 64-bytes
2847 * as the sentry for this */
2848 h_stream.data[0] = -1;
2851 smb2_util_unlink(tree1, fname_base);
2853 tree1->session->transport->oplock.handler = torture_oplock_handler;
2854 tree1->session->transport->oplock.private_data = tree1;
2856 tree2->session->transport->oplock.handler = torture_oplock_handler;
2857 tree2->session->transport->oplock.private_data = tree2;
2859 /* Setup generic open parameters. */
2860 ZERO_STRUCT(io.smb2);
2861 io.generic.level = RAW_OPEN_SMB2;
2862 io.smb2.in.desired_access = (SEC_FILE_READ_DATA |
2863 SEC_FILE_WRITE_DATA |
2864 SEC_FILE_APPEND_DATA |
2865 SEC_STD_READ_CONTROL);
2866 io.smb2.in.alloc_size = 0;
2867 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2868 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2869 NTCREATEX_SHARE_ACCESS_WRITE;
2870 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2871 io.smb2.in.create_options = 0;
2872 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2873 io.smb2.in.security_flags = 0;
2875 /* Create the file with a stream */
2876 io.smb2.in.fname = fname_stream;
2877 io.smb2.in.create_flags = 0;
2878 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2879 status = smb2_create(tree1, tctx, &(io.smb2));
2880 torture_assert_ntstatus_ok(tctx, status, "Error creating file");
2881 smb2_util_close(tree1, io.smb2.out.file.handle);
2883 /* Change the disposition to open now that the file has been created. */
2884 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
2886 /* Try some permutations of taking oplocks on streams. */
2887 for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
2888 const char *fname = *stream_oplock_results[i].fname;
2889 bool open_base_file = stream_oplock_results[i].open_base_file;
2890 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
2891 uint32_t oplock_granted =
2892 stream_oplock_results[i].oplock_granted;
2894 if (open_base_file) {
2895 torture_comment(tctx, "Opening base file: %s with "
2896 "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2897 io.smb2.in.fname = fname_base;
2898 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2899 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2900 status = smb2_create(tree2, tctx, &(io.smb2));
2901 torture_assert_ntstatus_ok(tctx, status,
2902 "Error opening file");
2903 CHECK_VAL(io.smb2.out.oplock_level,
2904 SMB2_OPLOCK_LEVEL_BATCH);
2905 h_base = io.smb2.out.file.handle;
2908 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
2910 io.smb2.in.fname = fname;
2911 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2912 io.smb2.in.oplock_level = oplock_req;
2914 /* Do the open with the desired oplock on the stream. */
2915 status = smb2_create(tree1, tctx, &(io.smb2));
2916 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2917 CHECK_VAL(io.smb2.out.oplock_level, oplock_granted);
2918 smb2_util_close(tree1, io.smb2.out.file.handle);
2920 /* Cleanup the base file if it was opened. */
2922 smb2_util_close(tree2, h_base);
2925 /* Open the stream with an exclusive oplock. */
2926 torture_comment(tctx, "Opening stream: %s with %d\n",
2927 fname_stream, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
2928 io.smb2.in.fname = fname_stream;
2929 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2930 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
2931 status = smb2_create(tree1, tctx, &(io.smb2));
2932 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2933 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
2934 h_stream = io.smb2.out.file.handle;
2936 /* Open the base file and see if it contends. */
2937 ZERO_STRUCT(break_info);
2938 torture_comment(tctx, "Opening base file: %s with %d\n",
2939 fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2940 io.smb2.in.fname = fname_base;
2941 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2942 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2943 status = smb2_create(tree2, tctx, &(io.smb2));
2944 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2945 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2946 smb2_util_close(tree2, io.smb2.out.file.handle);
2948 torture_wait_for_oplock_break(tctx);
2949 CHECK_VAL(break_info.count, 0);
2950 CHECK_VAL(break_info.failures, 0);
2952 /* Open the stream again to see if it contends. */
2953 ZERO_STRUCT(break_info);
2954 torture_comment(tctx, "Opening stream again: %s with "
2955 "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2956 io.smb2.in.fname = fname_stream;
2957 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2958 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
2959 status = smb2_create(tree2, tctx, &(io.smb2));
2960 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2961 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2962 smb2_util_close(tree2, io.smb2.out.file.handle);
2964 torture_wait_for_oplock_break(tctx);
2965 CHECK_VAL(break_info.count, 1);
2966 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2967 CHECK_VAL(break_info.failures, 0);
2969 /* Close the stream. */
2970 if (h_stream.data[0] != -1) {
2971 smb2_util_close(tree1, h_stream);
2974 smb2_util_close(tree1, h);
2976 smb2_deltree(tree1, BASEDIR);
2980 static bool test_smb2_oplock_doc(struct torture_context *tctx, struct smb2_tree *tree,
2981 struct smb2_tree *tree2)
2983 const char *fname = BASEDIR "\\test_oplock_doc.dat";
2987 struct smb2_handle h, h1;
2988 union smb_setfileinfo sfinfo;
2990 status = torture_smb2_testdir(tree, BASEDIR, &h);
2991 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2992 smb2_util_close(tree, h);
2995 smb2_util_unlink(tree, fname);
2996 tree->session->transport->oplock.handler = torture_oplock_handler;
2997 tree->session->transport->oplock.private_data = tree;
3000 base ntcreatex parms
3002 ZERO_STRUCT(io.smb2);
3003 io.generic.level = RAW_OPEN_SMB2;
3004 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3005 io.smb2.in.alloc_size = 0;
3006 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3007 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
3008 NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
3009 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3010 io.smb2.in.create_options = 0;
3011 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3012 io.smb2.in.security_flags = 0;
3013 io.smb2.in.fname = fname;
3015 torture_comment(tctx, "open a file with a batch oplock\n");
3016 ZERO_STRUCT(break_info);
3017 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3018 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3020 status = smb2_create(tree, tctx, &(io.smb2));
3021 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3022 h1 = io.smb2.out.file.handle;
3023 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3025 torture_comment(tctx, "Set delete on close\n");
3026 ZERO_STRUCT(sfinfo);
3027 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3028 sfinfo.generic.in.file.handle = h1;
3029 sfinfo.disposition_info.in.delete_on_close = 1;
3030 status = smb2_setinfo_file(tree, &sfinfo);
3031 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3033 torture_comment(tctx, "2nd open should not break and get "
3034 "DELETE_PENDING\n");
3035 ZERO_STRUCT(break_info);
3036 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
3037 io.smb2.in.create_options = 0;
3038 io.smb2.in.desired_access = SEC_FILE_READ_DATA;
3039 status = smb2_create(tree2, tctx, &io.smb2);
3040 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DELETE_PENDING,
3041 "Incorrect status");
3042 CHECK_VAL(break_info.count, 0);
3044 smb2_util_close(tree, h1);
3046 smb2_util_unlink(tree, fname);
3047 smb2_deltree(tree, BASEDIR);
3051 /* Open a file with a batch oplock, then open it again from a second client
3052 * requesting no oplock. Having two open file handles should break our own
3053 * oplock during BRL acquisition.
3055 static bool test_smb2_oplock_brl1(struct torture_context *tctx,
3056 struct smb2_tree *tree1,
3057 struct smb2_tree *tree2)
3059 const char *fname = BASEDIR "\\test_batch_brl.dat";
3065 struct smb2_lock lck;
3066 struct smb2_lock_element lock[1];
3067 struct smb2_handle h, h1, h2;
3069 status = torture_smb2_testdir(tree1, BASEDIR, &h);
3070 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3073 smb2_util_unlink(tree1, fname);
3075 tree1->session->transport->oplock.handler =
3076 torture_oplock_handler_two_notifications;
3077 tree1->session->transport->oplock.private_data = tree1;
3080 base ntcreatex parms
3082 ZERO_STRUCT(io.smb2);
3083 io.generic.level = RAW_OPEN_SMB2;
3084 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3085 SEC_RIGHTS_FILE_WRITE;
3086 io.smb2.in.alloc_size = 0;
3087 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3088 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3089 NTCREATEX_SHARE_ACCESS_WRITE;
3090 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3091 io.smb2.in.create_options = 0;
3092 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3093 io.smb2.in.security_flags = 0;
3094 io.smb2.in.fname = fname;
3097 with a batch oplock we get a break
3099 torture_comment(tctx, "open with batch oplock\n");
3100 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3101 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3103 status = smb2_create(tree1, tctx, &(io.smb2));
3104 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3105 h1 = io.smb2.out.file.handle;
3106 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3108 /* create a file with bogus data */
3109 memset(buf, 0, sizeof(buf));
3111 status = smb2_util_write(tree1, h1,buf, 0, sizeof(buf));
3112 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3113 torture_comment(tctx, "Failed to create file\n");
3118 torture_comment(tctx, "a 2nd open should give a break\n");
3119 ZERO_STRUCT(break_info);
3121 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3122 io.smb2.in.oplock_level = 0;
3123 status = smb2_create(tree2, tctx, &(io.smb2));
3124 h2 = io.smb2.out.file.handle;
3125 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3127 torture_wait_for_oplock_break(tctx);
3128 CHECK_VAL(break_info.count, 1);
3129 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3130 CHECK_VAL(break_info.failures, 0);
3131 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3133 ZERO_STRUCT(break_info);
3135 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3138 lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3139 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3142 lck.in.file.handle = h1;
3143 lck.in.locks = &lock[0];
3144 lck.in.lock_count = 1;
3145 status = smb2_lock(tree1, &lck);
3146 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3148 torture_wait_for_oplock_break(tctx);
3149 CHECK_VAL(break_info.count, 1);
3150 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3151 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3152 CHECK_VAL(break_info.failures, 0);
3154 /* expect no oplock break */
3155 ZERO_STRUCT(break_info);
3157 status = smb2_lock(tree1, &lck);
3158 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3159 "Incorrect status");
3161 torture_wait_for_oplock_break(tctx);
3162 CHECK_VAL(break_info.count, 0);
3163 CHECK_VAL(break_info.level, 0);
3164 CHECK_VAL(break_info.failures, 0);
3166 smb2_util_close(tree1, h1);
3167 smb2_util_close(tree2, h2);
3168 smb2_util_close(tree1, h);
3171 smb2_deltree(tree1, BASEDIR);
3176 /* Open a file with a batch oplock on one tree and then acquire a brl.
3177 * We should not contend our own oplock.
3179 static bool test_smb2_oplock_brl2(struct torture_context *tctx, struct smb2_tree *tree1)
3181 const char *fname = BASEDIR "\\test_batch_brl.dat";
3187 struct smb2_handle h, h1;
3188 struct smb2_lock lck;
3189 struct smb2_lock_element lock[1];
3191 status = torture_smb2_testdir(tree1, BASEDIR, &h);
3192 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3195 smb2_util_unlink(tree1, fname);
3197 tree1->session->transport->oplock.handler = torture_oplock_handler;
3198 tree1->session->transport->oplock.private_data = tree1;
3201 base ntcreatex parms
3203 ZERO_STRUCT(io.smb2);
3204 io.generic.level = RAW_OPEN_SMB2;
3205 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3206 SEC_RIGHTS_FILE_WRITE;
3207 io.smb2.in.alloc_size = 0;
3208 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3209 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3210 NTCREATEX_SHARE_ACCESS_WRITE;
3211 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3212 io.smb2.in.create_options = 0;
3213 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3214 io.smb2.in.security_flags = 0;
3215 io.smb2.in.fname = fname;
3218 with a batch oplock we get a break
3220 torture_comment(tctx, "open with batch oplock\n");
3221 ZERO_STRUCT(break_info);
3222 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3223 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3225 status = smb2_create(tree1, tctx, &(io.smb2));
3226 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3227 h1 = io.smb2.out.file.handle;
3228 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3230 /* create a file with bogus data */
3231 memset(buf, 0, sizeof(buf));
3233 status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3234 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3235 torture_comment(tctx, "Failed to create file\n");
3240 ZERO_STRUCT(break_info);
3242 torture_comment(tctx, "a self BRL acquisition should not break to "
3247 lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3248 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3251 lck.in.file.handle = h1;
3252 lck.in.locks = &lock[0];
3253 lck.in.lock_count = 1;
3254 status = smb2_lock(tree1, &lck);
3255 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3258 status = smb2_lock(tree1, &lck);
3259 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3260 "Incorrect status");
3262 /* With one file handle open a BRL should not contend our oplock.
3263 * Thus, no oplock break will be received and the entire break_info
3264 * struct will be 0 */
3265 torture_wait_for_oplock_break(tctx);
3266 CHECK_VAL(break_info.count, 0);
3267 CHECK_VAL(break_info.level, 0);
3268 CHECK_VAL(break_info.failures, 0);
3270 smb2_util_close(tree1, h1);
3271 smb2_util_close(tree1, h);
3274 smb2_deltree(tree1, BASEDIR);
3278 /* Open a file with a batch oplock twice from one tree and then acquire a
3279 * brl. BRL acquisition should break our own oplock.
3281 static bool test_smb2_oplock_brl3(struct torture_context *tctx, struct smb2_tree *tree1)
3283 const char *fname = BASEDIR "\\test_batch_brl.dat";
3288 struct smb2_handle h, h1, h2;
3289 struct smb2_lock lck;
3290 struct smb2_lock_element lock[1];
3292 status = torture_smb2_testdir(tree1, BASEDIR, &h);
3293 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3296 smb2_util_unlink(tree1, fname);
3297 tree1->session->transport->oplock.handler =
3298 torture_oplock_handler_two_notifications;
3299 tree1->session->transport->oplock.private_data = tree1;
3302 base ntcreatex parms
3304 ZERO_STRUCT(io.smb2);
3305 io.generic.level = RAW_OPEN_SMB2;
3306 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3307 SEC_RIGHTS_FILE_WRITE;
3308 io.smb2.in.alloc_size = 0;
3309 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3310 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3311 NTCREATEX_SHARE_ACCESS_WRITE;
3312 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3313 io.smb2.in.create_options = 0;
3314 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3315 io.smb2.in.security_flags = 0;
3316 io.smb2.in.fname = fname;
3319 with a batch oplock we get a break
3321 torture_comment(tctx, "open with batch oplock\n");
3322 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3323 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3325 status = smb2_create(tree1, tctx, &(io.smb2));
3326 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3327 h1 = io.smb2.out.file.handle;
3328 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3330 /* create a file with bogus data */
3331 memset(buf, 0, sizeof(buf));
3332 status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3334 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3335 torture_comment(tctx, "Failed to create file\n");
3340 torture_comment(tctx, "a 2nd open should give a break\n");
3341 ZERO_STRUCT(break_info);
3343 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3344 io.smb2.in.oplock_level = 0;
3345 status = smb2_create(tree1, tctx, &(io.smb2));
3346 h2 = io.smb2.out.file.handle;
3347 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3348 CHECK_VAL(break_info.count, 1);
3349 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3350 CHECK_VAL(break_info.failures, 0);
3351 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3353 ZERO_STRUCT(break_info);
3355 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3359 lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3360 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3363 lck.in.file.handle = h1;
3364 lck.in.locks = &lock[0];
3365 lck.in.lock_count = 1;
3366 status = smb2_lock(tree1, &lck);
3367 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3369 torture_wait_for_oplock_break(tctx);
3370 CHECK_VAL(break_info.count, 1);
3371 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3372 CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3373 CHECK_VAL(break_info.failures, 0);
3375 /* expect no oplock break */
3376 ZERO_STRUCT(break_info);
3378 status = smb2_lock(tree1, &lck);
3379 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3380 "Incorrect status");
3382 torture_wait_for_oplock_break(tctx);
3383 CHECK_VAL(break_info.count, 0);
3384 CHECK_VAL(break_info.level, 0);
3385 CHECK_VAL(break_info.failures, 0);
3387 smb2_util_close(tree1, h1);
3388 smb2_util_close(tree1, h2);
3389 smb2_util_close(tree1, h);
3392 smb2_deltree(tree1, BASEDIR);
3397 /* Starting the SMB2 specific oplock tests at 500 so we can keep the SMB1
3398 * tests in sync with an identically numbered SMB2 test */
3400 /* Test whether the server correctly returns an error when we send
3401 * a response to a levelII to none oplock notification. */
3402 static bool test_smb2_oplock_levelII500(struct torture_context *tctx,
3403 struct smb2_tree *tree1)
3405 const char *fname = BASEDIR "\\test_levelII500.dat";
3409 struct smb2_handle h, h1;
3412 status = torture_smb2_testdir(tree1, BASEDIR, &h);
3413 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3416 smb2_util_unlink(tree1, fname);
3418 tree1->session->transport->oplock.handler = torture_oplock_handler;
3419 tree1->session->transport->oplock.private_data = tree1;
3422 base ntcreatex parms
3424 ZERO_STRUCT(io.smb2);
3425 io.generic.level = RAW_OPEN_SMB2;
3426 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3427 io.smb2.in.alloc_size = 0;
3428 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3429 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3430 io.smb2.in.create_options = 0;
3431 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3432 io.smb2.in.security_flags = 0;
3433 io.smb2.in.fname = fname;
3435 torture_comment(tctx, "LEVELII500: acknowledging a break from II to "
3436 "none should return an error\n");
3437 ZERO_STRUCT(break_info);
3439 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3440 SEC_RIGHTS_FILE_WRITE;
3441 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3442 NTCREATEX_SHARE_ACCESS_WRITE;
3443 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3444 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
3445 status = smb2_create(tree1, tctx, &(io.smb2));
3446 torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3447 h1 = io.smb2.out.file.handle;
3448 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
3450 ZERO_STRUCT(break_info);
3452 torture_comment(tctx, "write should trigger a break to none and when "
3453 "we reply, an oplock break failure\n");
3454 smb2_util_write(tree1, h1, &c, 0, 1);
3456 /* Wait several times to receive both the break notification, and the
3457 * NT_STATUS_INVALID_OPLOCK_PROTOCOL error in the break response */
3458 torture_wait_for_oplock_break(tctx);
3459 torture_wait_for_oplock_break(tctx);
3460 torture_wait_for_oplock_break(tctx);
3461 torture_wait_for_oplock_break(tctx);
3463 /* There appears to be a race condition in W2K8 and W2K8R2 where
3464 * sometimes the server will happily reply to our break response with
3465 * NT_STATUS_OK, and sometimes it will return the OPLOCK_PROTOCOL
3466 * error. As the MS-SMB2 doc states that a client should not reply to
3467 * a level2 to none break notification, I'm leaving the protocol error
3468 * as the expected behavior. */
3469 CHECK_VAL(break_info.count, 1);
3470 CHECK_VAL(break_info.level, 0);
3471 CHECK_VAL(break_info.failures, 1);
3472 torture_assert_ntstatus_equal(tctx, break_info.failure_status,
3473 NT_STATUS_INVALID_OPLOCK_PROTOCOL,
3474 "Incorrect status");
3476 smb2_util_close(tree1, h1);
3477 smb2_util_close(tree1, h);
3479 smb2_deltree(tree1, BASEDIR);
3483 struct torture_suite *torture_smb2_oplocks_init(void)
3485 struct torture_suite *suite =
3486 torture_suite_create(talloc_autofree_context(), "oplock");
3488 torture_suite_add_2smb2_test(suite, "exclusive1", test_smb2_oplock_exclusive1);
3489 torture_suite_add_2smb2_test(suite, "exclusive2", test_smb2_oplock_exclusive2);
3490 torture_suite_add_2smb2_test(suite, "exclusive3", test_smb2_oplock_exclusive3);
3491 torture_suite_add_2smb2_test(suite, "exclusive4", test_smb2_oplock_exclusive4);
3492 torture_suite_add_2smb2_test(suite, "exclusive5", test_smb2_oplock_exclusive5);
3493 torture_suite_add_2smb2_test(suite, "exclusive6", test_smb2_oplock_exclusive6);
3494 torture_suite_add_2smb2_test(suite, "exclusive9",
3495 test_smb2_oplock_exclusive9);
3496 torture_suite_add_2smb2_test(suite, "batch1", test_smb2_oplock_batch1);
3497 torture_suite_add_2smb2_test(suite, "batch2", test_smb2_oplock_batch2);
3498 torture_suite_add_2smb2_test(suite, "batch3", test_smb2_oplock_batch3);
3499 torture_suite_add_2smb2_test(suite, "batch4", test_smb2_oplock_batch4);
3500 torture_suite_add_2smb2_test(suite, "batch5", test_smb2_oplock_batch5);
3501 torture_suite_add_2smb2_test(suite, "batch6", test_smb2_oplock_batch6);
3502 torture_suite_add_2smb2_test(suite, "batch7", test_smb2_oplock_batch7);
3503 torture_suite_add_2smb2_test(suite, "batch8", test_smb2_oplock_batch8);
3504 torture_suite_add_2smb2_test(suite, "batch9", test_smb2_oplock_batch9);
3505 torture_suite_add_2smb2_test(suite, "batch10", test_smb2_oplock_batch10);
3506 torture_suite_add_2smb2_test(suite, "batch11", test_smb2_oplock_batch11);
3507 torture_suite_add_2smb2_test(suite, "batch12", test_smb2_oplock_batch12);
3508 torture_suite_add_2smb2_test(suite, "batch13", test_smb2_oplock_batch13);
3509 torture_suite_add_2smb2_test(suite, "batch14", test_smb2_oplock_batch14);
3510 torture_suite_add_2smb2_test(suite, "batch15", test_smb2_oplock_batch15);
3511 torture_suite_add_2smb2_test(suite, "batch16", test_smb2_oplock_batch16);
3512 torture_suite_add_1smb2_test(suite, "batch19", test_smb2_oplock_batch19);
3513 torture_suite_add_2smb2_test(suite, "batch20", test_smb2_oplock_batch20);
3514 torture_suite_add_1smb2_test(suite, "batch21", test_smb2_oplock_batch21);
3515 torture_suite_add_1smb2_test(suite, "batch22", test_smb2_oplock_batch22);
3516 torture_suite_add_2smb2_test(suite, "batch23", test_smb2_oplock_batch23);
3517 torture_suite_add_2smb2_test(suite, "batch24", test_smb2_oplock_batch24);
3518 torture_suite_add_1smb2_test(suite, "batch25", test_smb2_oplock_batch25);
3519 torture_suite_add_2smb2_test(suite, "stream1", test_raw_oplock_stream1);
3520 torture_suite_add_2smb2_test(suite, "doc", test_smb2_oplock_doc);
3521 torture_suite_add_2smb2_test(suite, "brl1", test_smb2_oplock_brl1);
3522 torture_suite_add_1smb2_test(suite, "brl2", test_smb2_oplock_brl2);
3523 torture_suite_add_1smb2_test(suite, "brl3", test_smb2_oplock_brl3);
3524 torture_suite_add_1smb2_test(suite, "levelii500", test_smb2_oplock_levelII500);
3526 suite->description = talloc_strdup(suite, "SMB2-OPLOCK tests");
3532 stress testing of oplocks
3534 bool test_smb2_bench_oplock(struct torture_context *tctx,
3535 struct smb2_tree *tree)
3537 struct smb2_tree **trees;
3540 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3541 int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
3543 int timelimit = torture_setting_int(tctx, "timelimit", 10);
3546 struct smb2_handle h;
3548 trees = talloc_array(mem_ctx, struct smb2_tree *, torture_nprocs);
3550 torture_comment(tctx, "Opening %d connections\n", torture_nprocs);
3551 for (i=0;i<torture_nprocs;i++) {
3552 if (!torture_smb2_connection(tctx, &trees[i])) {
3555 talloc_steal(mem_ctx, trees[i]);
3556 trees[i]->session->transport->oplock.handler =
3557 torture_oplock_handler_close;
3558 trees[i]->session->transport->oplock.private_data = trees[i];
3561 status = torture_smb2_testdir(trees[0], BASEDIR, &h);
3562 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3564 ZERO_STRUCT(io.smb2);
3565 io.smb2.level = RAW_OPEN_SMB2;
3566 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3567 io.smb2.in.alloc_size = 0;
3568 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3569 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3570 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3571 io.smb2.in.create_options = 0;
3572 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3573 io.smb2.in.security_flags = 0;
3574 io.smb2.in.fname = BASEDIR "\\test.dat";
3575 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3576 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3578 tv = timeval_current();
3581 we open the same file with SHARE_ACCESS_NONE from all the
3582 connections in a round robin fashion. Each open causes an
3583 oplock break on the previous connection, which is answered
3584 by the oplock_handler_close() to close the file.
3586 This measures how fast we can pass on oplocks, and stresses
3587 the oplock handling code
3589 torture_comment(tctx, "Running for %d seconds\n", timelimit);
3590 while (timeval_elapsed(&tv) < timelimit) {
3591 for (i=0;i<torture_nprocs;i++) {
3592 status = smb2_create(trees[i], mem_ctx, &(io.smb2));
3593 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3597 if (torture_setting_bool(tctx, "progress", true)) {
3598 torture_comment(tctx, "%.2f ops/second\r",
3599 count/timeval_elapsed(&tv));
3603 torture_comment(tctx, "%.2f ops/second\n", count/timeval_elapsed(&tv));
3604 smb2_util_close(trees[0], io.smb2.out.file.handle);
3605 smb2_util_unlink(trees[0], BASEDIR "\\test.dat");
3606 smb2_deltree(trees[0], BASEDIR);
3607 talloc_free(mem_ctx);
3611 static struct hold_oplock_info {
3613 bool close_on_break;
3614 uint32_t share_access;
3615 struct smb2_handle handle;
3617 { BASEDIR "\\notshared_close", true,
3618 NTCREATEX_SHARE_ACCESS_NONE, },
3619 { BASEDIR "\\notshared_noclose", false,
3620 NTCREATEX_SHARE_ACCESS_NONE, },
3621 { BASEDIR "\\shared_close", true,
3622 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3623 { BASEDIR "\\shared_noclose", false,
3624 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3627 static bool torture_oplock_handler_hold(struct smb2_transport *transport,
3628 const struct smb2_handle *handle,
3629 uint8_t level, void *private_data)
3631 struct hold_oplock_info *info;
3634 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3635 if (smb2_util_handle_equal(hold_info[i].handle, *handle))
3639 if (i == ARRAY_SIZE(hold_info)) {
3640 printf("oplock break for unknown handle 0x%llx%llx\n",
3641 (unsigned long long) handle->data[0],
3642 (unsigned long long) handle->data[1]);
3646 info = &hold_info[i];
3648 if (info->close_on_break) {
3649 printf("oplock break on %s - closing\n", info->fname);
3650 torture_oplock_handler_close(transport, handle,
3651 level, private_data);
3655 printf("oplock break on %s - acking break\n", info->fname);
3656 printf("Acking to none in oplock handler\n");
3658 torture_oplock_handler_ack_to_none(transport, handle,
3659 level, private_data);
3664 used for manual testing of oplocks - especially interaction with
3665 other filesystems (such as NFS and local access)
3667 bool test_smb2_hold_oplock(struct torture_context *tctx,
3668 struct smb2_tree *tree)
3670 struct torture_context *mem_ctx = talloc_new(tctx);
3671 struct tevent_context *ev = tctx->ev;
3673 struct smb2_handle h;
3676 torture_comment(tctx, "Setting up open files with oplocks in %s\n",
3679 status = torture_smb2_testdir(tree, BASEDIR, &h);
3680 torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3682 tree->session->transport->oplock.handler = torture_oplock_handler_hold;
3683 tree->session->transport->oplock.private_data = tree;
3685 /* setup the files */
3686 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3690 ZERO_STRUCT(io.smb2);
3691 io.generic.level = RAW_OPEN_SMB2;
3692 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3693 io.smb2.in.alloc_size = 0;
3694 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3695 io.smb2.in.share_access = hold_info[i].share_access;
3696 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3697 io.smb2.in.create_options = 0;
3698 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3699 io.smb2.in.security_flags = 0;
3700 io.smb2.in.fname = hold_info[i].fname;
3701 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3702 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3704 torture_comment(tctx, "opening %s\n", hold_info[i].fname);
3706 status = smb2_create(tree, mem_ctx, &(io.smb2));
3707 if (!NT_STATUS_IS_OK(status)) {
3708 torture_comment(tctx, "Failed to open %s - %s\n",
3709 hold_info[i].fname, nt_errstr(status));
3713 if (io.smb2.out.oplock_level != SMB2_OPLOCK_LEVEL_BATCH) {
3714 torture_comment(tctx, "Oplock not granted for %s - "
3715 "expected %d but got %d\n",
3717 SMB2_OPLOCK_LEVEL_BATCH,
3718 io.smb2.out.oplock_level);
3721 hold_info[i].handle = io.smb2.out.file.handle;
3723 /* make the file non-zero size */
3724 status = smb2_util_write(tree, hold_info[i].handle, &c, 0, 1);
3725 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3726 torture_comment(tctx, "Failed to write to file\n");
3731 torture_comment(tctx, "Waiting for oplock events\n");
3732 tevent_loop_wait(ev);
3733 smb2_deltree(tree, BASEDIR);
3734 talloc_free(mem_ctx);