ad-dc: use exit_daemon() to communicate status of startup to systemd
[Samba.git] / source4 / torture / raw / oplock.c
bloba4f6a0555ef345ff3387a70b4a5a871c0c1b51fb
1 /*
2 Unix SMB/CIFS implementation.
3 basic raw test suite for oplocks
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "libcli/raw/libcliraw.h"
22 #include "libcli/raw/raw_proto.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
25 #include "lib/events/events.h"
26 #include "param/param.h"
27 #include "lib/cmdline/popt_common.h"
28 #include "libcli/resolve/resolve.h"
29 #include "torture/raw/proto.h"
31 #define CHECK_VAL(v, correct) do { \
32 if ((v) != (correct)) { \
33 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
34 __location__, #v, (int)v, (int)correct); \
35 ret = false; \
36 }} while (0)
38 #define CHECK_RANGE(v, min, max) do { \
39 if ((v) < (min) || (v) > (max)) { \
40 torture_warning(tctx, "(%s): wrong value for %s got " \
41 "%d - should be between %d and %d\n", \
42 __location__, #v, (int)v, (int)min, (int)max); \
43 }} while (0)
45 #define CHECK_STRMATCH(v, correct) do { \
46 if (!v || strstr((v),(correct)) == NULL) { \
47 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got '%s' - should be '%s'\n", \
48 __location__, #v, v?v:"NULL", correct); \
49 ret = false; \
50 } \
51 } while (0)
53 #define CHECK_STATUS(tctx, status, correct) do { \
54 if (!NT_STATUS_EQUAL(status, correct)) { \
55 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
56 nt_errstr(status), nt_errstr(correct)); \
57 ret = false; \
58 goto done; \
59 }} while (0)
62 static struct {
63 int fnum;
64 uint8_t level;
65 int count;
66 int failures;
67 } break_info;
69 #define BASEDIR "\\test_oplock"
72 a handler function for oplock break requests. Ack it as a break to level II if possible
74 static bool oplock_handler_ack_to_given(struct smbcli_transport *transport,
75 uint16_t tid, uint16_t fnum,
76 uint8_t level, void *private_data)
78 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
79 const char *name;
81 break_info.fnum = fnum;
82 break_info.level = level;
83 break_info.count++;
85 switch (level) {
86 case OPLOCK_BREAK_TO_LEVEL_II:
87 name = "level II";
88 break;
89 case OPLOCK_BREAK_TO_NONE:
90 name = "none";
91 break;
92 default:
93 name = "unknown";
94 break_info.failures++;
96 printf("Acking to %s [0x%02X] in oplock handler\n",
97 name, level);
99 return smbcli_oplock_ack(tree, fnum, level);
103 a handler function for oplock break requests. Ack it as a break to none
105 static bool oplock_handler_ack_to_none(struct smbcli_transport *transport,
106 uint16_t tid, uint16_t fnum,
107 uint8_t level, void *private_data)
109 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
110 break_info.fnum = fnum;
111 break_info.level = level;
112 break_info.count++;
114 printf("Acking to none in oplock handler\n");
116 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
120 a handler function for oplock break requests. Let it timeout
122 static bool oplock_handler_timeout(struct smbcli_transport *transport,
123 uint16_t tid, uint16_t fnum,
124 uint8_t level, void *private_data)
126 break_info.fnum = fnum;
127 break_info.level = level;
128 break_info.count++;
130 printf("Let oplock break timeout\n");
131 return true;
134 static void oplock_handler_close_recv(struct smbcli_request *req)
136 NTSTATUS status;
137 status = smbcli_request_simple_recv(req);
138 if (!NT_STATUS_IS_OK(status)) {
139 printf("close failed in oplock_handler_close\n");
140 break_info.failures++;
145 a handler function for oplock break requests - close the file
147 static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t tid,
148 uint16_t fnum, uint8_t level, void *private_data)
150 union smb_close io;
151 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
152 struct smbcli_request *req;
154 break_info.fnum = fnum;
155 break_info.level = level;
156 break_info.count++;
158 io.close.level = RAW_CLOSE_CLOSE;
159 io.close.in.file.fnum = fnum;
160 io.close.in.write_time = 0;
161 req = smb_raw_close_send(tree, &io);
162 if (req == NULL) {
163 printf("failed to send close in oplock_handler_close\n");
164 return false;
167 req->async.fn = oplock_handler_close_recv;
168 req->async.private_data = NULL;
170 return true;
173 static bool open_connection_no_level2_oplocks(struct torture_context *tctx,
174 struct smbcli_state **c)
176 NTSTATUS status;
177 struct smbcli_options options;
178 struct smbcli_session_options session_options;
180 lpcfg_smbcli_options(tctx->lp_ctx, &options);
181 lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);
183 options.use_level2_oplocks = false;
185 status = smbcli_full_connection(tctx, c,
186 torture_setting_string(tctx, "host", NULL),
187 lpcfg_smb_ports(tctx->lp_ctx),
188 torture_setting_string(tctx, "share", NULL),
189 NULL, lpcfg_socket_options(tctx->lp_ctx), cmdline_credentials,
190 lpcfg_resolve_context(tctx->lp_ctx),
191 tctx->ev, &options, &session_options,
192 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
193 if (!NT_STATUS_IS_OK(status)) {
194 torture_comment(tctx, "Failed to open connection - %s\n",
195 nt_errstr(status));
196 return false;
199 return true;
203 Timer handler function notifies the registering function that time is up
205 static void timeout_cb(struct tevent_context *ev,
206 struct tevent_timer *te,
207 struct timeval current_time,
208 void *private_data)
210 bool *timesup = (bool *)private_data;
211 *timesup = true;
212 return;
216 Wait a short period of time to receive a single oplock break request
218 static void torture_wait_for_oplock_break(struct torture_context *tctx)
220 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
221 struct tevent_timer *te = NULL;
222 struct timeval ne;
223 bool timesup = false;
224 int old_count = break_info.count;
226 /* Wait .1 seconds for an oplock break */
227 ne = tevent_timeval_current_ofs(0, 100000);
229 if ((te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup))
230 == NULL)
232 torture_comment(tctx, "Failed to wait for an oplock break. "
233 "test results may not be accurate.");
234 goto done;
237 while (!timesup && break_info.count < old_count + 1) {
238 if (tevent_loop_once(tctx->ev) != 0) {
239 torture_comment(tctx, "Failed to wait for an oplock "
240 "break. test results may not be "
241 "accurate.");
242 goto done;
246 done:
247 /* We don't know if the timed event fired and was freed, we received
248 * our oplock break, or some other event triggered the loop. Thus,
249 * we create a tmp_ctx to be able to safely free/remove the timed
250 * event in all 3 cases. */
251 talloc_free(tmp_ctx);
253 return;
256 static uint8_t get_break_level1_to_none_count(struct torture_context *tctx)
258 return torture_setting_bool(tctx, "2_step_break_to_none", false) ?
259 2 : 1;
262 static uint8_t get_setinfo_break_count(struct torture_context *tctx)
264 if (TARGET_IS_W2K12(tctx)) {
265 return 2;
267 if (TARGET_IS_SAMBA3(tctx)) {
268 return 2;
270 return 1;
273 static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
275 const char *fname = BASEDIR "\\test_exclusive1.dat";
276 NTSTATUS status;
277 bool ret = true;
278 union smb_open io;
279 union smb_unlink unl;
280 uint16_t fnum=0;
282 if (!torture_setup_dir(cli1, BASEDIR)) {
283 return false;
286 /* cleanup */
287 smbcli_unlink(cli1->tree, fname);
289 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
292 base ntcreatex parms
294 io.generic.level = RAW_OPEN_NTCREATEX;
295 io.ntcreatex.in.root_fid.fnum = 0;
296 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
297 io.ntcreatex.in.alloc_size = 0;
298 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
299 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
300 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
301 io.ntcreatex.in.create_options = 0;
302 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
303 io.ntcreatex.in.security_flags = 0;
304 io.ntcreatex.in.fname = fname;
306 torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
307 ZERO_STRUCT(break_info);
308 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
310 status = smb_raw_open(cli1->tree, tctx, &io);
311 CHECK_STATUS(tctx, status, NT_STATUS_OK);
312 fnum = io.ntcreatex.out.file.fnum;
313 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
315 torture_comment(tctx, "a 2nd open should not cause a break\n");
316 status = smb_raw_open(cli2->tree, tctx, &io);
317 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
318 torture_wait_for_oplock_break(tctx);
319 CHECK_VAL(break_info.count, 0);
320 CHECK_VAL(break_info.failures, 0);
322 torture_comment(tctx, "unlink it - should also be no break\n");
323 unl.unlink.in.pattern = fname;
324 unl.unlink.in.attrib = 0;
325 status = smb_raw_unlink(cli2->tree, &unl);
326 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
327 torture_wait_for_oplock_break(tctx);
328 CHECK_VAL(break_info.count, 0);
329 CHECK_VAL(break_info.failures, 0);
331 smbcli_close(cli1->tree, fnum);
333 done:
334 smb_raw_exit(cli1->session);
335 smb_raw_exit(cli2->session);
336 smbcli_deltree(cli1->tree, BASEDIR);
337 return ret;
340 static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
342 const char *fname = BASEDIR "\\test_exclusive2.dat";
343 NTSTATUS status;
344 bool ret = true;
345 union smb_open io;
346 union smb_unlink unl;
347 uint16_t fnum=0, fnum2=0;
349 if (!torture_setup_dir(cli1, BASEDIR)) {
350 return false;
353 /* cleanup */
354 smbcli_unlink(cli1->tree, fname);
356 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
359 base ntcreatex parms
361 io.generic.level = RAW_OPEN_NTCREATEX;
362 io.ntcreatex.in.root_fid.fnum = 0;
363 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
364 io.ntcreatex.in.alloc_size = 0;
365 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
366 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
367 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
368 io.ntcreatex.in.create_options = 0;
369 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
370 io.ntcreatex.in.security_flags = 0;
371 io.ntcreatex.in.fname = fname;
373 torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
374 ZERO_STRUCT(break_info);
375 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
376 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
377 NTCREATEX_SHARE_ACCESS_WRITE|
378 NTCREATEX_SHARE_ACCESS_DELETE;
380 status = smb_raw_open(cli1->tree, tctx, &io);
381 CHECK_STATUS(tctx, status, NT_STATUS_OK);
382 fnum = io.ntcreatex.out.file.fnum;
383 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
385 torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
386 status = smb_raw_open(cli2->tree, tctx, &io);
387 CHECK_STATUS(tctx, status, NT_STATUS_OK);
388 fnum2 = io.ntcreatex.out.file.fnum;
389 torture_wait_for_oplock_break(tctx);
390 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
391 CHECK_VAL(break_info.count, 1);
392 CHECK_VAL(break_info.fnum, fnum);
393 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
394 CHECK_VAL(break_info.failures, 0);
395 ZERO_STRUCT(break_info);
397 /* now we have 2 level II oplocks... */
398 torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
399 unl.unlink.in.pattern = fname;
400 unl.unlink.in.attrib = 0;
401 status = smb_raw_unlink(cli2->tree, &unl);
402 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
403 torture_wait_for_oplock_break(tctx);
404 CHECK_VAL(break_info.count, 0);
405 CHECK_VAL(break_info.failures, 0);
407 torture_comment(tctx, "close 1st handle\n");
408 smbcli_close(cli1->tree, fnum);
410 torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
411 unl.unlink.in.pattern = fname;
412 unl.unlink.in.attrib = 0;
413 status = smb_raw_unlink(cli2->tree, &unl);
414 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
415 torture_wait_for_oplock_break(tctx);
416 CHECK_VAL(break_info.count, 0);
417 CHECK_VAL(break_info.failures, 0);
419 torture_comment(tctx, "close 2nd handle\n");
420 smbcli_close(cli2->tree, fnum2);
422 torture_comment(tctx, "unlink it\n");
423 unl.unlink.in.pattern = fname;
424 unl.unlink.in.attrib = 0;
425 status = smb_raw_unlink(cli2->tree, &unl);
426 CHECK_STATUS(tctx, status, NT_STATUS_OK);
427 torture_wait_for_oplock_break(tctx);
428 CHECK_VAL(break_info.count, 0);
429 CHECK_VAL(break_info.failures, 0);
431 done:
432 smb_raw_exit(cli1->session);
433 smb_raw_exit(cli2->session);
434 smbcli_deltree(cli1->tree, BASEDIR);
435 return ret;
438 static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
440 const char *fname = BASEDIR "\\test_exclusive3.dat";
441 NTSTATUS status;
442 bool ret = true;
443 union smb_open io;
444 union smb_setfileinfo sfi;
445 uint16_t fnum=0;
447 if (!torture_setup_dir(cli1, BASEDIR)) {
448 return false;
451 /* cleanup */
452 smbcli_unlink(cli1->tree, fname);
454 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
457 base ntcreatex parms
459 io.generic.level = RAW_OPEN_NTCREATEX;
460 io.ntcreatex.in.root_fid.fnum = 0;
461 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
462 io.ntcreatex.in.alloc_size = 0;
463 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
464 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
465 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
466 io.ntcreatex.in.create_options = 0;
467 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
468 io.ntcreatex.in.security_flags = 0;
469 io.ntcreatex.in.fname = fname;
471 torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
473 ZERO_STRUCT(break_info);
474 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
476 status = smb_raw_open(cli1->tree, tctx, &io);
477 CHECK_STATUS(tctx, status, NT_STATUS_OK);
478 fnum = io.ntcreatex.out.file.fnum;
479 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
481 torture_comment(tctx, "setpathinfo EOF should trigger a break to none\n");
482 ZERO_STRUCT(sfi);
483 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
484 sfi.generic.in.file.path = fname;
485 sfi.end_of_file_info.in.size = 100;
487 status = smb_raw_setpathinfo(cli2->tree, &sfi);
489 CHECK_STATUS(tctx, status, NT_STATUS_OK);
490 torture_wait_for_oplock_break(tctx);
491 CHECK_VAL(break_info.count, get_setinfo_break_count(tctx));
492 CHECK_VAL(break_info.failures, 0);
493 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
495 smbcli_close(cli1->tree, fnum);
497 done:
498 smb_raw_exit(cli1->session);
499 smb_raw_exit(cli2->session);
500 smbcli_deltree(cli1->tree, BASEDIR);
501 return ret;
504 static bool test_raw_oplock_exclusive4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
506 const char *fname = BASEDIR "\\test_exclusive4.dat";
507 NTSTATUS status;
508 bool ret = true;
509 union smb_open io;
510 uint16_t fnum=0, fnum2=0;
512 if (!torture_setup_dir(cli1, BASEDIR)) {
513 return false;
516 /* cleanup */
517 smbcli_unlink(cli1->tree, fname);
519 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
522 base ntcreatex parms
524 io.generic.level = RAW_OPEN_NTCREATEX;
525 io.ntcreatex.in.root_fid.fnum = 0;
526 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
527 io.ntcreatex.in.alloc_size = 0;
528 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
529 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
530 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
531 io.ntcreatex.in.create_options = 0;
532 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
533 io.ntcreatex.in.security_flags = 0;
534 io.ntcreatex.in.fname = fname;
536 torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
537 ZERO_STRUCT(break_info);
538 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
540 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
541 status = smb_raw_open(cli1->tree, tctx, &io);
542 CHECK_STATUS(tctx, status, NT_STATUS_OK);
543 fnum = io.ntcreatex.out.file.fnum;
544 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
546 ZERO_STRUCT(break_info);
547 torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
549 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
550 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
551 status = smb_raw_open(cli2->tree, tctx, &io);
552 CHECK_STATUS(tctx, status, NT_STATUS_OK);
553 fnum2 = io.ntcreatex.out.file.fnum;
554 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
555 torture_wait_for_oplock_break(tctx);
556 CHECK_VAL(break_info.count, 0);
557 CHECK_VAL(break_info.failures, 0);
560 * Open another non-stat open. This reproduces bug 10216. Make sure it
561 * won't happen again...
563 io.ntcreatex.in.flags = 0;
564 io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
565 status = smb_raw_open(cli2->tree, tctx, &io);
566 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
567 torture_wait_for_oplock_break(tctx);
568 CHECK_VAL(break_info.count, 0);
569 CHECK_VAL(break_info.failures, 0);
571 smbcli_close(cli1->tree, fnum);
572 smbcli_close(cli2->tree, fnum2);
574 done:
575 smb_raw_exit(cli1->session);
576 smb_raw_exit(cli2->session);
577 smbcli_deltree(cli1->tree, BASEDIR);
578 return ret;
581 static bool test_raw_oplock_exclusive5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
583 const char *fname = BASEDIR "\\test_exclusive5.dat";
584 NTSTATUS status;
585 bool ret = true;
586 union smb_open io;
587 uint16_t fnum=0, fnum2=0;
589 if (!torture_setup_dir(cli1, BASEDIR)) {
590 return false;
593 /* cleanup */
594 smbcli_unlink(cli1->tree, fname);
596 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
597 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
600 base ntcreatex parms
602 io.generic.level = RAW_OPEN_NTCREATEX;
603 io.ntcreatex.in.root_fid.fnum = 0;
604 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
605 io.ntcreatex.in.alloc_size = 0;
606 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
607 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
608 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
609 io.ntcreatex.in.create_options = 0;
610 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
611 io.ntcreatex.in.security_flags = 0;
612 io.ntcreatex.in.fname = fname;
614 torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
615 ZERO_STRUCT(break_info);
616 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
619 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
620 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
621 NTCREATEX_SHARE_ACCESS_WRITE|
622 NTCREATEX_SHARE_ACCESS_DELETE;
623 status = smb_raw_open(cli1->tree, tctx, &io);
624 CHECK_STATUS(tctx, status, NT_STATUS_OK);
625 fnum = io.ntcreatex.out.file.fnum;
626 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
628 ZERO_STRUCT(break_info);
630 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
632 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
633 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
634 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
635 status = smb_raw_open(cli2->tree, tctx, &io);
636 CHECK_STATUS(tctx, status, NT_STATUS_OK);
637 fnum2 = io.ntcreatex.out.file.fnum;
638 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
639 torture_wait_for_oplock_break(tctx);
640 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
641 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
642 CHECK_VAL(break_info.failures, 0);
644 smbcli_close(cli1->tree, fnum);
645 smbcli_close(cli2->tree, fnum2);
647 done:
648 smb_raw_exit(cli1->session);
649 smb_raw_exit(cli2->session);
650 smbcli_deltree(cli1->tree, BASEDIR);
651 return ret;
654 static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
656 const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
657 const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
658 NTSTATUS status;
659 bool ret = true;
660 union smb_open io;
661 union smb_rename rn;
662 uint16_t fnum=0;
664 if (!torture_setup_dir(cli1, BASEDIR)) {
665 return false;
668 /* cleanup */
669 smbcli_unlink(cli1->tree, fname1);
670 smbcli_unlink(cli1->tree, fname2);
672 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
675 base ntcreatex parms
677 io.generic.level = RAW_OPEN_NTCREATEX;
678 io.ntcreatex.in.root_fid.fnum = 0;
679 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
680 io.ntcreatex.in.alloc_size = 0;
681 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
682 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
683 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
684 io.ntcreatex.in.create_options = 0;
685 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
686 io.ntcreatex.in.security_flags = 0;
687 io.ntcreatex.in.fname = fname1;
689 torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
690 "oplock (share mode: none)\n");
691 ZERO_STRUCT(break_info);
692 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
694 status = smb_raw_open(cli1->tree, tctx, &io);
695 CHECK_STATUS(tctx, status, NT_STATUS_OK);
696 fnum = io.ntcreatex.out.file.fnum;
697 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
699 torture_comment(tctx, "rename should not generate a break but get a "
700 "sharing violation\n");
701 ZERO_STRUCT(rn);
702 rn.generic.level = RAW_RENAME_RENAME;
703 rn.rename.in.pattern1 = fname1;
704 rn.rename.in.pattern2 = fname2;
705 rn.rename.in.attrib = 0;
707 torture_comment(tctx, "trying rename while first file open\n");
708 status = smb_raw_rename(cli2->tree, &rn);
710 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
711 torture_wait_for_oplock_break(tctx);
712 CHECK_VAL(break_info.count, 0);
713 CHECK_VAL(break_info.failures, 0);
715 smbcli_close(cli1->tree, fnum);
717 done:
718 smb_raw_exit(cli1->session);
719 smb_raw_exit(cli2->session);
720 smbcli_deltree(cli1->tree, BASEDIR);
721 return ret;
725 * Exclusive version of batch19
727 static bool test_raw_oplock_exclusive7(struct torture_context *tctx,
728 struct smbcli_state *cli1, struct smbcli_state *cli2)
730 const char *fname1 = BASEDIR "\\test_exclusiv6_1.dat";
731 const char *fname2 = BASEDIR "\\test_exclusiv6_2.dat";
732 const char *fname3 = BASEDIR "\\test_exclusiv6_3.dat";
733 NTSTATUS status;
734 bool ret = true;
735 union smb_open io;
736 union smb_fileinfo qfi;
737 union smb_setfileinfo sfi;
738 uint16_t fnum=0;
739 uint16_t fnum2 = 0;
741 if (!torture_setup_dir(cli1, BASEDIR)) {
742 return false;
745 /* cleanup */
746 smbcli_unlink(cli1->tree, fname1);
747 smbcli_unlink(cli1->tree, fname2);
748 smbcli_unlink(cli1->tree, fname3);
750 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
751 cli1->tree);
754 base ntcreatex parms
756 io.generic.level = RAW_OPEN_NTCREATEX;
757 io.ntcreatex.in.root_fid.fnum = 0;
758 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
759 io.ntcreatex.in.alloc_size = 0;
760 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
761 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
762 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
763 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
764 io.ntcreatex.in.create_options = 0;
765 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
766 io.ntcreatex.in.security_flags = 0;
767 io.ntcreatex.in.fname = fname1;
769 torture_comment(tctx, "open a file with an exclusive oplock (share "
770 "mode: none)\n");
771 ZERO_STRUCT(break_info);
772 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
773 NTCREATEX_FLAGS_REQUEST_OPLOCK;
774 status = smb_raw_open(cli1->tree, tctx, &io);
775 CHECK_STATUS(tctx, status, NT_STATUS_OK);
776 fnum = io.ntcreatex.out.file.fnum;
777 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
779 torture_comment(tctx, "setpathinfo rename info should trigger a break "
780 "to none\n");
781 ZERO_STRUCT(sfi);
782 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
783 sfi.generic.in.file.path = fname1;
784 sfi.rename_information.in.overwrite = 0;
785 sfi.rename_information.in.root_fid = 0;
786 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
788 status = smb_raw_setpathinfo(cli2->tree, &sfi);
789 CHECK_STATUS(tctx, status, NT_STATUS_OK);
791 torture_wait_for_oplock_break(tctx);
792 CHECK_VAL(break_info.failures, 0);
794 if (TARGET_IS_WINXP(tctx) || TARGET_IS_W2K12(tctx)) {
795 /* XP incorrectly breaks to level2. */
796 CHECK_VAL(break_info.count, 1);
797 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
798 } else {
799 /* Exclusive oplocks should not be broken on rename. */
800 CHECK_VAL(break_info.failures, 0);
801 CHECK_VAL(break_info.count, 0);
804 ZERO_STRUCT(qfi);
805 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
806 qfi.generic.in.file.fnum = fnum;
808 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
809 CHECK_STATUS(tctx, status, NT_STATUS_OK);
810 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
812 /* Try breaking to level2 and then see if rename breaks the level2.*/
813 ZERO_STRUCT(break_info);
814 io.ntcreatex.in.fname = fname2;
815 status = smb_raw_open(cli2->tree, tctx, &io);
816 CHECK_STATUS(tctx, status, NT_STATUS_OK);
817 fnum2 = io.ntcreatex.out.file.fnum;
818 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
820 torture_wait_for_oplock_break(tctx);
821 CHECK_VAL(break_info.failures, 0);
823 if (TARGET_IS_WINXP(tctx)) {
824 /* XP already broke to level2. */
825 CHECK_VAL(break_info.failures, 0);
826 CHECK_VAL(break_info.count, 0);
827 } else if (TARGET_IS_W2K12(tctx)) {
828 /* no break */
829 CHECK_VAL(break_info.count, 0);
830 CHECK_VAL(break_info.level, 0);
831 } else {
832 /* Break to level 2 expected. */
833 CHECK_VAL(break_info.count, 1);
834 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
837 ZERO_STRUCT(break_info);
838 sfi.generic.in.file.path = fname2;
839 sfi.rename_information.in.overwrite = 0;
840 sfi.rename_information.in.root_fid = 0;
841 sfi.rename_information.in.new_name = fname1+strlen(BASEDIR)+1;
843 status = smb_raw_setpathinfo(cli2->tree, &sfi);
844 CHECK_STATUS(tctx, status, NT_STATUS_OK);
846 /* Level2 oplocks are not broken on rename. */
847 torture_wait_for_oplock_break(tctx);
848 CHECK_VAL(break_info.failures, 0);
849 CHECK_VAL(break_info.count, 0);
851 /* Close and re-open file with oplock. */
852 smbcli_close(cli1->tree, fnum);
853 status = smb_raw_open(cli1->tree, tctx, &io);
854 CHECK_STATUS(tctx, status, NT_STATUS_OK);
855 fnum = io.ntcreatex.out.file.fnum;
856 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
858 torture_comment(tctx, "setfileinfo rename info on a client's own fid "
859 "should not trigger a break nor a violation\n");
860 ZERO_STRUCT(break_info);
861 ZERO_STRUCT(sfi);
862 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
863 sfi.generic.in.file.fnum = fnum;
864 sfi.rename_information.in.overwrite = 0;
865 sfi.rename_information.in.root_fid = 0;
866 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
868 status = smb_raw_setfileinfo(cli1->tree, &sfi);
869 CHECK_STATUS(tctx, status, NT_STATUS_OK);
871 torture_wait_for_oplock_break(tctx);
872 if (TARGET_IS_WINXP(tctx)) {
873 /* XP incorrectly breaks to level2. */
874 CHECK_VAL(break_info.count, 1);
875 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
876 } else {
877 CHECK_VAL(break_info.count, 0);
880 ZERO_STRUCT(qfi);
881 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
882 qfi.generic.in.file.fnum = fnum;
884 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
885 CHECK_STATUS(tctx, status, NT_STATUS_OK);
886 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
888 done:
889 smbcli_close(cli1->tree, fnum);
890 smbcli_close(cli2->tree, fnum2);
892 smb_raw_exit(cli1->session);
893 smb_raw_exit(cli2->session);
894 smbcli_deltree(cli1->tree, BASEDIR);
895 return ret;
898 static bool test_raw_oplock_exclusive8(struct torture_context *tctx,
899 struct smbcli_state *cli1,
900 struct smbcli_state *cli2)
902 const char *fname = BASEDIR "\\test_exclusive8.dat";
903 NTSTATUS status;
904 bool ret = true;
905 union smb_open io;
906 uint16_t fnum1 = 0;
907 uint16_t fnum2 = 0;
908 uint16_t fnum3 = 0;
910 if (!torture_setup_dir(cli1, BASEDIR)) {
911 return false;
914 /* cleanup */
915 smbcli_unlink(cli1->tree, fname);
917 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
918 cli1->tree);
921 base ntcreatex parms
923 io.generic.level = RAW_OPEN_NTCREATEX;
924 io.ntcreatex.in.root_fid.fnum = 0;
925 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
926 io.ntcreatex.in.alloc_size = 0;
927 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
928 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
929 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
930 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
931 io.ntcreatex.in.create_options = 0;
932 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
933 io.ntcreatex.in.security_flags = 0;
934 io.ntcreatex.in.fname = fname;
936 torture_comment(tctx, "open a file with an exclusive oplock (share "
937 "mode: all)\n");
938 ZERO_STRUCT(break_info);
939 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
940 NTCREATEX_FLAGS_REQUEST_OPLOCK;
941 status = smb_raw_open(cli1->tree, tctx, &io);
942 CHECK_STATUS(tctx, status, NT_STATUS_OK);
943 fnum1 = io.ntcreatex.out.file.fnum;
944 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
946 torture_comment(tctx, "second open with delete should trigger a "
947 "break\n");
949 io.ntcreatex.in.access_mask = SEC_STD_DELETE;
950 io.ntcreatex.in.flags = 0;
951 status = smb_raw_open(cli2->tree, tctx, &io);
952 CHECK_STATUS(tctx, status, NT_STATUS_OK);
953 fnum2 = io.ntcreatex.out.file.fnum;
954 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
955 CHECK_VAL(break_info.failures, 0);
956 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
958 /* Trigger a little panic in "old" samba code.. */
959 status = smb_raw_open(cli2->tree, tctx, &io);
960 CHECK_STATUS(tctx, status, NT_STATUS_OK);
961 fnum3 = io.ntcreatex.out.file.fnum;
963 smbcli_close(cli2->tree, fnum3);
964 smbcli_close(cli2->tree, fnum2);
965 smbcli_close(cli1->tree, fnum1);
967 done:
968 smbcli_deltree(cli1->tree, BASEDIR);
969 smb_raw_exit(cli1->session);
970 smb_raw_exit(cli2->session);
971 return ret;
974 static bool test_raw_oplock_exclusive9(struct torture_context *tctx,
975 struct smbcli_state *cli1,
976 struct smbcli_state *cli2)
978 const char *fname = BASEDIR "\\test_exclusive9.dat";
979 NTSTATUS status;
980 bool ret = true;
981 union smb_open io;
982 uint16_t fnum=0, fnum2=0;
983 int i;
985 struct {
986 uint32_t create_disposition;
987 uint32_t break_level;
988 } levels[] = {
989 { NTCREATEX_DISP_SUPERSEDE, OPLOCK_BREAK_TO_NONE },
990 { NTCREATEX_DISP_OPEN, OPLOCK_BREAK_TO_LEVEL_II },
991 { NTCREATEX_DISP_OVERWRITE_IF, OPLOCK_BREAK_TO_NONE },
992 { NTCREATEX_DISP_OPEN_IF, OPLOCK_BREAK_TO_LEVEL_II },
995 if (!torture_setup_dir(cli1, BASEDIR)) {
996 return false;
999 /* cleanup */
1000 smbcli_unlink(cli1->tree, fname);
1002 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
1003 cli1->tree);
1004 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given,
1005 cli1->tree);
1008 base ntcreatex parms
1010 io.generic.level = RAW_OPEN_NTCREATEX;
1011 io.ntcreatex.in.root_fid.fnum = 0;
1012 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1013 io.ntcreatex.in.alloc_size = 0;
1014 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1015 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1016 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1017 io.ntcreatex.in.create_options = 0;
1018 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1019 io.ntcreatex.in.security_flags = 0;
1020 io.ntcreatex.in.fname = fname;
1022 ZERO_STRUCT(break_info);
1023 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
1024 cli1->tree);
1026 for (i=0; i<ARRAY_SIZE(levels); i++) {
1028 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1029 NTCREATEX_FLAGS_REQUEST_OPLOCK;
1030 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1031 NTCREATEX_SHARE_ACCESS_WRITE|
1032 NTCREATEX_SHARE_ACCESS_DELETE;
1033 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1034 status = smb_raw_open(cli1->tree, tctx, &io);
1035 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1036 fnum = io.ntcreatex.out.file.fnum;
1037 CHECK_VAL(io.ntcreatex.out.oplock_level,
1038 EXCLUSIVE_OPLOCK_RETURN);
1040 ZERO_STRUCT(break_info);
1042 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1043 NTCREATEX_FLAGS_REQUEST_OPLOCK;
1044 io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
1045 io.ntcreatex.in.open_disposition =
1046 levels[i].create_disposition;
1047 status = smb_raw_open(cli2->tree, tctx, &io);
1048 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1049 fnum2 = io.ntcreatex.out.file.fnum;
1050 CHECK_VAL(io.ntcreatex.out.oplock_level,
1051 LEVEL_II_OPLOCK_RETURN);
1052 torture_wait_for_oplock_break(tctx);
1053 CHECK_VAL(break_info.count, 1);
1054 CHECK_VAL(break_info.level, levels[i].break_level);
1055 CHECK_VAL(break_info.failures, 0);
1057 smbcli_close(cli1->tree, fnum);
1058 smbcli_close(cli2->tree, fnum2);
1061 done:
1062 smb_raw_exit(cli1->session);
1063 smb_raw_exit(cli2->session);
1064 smbcli_deltree(cli1->tree, BASEDIR);
1065 return ret;
1068 static bool test_raw_oplock_level_ii_1(struct torture_context *tctx,
1069 struct smbcli_state *cli1,
1070 struct smbcli_state *cli2)
1072 const char *fname = BASEDIR "\\test_level_ii_1.dat";
1073 NTSTATUS status;
1074 bool ret = true;
1075 union smb_open io;
1076 uint16_t fnum=0, fnum2=0;
1077 char c = 0;
1078 ssize_t written;
1080 if (!torture_setup_dir(cli1, BASEDIR)) {
1081 return false;
1084 /* cleanup */
1085 smbcli_unlink(cli1->tree, fname);
1087 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
1088 cli1->tree);
1089 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given,
1090 cli1->tree);
1093 base ntcreatex parms
1095 io.generic.level = RAW_OPEN_NTCREATEX;
1096 io.ntcreatex.in.root_fid.fnum = 0;
1097 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1098 io.ntcreatex.in.alloc_size = 0;
1099 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1100 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1101 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1102 io.ntcreatex.in.create_options = 0;
1103 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1104 io.ntcreatex.in.security_flags = 0;
1105 io.ntcreatex.in.fname = fname;
1107 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1108 NTCREATEX_FLAGS_REQUEST_OPLOCK;
1109 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1110 NTCREATEX_SHARE_ACCESS_WRITE|
1111 NTCREATEX_SHARE_ACCESS_DELETE;
1112 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1113 status = smb_raw_open(cli1->tree, tctx, &io);
1114 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1115 fnum = io.ntcreatex.out.file.fnum;
1116 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
1118 ZERO_STRUCT(break_info);
1120 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1121 NTCREATEX_FLAGS_REQUEST_OPLOCK;
1122 io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA;
1123 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1124 status = smb_raw_open(cli2->tree, tctx, &io);
1125 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1126 fnum2 = io.ntcreatex.out.file.fnum;
1127 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1128 torture_wait_for_oplock_break(tctx);
1129 CHECK_VAL(break_info.count, 1);
1130 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1131 CHECK_VAL(break_info.failures, 0);
1133 status = smbcli_close(cli2->tree, fnum2);
1134 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1137 * fnum1 has a level2 oplock now
1140 ZERO_STRUCT(break_info);
1143 * Don't answer the break to none that will come in
1146 smbcli_oplock_handler(cli1->transport, oplock_handler_timeout,
1147 cli1->tree);
1149 io.ntcreatex.in.flags = 0;
1150 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1152 status = smb_raw_open(cli2->tree, tctx, &io);
1153 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1154 fnum2 = io.ntcreatex.out.file.fnum;
1155 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1156 torture_wait_for_oplock_break(tctx);
1157 CHECK_VAL(break_info.count, 1);
1158 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
1159 CHECK_VAL(break_info.failures, 0);
1162 * Check that a write does not cause another break. This used to be a
1163 * bug in smbd.
1166 ZERO_STRUCT(break_info);
1167 written = smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
1168 CHECK_VAL(written, 1);
1169 torture_wait_for_oplock_break(tctx);
1170 CHECK_VAL(break_info.count, 0);
1171 CHECK_VAL(break_info.failures, 0);
1173 status = smbcli_close(cli2->tree, fnum2);
1174 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1175 status = smbcli_close(cli1->tree, fnum);
1176 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1178 done:
1179 smb_raw_exit(cli1->session);
1180 smb_raw_exit(cli2->session);
1181 smbcli_deltree(cli1->tree, BASEDIR);
1182 return ret;
1185 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1187 const char *fname = BASEDIR "\\test_batch1.dat";
1188 NTSTATUS status;
1189 bool ret = true;
1190 union smb_open io;
1191 union smb_unlink unl;
1192 uint16_t fnum=0;
1193 char c = 0;
1195 if (!torture_setup_dir(cli1, BASEDIR)) {
1196 return false;
1199 /* cleanup */
1200 smbcli_unlink(cli1->tree, fname);
1202 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1205 base ntcreatex parms
1207 io.generic.level = RAW_OPEN_NTCREATEX;
1208 io.ntcreatex.in.root_fid.fnum = 0;
1209 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1210 io.ntcreatex.in.alloc_size = 0;
1211 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1212 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1213 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1214 io.ntcreatex.in.create_options = 0;
1215 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1216 io.ntcreatex.in.security_flags = 0;
1217 io.ntcreatex.in.fname = fname;
1220 with a batch oplock we get a break
1222 torture_comment(tctx, "BATCH1: open with batch oplock\n");
1223 ZERO_STRUCT(break_info);
1224 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1225 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1226 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1227 status = smb_raw_open(cli1->tree, tctx, &io);
1228 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1229 fnum = io.ntcreatex.out.file.fnum;
1230 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1232 torture_comment(tctx, "unlink should generate a break\n");
1233 unl.unlink.in.pattern = fname;
1234 unl.unlink.in.attrib = 0;
1235 status = smb_raw_unlink(cli2->tree, &unl);
1236 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1238 torture_wait_for_oplock_break(tctx);
1239 CHECK_VAL(break_info.count, 1);
1240 CHECK_VAL(break_info.fnum, fnum);
1241 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1242 CHECK_VAL(break_info.failures, 0);
1244 torture_comment(tctx, "2nd unlink should not generate a break\n");
1245 ZERO_STRUCT(break_info);
1246 status = smb_raw_unlink(cli2->tree, &unl);
1247 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1249 torture_wait_for_oplock_break(tctx);
1250 CHECK_VAL(break_info.count, 0);
1252 torture_comment(tctx, "writing should generate a self break to none\n");
1253 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1255 torture_wait_for_oplock_break(tctx);
1256 torture_wait_for_oplock_break(tctx);
1257 CHECK_VAL(break_info.count, 1);
1258 CHECK_VAL(break_info.fnum, fnum);
1259 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
1260 CHECK_VAL(break_info.failures, 0);
1262 smbcli_close(cli1->tree, fnum);
1264 done:
1265 smb_raw_exit(cli1->session);
1266 smb_raw_exit(cli2->session);
1267 smbcli_deltree(cli1->tree, BASEDIR);
1268 return ret;
1271 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1273 const char *fname = BASEDIR "\\test_batch2.dat";
1274 NTSTATUS status;
1275 bool ret = true;
1276 union smb_open io;
1277 union smb_unlink unl;
1278 uint16_t fnum=0;
1279 char c = 0;
1281 if (!torture_setup_dir(cli1, BASEDIR)) {
1282 return false;
1285 /* cleanup */
1286 smbcli_unlink(cli1->tree, fname);
1288 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1291 base ntcreatex parms
1293 io.generic.level = RAW_OPEN_NTCREATEX;
1294 io.ntcreatex.in.root_fid.fnum = 0;
1295 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1296 io.ntcreatex.in.alloc_size = 0;
1297 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1298 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1299 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1300 io.ntcreatex.in.create_options = 0;
1301 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1302 io.ntcreatex.in.security_flags = 0;
1303 io.ntcreatex.in.fname = fname;
1305 torture_comment(tctx, "BATCH2: open with batch oplock\n");
1306 ZERO_STRUCT(break_info);
1307 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1308 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1309 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1310 status = smb_raw_open(cli1->tree, tctx, &io);
1311 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1312 fnum = io.ntcreatex.out.file.fnum;
1313 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1315 torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
1316 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
1317 unl.unlink.in.pattern = fname;
1318 unl.unlink.in.attrib = 0;
1319 status = smb_raw_unlink(cli2->tree, &unl);
1320 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1322 torture_wait_for_oplock_break(tctx);
1323 CHECK_VAL(break_info.count, 1);
1324 CHECK_VAL(break_info.fnum, fnum);
1325 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1326 CHECK_VAL(break_info.failures, 0);
1328 torture_comment(tctx, "2nd unlink should not generate a break\n");
1329 ZERO_STRUCT(break_info);
1330 status = smb_raw_unlink(cli2->tree, &unl);
1331 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1333 torture_wait_for_oplock_break(tctx);
1334 CHECK_VAL(break_info.count, 0);
1336 torture_comment(tctx, "writing should not generate a break\n");
1337 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1339 torture_wait_for_oplock_break(tctx);
1340 CHECK_VAL(break_info.count, 0);
1342 smbcli_close(cli1->tree, fnum);
1344 done:
1345 smb_raw_exit(cli1->session);
1346 smb_raw_exit(cli2->session);
1347 smbcli_deltree(cli1->tree, BASEDIR);
1348 return ret;
1351 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1353 const char *fname = BASEDIR "\\test_batch3.dat";
1354 NTSTATUS status;
1355 bool ret = true;
1356 union smb_open io;
1357 union smb_unlink unl;
1358 uint16_t fnum=0;
1360 if (!torture_setup_dir(cli1, BASEDIR)) {
1361 return false;
1364 /* cleanup */
1365 smbcli_unlink(cli1->tree, fname);
1367 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1370 base ntcreatex parms
1372 io.generic.level = RAW_OPEN_NTCREATEX;
1373 io.ntcreatex.in.root_fid.fnum = 0;
1374 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1375 io.ntcreatex.in.alloc_size = 0;
1376 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1377 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1378 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1379 io.ntcreatex.in.create_options = 0;
1380 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1381 io.ntcreatex.in.security_flags = 0;
1382 io.ntcreatex.in.fname = fname;
1384 torture_comment(tctx, "BATCH3: if we close on break then the unlink can succeed\n");
1385 ZERO_STRUCT(break_info);
1386 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1387 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1388 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1389 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1390 status = smb_raw_open(cli1->tree, tctx, &io);
1391 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1392 fnum = io.ntcreatex.out.file.fnum;
1393 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1395 unl.unlink.in.pattern = fname;
1396 unl.unlink.in.attrib = 0;
1397 ZERO_STRUCT(break_info);
1398 status = smb_raw_unlink(cli2->tree, &unl);
1399 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1401 torture_wait_for_oplock_break(tctx);
1402 CHECK_VAL(break_info.count, 1);
1403 CHECK_VAL(break_info.fnum, fnum);
1404 CHECK_VAL(break_info.level, 1);
1405 CHECK_VAL(break_info.failures, 0);
1407 smbcli_close(cli1->tree, fnum);
1409 done:
1410 smb_raw_exit(cli1->session);
1411 smb_raw_exit(cli2->session);
1412 smbcli_deltree(cli1->tree, BASEDIR);
1413 return ret;
1416 static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1418 const char *fname = BASEDIR "\\test_batch4.dat";
1419 NTSTATUS status;
1420 bool ret = true;
1421 union smb_open io;
1422 union smb_read rd;
1423 uint16_t fnum=0;
1425 if (!torture_setup_dir(cli1, BASEDIR)) {
1426 return false;
1429 /* cleanup */
1430 smbcli_unlink(cli1->tree, fname);
1432 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1435 base ntcreatex parms
1437 io.generic.level = RAW_OPEN_NTCREATEX;
1438 io.ntcreatex.in.root_fid.fnum = 0;
1439 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1440 io.ntcreatex.in.alloc_size = 0;
1441 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1442 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1443 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1444 io.ntcreatex.in.create_options = 0;
1445 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1446 io.ntcreatex.in.security_flags = 0;
1447 io.ntcreatex.in.fname = fname;
1449 torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
1450 ZERO_STRUCT(break_info);
1451 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1453 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1454 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1455 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1456 status = smb_raw_open(cli1->tree, tctx, &io);
1457 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1458 fnum = io.ntcreatex.out.file.fnum;
1459 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1461 rd.readx.level = RAW_READ_READX;
1462 rd.readx.in.file.fnum = fnum;
1463 rd.readx.in.mincnt = 1;
1464 rd.readx.in.maxcnt = 1;
1465 rd.readx.in.offset = 0;
1466 rd.readx.in.remaining = 0;
1467 rd.readx.in.read_for_execute = false;
1468 status = smb_raw_read(cli1->tree, &rd);
1469 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1470 torture_wait_for_oplock_break(tctx);
1471 CHECK_VAL(break_info.count, 0);
1472 CHECK_VAL(break_info.failures, 0);
1474 smbcli_close(cli1->tree, fnum);
1476 done:
1477 smb_raw_exit(cli1->session);
1478 smb_raw_exit(cli2->session);
1479 smbcli_deltree(cli1->tree, BASEDIR);
1480 return ret;
1483 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1485 const char *fname = BASEDIR "\\test_batch5.dat";
1486 NTSTATUS status;
1487 bool ret = true;
1488 union smb_open io;
1489 uint16_t fnum=0;
1491 if (!torture_setup_dir(cli1, BASEDIR)) {
1492 return false;
1495 /* cleanup */
1496 smbcli_unlink(cli1->tree, fname);
1498 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1501 base ntcreatex parms
1503 io.generic.level = RAW_OPEN_NTCREATEX;
1504 io.ntcreatex.in.root_fid.fnum = 0;
1505 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1506 io.ntcreatex.in.alloc_size = 0;
1507 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1508 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1509 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1510 io.ntcreatex.in.create_options = 0;
1511 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1512 io.ntcreatex.in.security_flags = 0;
1513 io.ntcreatex.in.fname = fname;
1515 torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1516 ZERO_STRUCT(break_info);
1517 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1519 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1520 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1521 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1522 status = smb_raw_open(cli1->tree, tctx, &io);
1523 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1524 fnum = io.ntcreatex.out.file.fnum;
1525 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1527 ZERO_STRUCT(break_info);
1529 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1530 status = smb_raw_open(cli2->tree, tctx, &io);
1531 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1533 torture_wait_for_oplock_break(tctx);
1534 CHECK_VAL(break_info.count, 1);
1535 CHECK_VAL(break_info.fnum, fnum);
1536 CHECK_VAL(break_info.level, 1);
1537 CHECK_VAL(break_info.failures, 0);
1539 smbcli_close(cli1->tree, fnum);
1541 done:
1542 smb_raw_exit(cli1->session);
1543 smb_raw_exit(cli2->session);
1544 smbcli_deltree(cli1->tree, BASEDIR);
1545 return ret;
1548 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1550 const char *fname = BASEDIR "\\test_batch6.dat";
1551 NTSTATUS status;
1552 bool ret = true;
1553 union smb_open io;
1554 uint16_t fnum=0, fnum2=0;
1555 char c = 0;
1557 if (!torture_setup_dir(cli1, BASEDIR)) {
1558 return false;
1561 /* cleanup */
1562 smbcli_unlink(cli1->tree, fname);
1564 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1565 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1568 base ntcreatex parms
1570 io.generic.level = RAW_OPEN_NTCREATEX;
1571 io.ntcreatex.in.root_fid.fnum = 0;
1572 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1573 io.ntcreatex.in.alloc_size = 0;
1574 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1575 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1576 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1577 io.ntcreatex.in.create_options = 0;
1578 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1579 io.ntcreatex.in.security_flags = 0;
1580 io.ntcreatex.in.fname = fname;
1582 torture_comment(tctx, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1583 ZERO_STRUCT(break_info);
1585 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
1586 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1587 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1588 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1589 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1590 status = smb_raw_open(cli1->tree, tctx, &io);
1591 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1592 fnum = io.ntcreatex.out.file.fnum;
1593 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1595 ZERO_STRUCT(break_info);
1597 status = smb_raw_open(cli2->tree, tctx, &io);
1598 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1599 fnum2 = io.ntcreatex.out.file.fnum;
1600 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1602 //torture_wait_for_oplock_break(tctx);
1603 CHECK_VAL(break_info.count, 1);
1604 CHECK_VAL(break_info.fnum, fnum);
1605 CHECK_VAL(break_info.level, 1);
1606 CHECK_VAL(break_info.failures, 0);
1607 ZERO_STRUCT(break_info);
1609 torture_comment(tctx, "write should trigger a break to none on both\n");
1610 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1612 /* We expect two breaks */
1613 torture_wait_for_oplock_break(tctx);
1614 torture_wait_for_oplock_break(tctx);
1616 CHECK_VAL(break_info.count, 2);
1617 CHECK_VAL(break_info.level, 0);
1618 CHECK_VAL(break_info.failures, 0);
1620 smbcli_close(cli1->tree, fnum);
1621 smbcli_close(cli2->tree, fnum2);
1623 done:
1624 smb_raw_exit(cli1->session);
1625 smb_raw_exit(cli2->session);
1626 smbcli_deltree(cli1->tree, BASEDIR);
1627 return ret;
1630 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1632 const char *fname = BASEDIR "\\test_batch7.dat";
1633 NTSTATUS status;
1634 bool ret = true;
1635 union smb_open io;
1636 uint16_t fnum=0, fnum2=0;
1638 if (!torture_setup_dir(cli1, BASEDIR)) {
1639 return false;
1642 /* cleanup */
1643 smbcli_unlink(cli1->tree, fname);
1645 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1648 base ntcreatex parms
1650 io.generic.level = RAW_OPEN_NTCREATEX;
1651 io.ntcreatex.in.root_fid.fnum = 0;
1652 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1653 io.ntcreatex.in.alloc_size = 0;
1654 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1655 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1656 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1657 io.ntcreatex.in.create_options = 0;
1658 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1659 io.ntcreatex.in.security_flags = 0;
1660 io.ntcreatex.in.fname = fname;
1662 torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1663 ZERO_STRUCT(break_info);
1664 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1666 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1667 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1668 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1669 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1670 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1671 status = smb_raw_open(cli1->tree, tctx, &io);
1672 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1673 fnum2 = io.ntcreatex.out.file.fnum;
1674 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1676 ZERO_STRUCT(break_info);
1678 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1679 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1680 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1681 status = smb_raw_open(cli2->tree, tctx, &io);
1682 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1683 fnum = io.ntcreatex.out.file.fnum;
1684 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1686 torture_wait_for_oplock_break(tctx);
1687 CHECK_VAL(break_info.count, 1);
1688 CHECK_VAL(break_info.fnum, fnum2);
1689 CHECK_VAL(break_info.level, 1);
1690 CHECK_VAL(break_info.failures, 0);
1692 smbcli_close(cli2->tree, fnum);
1694 done:
1695 smb_raw_exit(cli1->session);
1696 smb_raw_exit(cli2->session);
1697 smbcli_deltree(cli1->tree, BASEDIR);
1698 return ret;
1701 static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1703 const char *fname = BASEDIR "\\test_batch8.dat";
1704 NTSTATUS status;
1705 bool ret = true;
1706 union smb_open io;
1707 uint16_t fnum=0, fnum2=0;
1709 if (!torture_setup_dir(cli1, BASEDIR)) {
1710 return false;
1713 /* cleanup */
1714 smbcli_unlink(cli1->tree, fname);
1716 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1719 base ntcreatex parms
1721 io.generic.level = RAW_OPEN_NTCREATEX;
1722 io.ntcreatex.in.root_fid.fnum = 0;
1723 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1724 io.ntcreatex.in.alloc_size = 0;
1725 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1726 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1727 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1728 io.ntcreatex.in.create_options = 0;
1729 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1730 io.ntcreatex.in.security_flags = 0;
1731 io.ntcreatex.in.fname = fname;
1733 torture_comment(tctx, "BATCH8: open with batch oplock\n");
1734 ZERO_STRUCT(break_info);
1735 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1737 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1738 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1739 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1740 status = smb_raw_open(cli1->tree, tctx, &io);
1741 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1742 fnum = io.ntcreatex.out.file.fnum;
1743 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1745 ZERO_STRUCT(break_info);
1746 torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
1748 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1749 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1750 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1751 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1752 status = smb_raw_open(cli2->tree, tctx, &io);
1753 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1754 fnum2 = io.ntcreatex.out.file.fnum;
1755 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1756 torture_wait_for_oplock_break(tctx);
1757 CHECK_VAL(break_info.count, 0);
1758 CHECK_VAL(break_info.failures, 0);
1760 smbcli_close(cli1->tree, fnum);
1761 smbcli_close(cli2->tree, fnum2);
1763 done:
1764 smb_raw_exit(cli1->session);
1765 smb_raw_exit(cli2->session);
1766 smbcli_deltree(cli1->tree, BASEDIR);
1767 return ret;
1770 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1772 const char *fname = BASEDIR "\\test_batch9.dat";
1773 NTSTATUS status;
1774 bool ret = true;
1775 union smb_open io;
1776 uint16_t fnum=0, fnum2=0;
1777 char c = 0;
1779 if (!torture_setup_dir(cli1, BASEDIR)) {
1780 return false;
1783 /* cleanup */
1784 smbcli_unlink(cli1->tree, fname);
1786 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1789 base ntcreatex parms
1791 io.generic.level = RAW_OPEN_NTCREATEX;
1792 io.ntcreatex.in.root_fid.fnum = 0;
1793 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1794 io.ntcreatex.in.alloc_size = 0;
1795 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1796 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1797 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1798 io.ntcreatex.in.create_options = 0;
1799 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1800 io.ntcreatex.in.security_flags = 0;
1801 io.ntcreatex.in.fname = fname;
1803 torture_comment(tctx, "BATCH9: open with attributes only can create file\n");
1805 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1806 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1807 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1808 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1809 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1810 status = smb_raw_open(cli1->tree, tctx, &io);
1811 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1812 fnum = io.ntcreatex.out.file.fnum;
1813 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1815 torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
1817 ZERO_STRUCT(break_info);
1818 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1820 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1821 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1822 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1823 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1824 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1825 status = smb_raw_open(cli2->tree, tctx, &io);
1826 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1827 fnum2 = io.ntcreatex.out.file.fnum;
1828 torture_wait_for_oplock_break(tctx);
1829 CHECK_VAL(break_info.count, 1);
1830 CHECK_VAL(break_info.fnum, fnum);
1831 CHECK_VAL(break_info.failures, 0);
1832 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1833 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1834 smbcli_close(cli2->tree, fnum2);
1836 torture_comment(tctx, "third oplocked open should grant level2 without break\n");
1837 ZERO_STRUCT(break_info);
1838 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1839 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1840 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1841 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1842 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1843 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1844 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1845 status = smb_raw_open(cli2->tree, tctx, &io);
1846 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1847 fnum2 = io.ntcreatex.out.file.fnum;
1848 torture_wait_for_oplock_break(tctx);
1849 CHECK_VAL(break_info.count, 0);
1850 CHECK_VAL(break_info.failures, 0);
1851 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1853 ZERO_STRUCT(break_info);
1855 torture_comment(tctx, "write should trigger a break to none on both\n");
1856 smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
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.level, 0);
1864 CHECK_VAL(break_info.failures, 0);
1866 smbcli_close(cli1->tree, fnum);
1867 smbcli_close(cli2->tree, fnum2);
1869 done:
1870 smb_raw_exit(cli1->session);
1871 smb_raw_exit(cli2->session);
1872 smbcli_deltree(cli1->tree, BASEDIR);
1873 return ret;
1876 static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1878 const char *fname = BASEDIR "\\test_batch10.dat";
1879 NTSTATUS status;
1880 bool ret = true;
1881 union smb_open io;
1882 uint16_t fnum=0, fnum2=0;
1884 if (!torture_setup_dir(cli1, BASEDIR)) {
1885 return false;
1888 /* cleanup */
1889 smbcli_unlink(cli1->tree, fname);
1891 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1894 base ntcreatex parms
1896 io.generic.level = RAW_OPEN_NTCREATEX;
1897 io.ntcreatex.in.root_fid.fnum = 0;
1898 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1899 io.ntcreatex.in.alloc_size = 0;
1900 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1901 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1902 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1903 io.ntcreatex.in.create_options = 0;
1904 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1905 io.ntcreatex.in.security_flags = 0;
1906 io.ntcreatex.in.fname = fname;
1908 torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
1909 ZERO_STRUCT(break_info);
1910 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1911 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1912 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1913 NTCREATEX_SHARE_ACCESS_WRITE|
1914 NTCREATEX_SHARE_ACCESS_DELETE;
1915 status = smb_raw_open(cli1->tree, tctx, &io);
1916 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1917 fnum = io.ntcreatex.out.file.fnum;
1918 torture_wait_for_oplock_break(tctx);
1919 CHECK_VAL(break_info.count, 0);
1920 CHECK_VAL(break_info.failures, 0);
1921 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1924 union smb_write wr;
1925 wr.write.level = RAW_WRITE_WRITE;
1926 wr.write.in.file.fnum = fnum;
1927 wr.write.in.count = 1;
1928 wr.write.in.offset = 0;
1929 wr.write.in.remaining = 0;
1930 wr.write.in.data = (const uint8_t *)"x";
1931 status = smb_raw_write(cli1->tree, &wr);
1932 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1935 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1937 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1938 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1939 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1940 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1941 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1942 NTCREATEX_SHARE_ACCESS_WRITE|
1943 NTCREATEX_SHARE_ACCESS_DELETE;
1944 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1945 status = smb_raw_open(cli2->tree, tctx, &io);
1946 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1947 fnum2 = io.ntcreatex.out.file.fnum;
1948 torture_wait_for_oplock_break(tctx);
1949 CHECK_VAL(break_info.count, 0);
1950 CHECK_VAL(break_info.failures, 0);
1951 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1953 torture_comment(tctx, "write should trigger a break to none\n");
1955 union smb_write wr;
1956 wr.write.level = RAW_WRITE_WRITE;
1957 wr.write.in.file.fnum = fnum;
1958 wr.write.in.count = 1;
1959 wr.write.in.offset = 0;
1960 wr.write.in.remaining = 0;
1961 wr.write.in.data = (const uint8_t *)"x";
1962 status = smb_raw_write(cli1->tree, &wr);
1963 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1966 torture_wait_for_oplock_break(tctx);
1968 CHECK_VAL(break_info.count, 1);
1969 CHECK_VAL(break_info.fnum, fnum2);
1970 CHECK_VAL(break_info.level, 0);
1971 CHECK_VAL(break_info.failures, 0);
1973 smbcli_close(cli1->tree, fnum);
1974 smbcli_close(cli2->tree, fnum2);
1976 done:
1977 smb_raw_exit(cli1->session);
1978 smb_raw_exit(cli2->session);
1979 smbcli_deltree(cli1->tree, BASEDIR);
1980 return ret;
1983 static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1985 const char *fname = BASEDIR "\\test_batch11.dat";
1986 NTSTATUS status;
1987 bool ret = true;
1988 union smb_open io;
1989 union smb_setfileinfo sfi;
1990 uint16_t fnum=0;
1992 if (!torture_setup_dir(cli1, BASEDIR)) {
1993 return false;
1996 /* cleanup */
1997 smbcli_unlink(cli1->tree, fname);
1999 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2002 base ntcreatex parms
2004 io.generic.level = RAW_OPEN_NTCREATEX;
2005 io.ntcreatex.in.root_fid.fnum = 0;
2006 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2007 io.ntcreatex.in.alloc_size = 0;
2008 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2009 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
2010 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2011 io.ntcreatex.in.create_options = 0;
2012 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2013 io.ntcreatex.in.security_flags = 0;
2014 io.ntcreatex.in.fname = fname;
2016 /* Test if a set-eof on pathname breaks an exclusive oplock. */
2017 torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
2019 ZERO_STRUCT(break_info);
2021 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2022 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2023 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2024 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2025 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2026 NTCREATEX_SHARE_ACCESS_WRITE|
2027 NTCREATEX_SHARE_ACCESS_DELETE;
2028 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2029 status = smb_raw_open(cli1->tree, tctx, &io);
2030 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2031 fnum = io.ntcreatex.out.file.fnum;
2032 torture_wait_for_oplock_break(tctx);
2033 CHECK_VAL(break_info.count, 0);
2034 CHECK_VAL(break_info.failures, 0);
2035 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2037 ZERO_STRUCT(sfi);
2038 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
2039 sfi.generic.in.file.path = fname;
2040 sfi.end_of_file_info.in.size = 100;
2042 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2043 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2045 torture_wait_for_oplock_break(tctx);
2046 CHECK_VAL(break_info.count, get_setinfo_break_count(tctx));
2047 CHECK_VAL(break_info.failures, 0);
2048 CHECK_VAL(break_info.level, 0);
2050 smbcli_close(cli1->tree, fnum);
2052 done:
2053 smb_raw_exit(cli1->session);
2054 smb_raw_exit(cli2->session);
2055 smbcli_deltree(cli1->tree, BASEDIR);
2056 return ret;
2059 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2061 const char *fname = BASEDIR "\\test_batch12.dat";
2062 NTSTATUS status;
2063 bool ret = true;
2064 union smb_open io;
2065 union smb_setfileinfo sfi;
2066 uint16_t fnum=0;
2068 if (!torture_setup_dir(cli1, BASEDIR)) {
2069 return false;
2072 /* cleanup */
2073 smbcli_unlink(cli1->tree, fname);
2075 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2078 base ntcreatex parms
2080 io.generic.level = RAW_OPEN_NTCREATEX;
2081 io.ntcreatex.in.root_fid.fnum = 0;
2082 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2083 io.ntcreatex.in.alloc_size = 0;
2084 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2085 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2086 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2087 io.ntcreatex.in.create_options = 0;
2088 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2089 io.ntcreatex.in.security_flags = 0;
2090 io.ntcreatex.in.fname = fname;
2092 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
2093 torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
2095 ZERO_STRUCT(break_info);
2096 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2098 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2099 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2100 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2101 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2102 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2103 NTCREATEX_SHARE_ACCESS_WRITE|
2104 NTCREATEX_SHARE_ACCESS_DELETE;
2105 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2106 status = smb_raw_open(cli1->tree, tctx, &io);
2107 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2108 fnum = io.ntcreatex.out.file.fnum;
2109 torture_wait_for_oplock_break(tctx);
2110 CHECK_VAL(break_info.count, 0);
2111 CHECK_VAL(break_info.failures, 0);
2112 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2114 ZERO_STRUCT(sfi);
2115 sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
2116 sfi.generic.in.file.path = fname;
2117 sfi.allocation_info.in.alloc_size = 65536 * 8;
2119 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2120 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2122 torture_wait_for_oplock_break(tctx);
2123 CHECK_VAL(break_info.count, get_setinfo_break_count(tctx));
2124 CHECK_VAL(break_info.failures, 0);
2125 CHECK_VAL(break_info.level, 0);
2127 smbcli_close(cli1->tree, fnum);
2129 done:
2130 smb_raw_exit(cli1->session);
2131 smb_raw_exit(cli2->session);
2132 smbcli_deltree(cli1->tree, BASEDIR);
2133 return ret;
2136 static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2138 const char *fname = BASEDIR "\\test_batch13.dat";
2139 NTSTATUS status;
2140 bool ret = true;
2141 union smb_open io;
2142 uint16_t fnum=0, fnum2=0;
2144 if (!torture_setup_dir(cli1, BASEDIR)) {
2145 return false;
2148 /* cleanup */
2149 smbcli_unlink(cli1->tree, fname);
2151 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2152 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
2155 base ntcreatex parms
2157 io.generic.level = RAW_OPEN_NTCREATEX;
2158 io.ntcreatex.in.root_fid.fnum = 0;
2159 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2160 io.ntcreatex.in.alloc_size = 0;
2161 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2162 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2163 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2164 io.ntcreatex.in.create_options = 0;
2165 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2166 io.ntcreatex.in.security_flags = 0;
2167 io.ntcreatex.in.fname = fname;
2169 torture_comment(tctx, "BATCH13: open with batch oplock\n");
2170 ZERO_STRUCT(break_info);
2172 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2173 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2174 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2175 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2176 NTCREATEX_SHARE_ACCESS_WRITE|
2177 NTCREATEX_SHARE_ACCESS_DELETE;
2178 status = smb_raw_open(cli1->tree, tctx, &io);
2179 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2180 fnum = io.ntcreatex.out.file.fnum;
2181 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2183 ZERO_STRUCT(break_info);
2185 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
2187 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2188 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2189 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2190 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
2191 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2192 NTCREATEX_SHARE_ACCESS_WRITE|
2193 NTCREATEX_SHARE_ACCESS_DELETE;
2194 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
2195 status = smb_raw_open(cli2->tree, tctx, &io);
2196 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2197 fnum2 = io.ntcreatex.out.file.fnum;
2198 torture_wait_for_oplock_break(tctx);
2199 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2200 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
2201 CHECK_VAL(break_info.failures, 0);
2203 smbcli_close(cli1->tree, fnum);
2204 smbcli_close(cli2->tree, fnum2);
2206 done:
2207 smb_raw_exit(cli1->session);
2208 smb_raw_exit(cli2->session);
2209 smbcli_deltree(cli1->tree, BASEDIR);
2210 return ret;
2213 static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2215 const char *fname = BASEDIR "\\test_batch14.dat";
2216 NTSTATUS status;
2217 bool ret = true;
2218 union smb_open io;
2219 uint16_t fnum=0, fnum2=0;
2221 if (!torture_setup_dir(cli1, BASEDIR)) {
2222 return false;
2225 /* cleanup */
2226 smbcli_unlink(cli1->tree, fname);
2228 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2231 base ntcreatex parms
2233 io.generic.level = RAW_OPEN_NTCREATEX;
2234 io.ntcreatex.in.root_fid.fnum = 0;
2235 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2236 io.ntcreatex.in.alloc_size = 0;
2237 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2238 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2239 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2240 io.ntcreatex.in.create_options = 0;
2241 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2242 io.ntcreatex.in.security_flags = 0;
2243 io.ntcreatex.in.fname = fname;
2245 torture_comment(tctx, "BATCH14: open with batch oplock\n");
2246 ZERO_STRUCT(break_info);
2248 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2249 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2250 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2251 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2252 NTCREATEX_SHARE_ACCESS_WRITE|
2253 NTCREATEX_SHARE_ACCESS_DELETE;
2254 status = smb_raw_open(cli1->tree, tctx, &io);
2255 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2256 fnum = io.ntcreatex.out.file.fnum;
2257 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2259 ZERO_STRUCT(break_info);
2261 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
2263 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2264 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2265 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2266 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
2267 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2268 NTCREATEX_SHARE_ACCESS_WRITE|
2269 NTCREATEX_SHARE_ACCESS_DELETE;
2270 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
2271 status = smb_raw_open(cli2->tree, tctx, &io);
2272 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2273 fnum2 = io.ntcreatex.out.file.fnum;
2274 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2276 torture_wait_for_oplock_break(tctx);
2277 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
2278 CHECK_VAL(break_info.failures, 0);
2280 smbcli_close(cli1->tree, fnum);
2281 smbcli_close(cli2->tree, fnum2);
2282 done:
2283 smb_raw_exit(cli1->session);
2284 smb_raw_exit(cli2->session);
2285 smbcli_deltree(cli1->tree, BASEDIR);
2286 return ret;
2289 static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2291 const char *fname = BASEDIR "\\test_batch15.dat";
2292 NTSTATUS status;
2293 bool ret = true;
2294 union smb_open io;
2295 union smb_fileinfo qfi;
2296 uint16_t fnum=0;
2298 if (!torture_setup_dir(cli1, BASEDIR)) {
2299 return false;
2302 /* cleanup */
2303 smbcli_unlink(cli1->tree, fname);
2305 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2308 base ntcreatex parms
2310 io.generic.level = RAW_OPEN_NTCREATEX;
2311 io.ntcreatex.in.root_fid.fnum = 0;
2312 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2313 io.ntcreatex.in.alloc_size = 0;
2314 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2315 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2316 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2317 io.ntcreatex.in.create_options = 0;
2318 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2319 io.ntcreatex.in.security_flags = 0;
2320 io.ntcreatex.in.fname = fname;
2322 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
2323 torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
2325 ZERO_STRUCT(break_info);
2327 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2328 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2329 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2330 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2331 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2332 NTCREATEX_SHARE_ACCESS_WRITE|
2333 NTCREATEX_SHARE_ACCESS_DELETE;
2334 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2335 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2336 status = smb_raw_open(cli1->tree, tctx, &io);
2337 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2338 fnum = io.ntcreatex.out.file.fnum;
2340 torture_wait_for_oplock_break(tctx);
2341 CHECK_VAL(break_info.count, 0);
2342 CHECK_VAL(break_info.failures, 0);
2343 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2345 ZERO_STRUCT(qfi);
2346 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2347 qfi.generic.in.file.path = fname;
2349 status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
2350 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2352 torture_wait_for_oplock_break(tctx);
2353 CHECK_VAL(break_info.count, 0);
2355 smbcli_close(cli1->tree, fnum);
2357 done:
2358 smb_raw_exit(cli1->session);
2359 smb_raw_exit(cli2->session);
2360 smbcli_deltree(cli1->tree, BASEDIR);
2361 return ret;
2364 static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2366 const char *fname = BASEDIR "\\test_batch16.dat";
2367 NTSTATUS status;
2368 bool ret = true;
2369 union smb_open io;
2370 uint16_t fnum=0, fnum2=0;
2372 if (!torture_setup_dir(cli1, BASEDIR)) {
2373 return false;
2376 /* cleanup */
2377 smbcli_unlink(cli1->tree, fname);
2379 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2380 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
2383 base ntcreatex parms
2385 io.generic.level = RAW_OPEN_NTCREATEX;
2386 io.ntcreatex.in.root_fid.fnum = 0;
2387 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2388 io.ntcreatex.in.alloc_size = 0;
2389 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2390 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2391 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2392 io.ntcreatex.in.create_options = 0;
2393 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2394 io.ntcreatex.in.security_flags = 0;
2395 io.ntcreatex.in.fname = fname;
2397 torture_comment(tctx, "BATCH16: open with batch oplock\n");
2398 ZERO_STRUCT(break_info);
2400 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2401 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2402 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2403 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2404 NTCREATEX_SHARE_ACCESS_WRITE|
2405 NTCREATEX_SHARE_ACCESS_DELETE;
2406 status = smb_raw_open(cli1->tree, tctx, &io);
2407 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2408 fnum = io.ntcreatex.out.file.fnum;
2409 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2411 ZERO_STRUCT(break_info);
2413 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
2415 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2416 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2417 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2418 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
2419 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2420 NTCREATEX_SHARE_ACCESS_WRITE|
2421 NTCREATEX_SHARE_ACCESS_DELETE;
2422 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2423 status = smb_raw_open(cli2->tree, tctx, &io);
2424 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2425 fnum2 = io.ntcreatex.out.file.fnum;
2426 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2428 torture_wait_for_oplock_break(tctx);
2429 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
2430 CHECK_VAL(break_info.failures, 0);
2432 smbcli_close(cli1->tree, fnum);
2433 smbcli_close(cli2->tree, fnum2);
2435 done:
2436 smb_raw_exit(cli1->session);
2437 smb_raw_exit(cli2->session);
2438 smbcli_deltree(cli1->tree, BASEDIR);
2439 return ret;
2442 static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2444 const char *fname1 = BASEDIR "\\test_batch17_1.dat";
2445 const char *fname2 = BASEDIR "\\test_batch17_2.dat";
2446 NTSTATUS status;
2447 bool ret = true;
2448 union smb_open io;
2449 union smb_rename rn;
2450 uint16_t fnum=0;
2452 if (!torture_setup_dir(cli1, BASEDIR)) {
2453 return false;
2456 /* cleanup */
2457 smbcli_unlink(cli1->tree, fname1);
2458 smbcli_unlink(cli1->tree, fname2);
2460 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2463 base ntcreatex parms
2465 io.generic.level = RAW_OPEN_NTCREATEX;
2466 io.ntcreatex.in.root_fid.fnum = 0;
2467 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2468 io.ntcreatex.in.alloc_size = 0;
2469 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2470 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2471 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2472 io.ntcreatex.in.create_options = 0;
2473 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2474 io.ntcreatex.in.security_flags = 0;
2475 io.ntcreatex.in.fname = fname1;
2477 torture_comment(tctx, "BATCH17: open a file with an batch oplock (share mode: none)\n");
2479 ZERO_STRUCT(break_info);
2480 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2481 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2482 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2484 status = smb_raw_open(cli1->tree, tctx, &io);
2485 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2486 fnum = io.ntcreatex.out.file.fnum;
2487 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2489 torture_comment(tctx, "rename should trigger a break\n");
2490 ZERO_STRUCT(rn);
2491 rn.generic.level = RAW_RENAME_RENAME;
2492 rn.rename.in.pattern1 = fname1;
2493 rn.rename.in.pattern2 = fname2;
2494 rn.rename.in.attrib = 0;
2496 torture_comment(tctx, "trying rename while first file open\n");
2497 status = smb_raw_rename(cli2->tree, &rn);
2498 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2500 torture_wait_for_oplock_break(tctx);
2501 CHECK_VAL(break_info.count, 1);
2502 CHECK_VAL(break_info.failures, 0);
2503 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2505 smbcli_close(cli1->tree, fnum);
2507 done:
2508 smb_raw_exit(cli1->session);
2509 smb_raw_exit(cli2->session);
2510 smbcli_deltree(cli1->tree, BASEDIR);
2511 return ret;
2514 static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2516 const char *fname1 = BASEDIR "\\test_batch18_1.dat";
2517 const char *fname2 = BASEDIR "\\test_batch18_2.dat";
2518 NTSTATUS status;
2519 bool ret = true;
2520 union smb_open io;
2521 union smb_rename rn;
2522 uint16_t fnum=0;
2524 if (!torture_setup_dir(cli1, BASEDIR)) {
2525 return false;
2528 /* cleanup */
2529 smbcli_unlink(cli1->tree, fname1);
2530 smbcli_unlink(cli1->tree, fname2);
2532 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2535 base ntcreatex parms
2537 io.generic.level = RAW_OPEN_NTCREATEX;
2538 io.ntcreatex.in.root_fid.fnum = 0;
2539 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2540 io.ntcreatex.in.alloc_size = 0;
2541 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2542 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2543 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2544 io.ntcreatex.in.create_options = 0;
2545 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2546 io.ntcreatex.in.security_flags = 0;
2547 io.ntcreatex.in.fname = fname1;
2549 torture_comment(tctx, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2551 ZERO_STRUCT(break_info);
2552 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2553 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2554 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2556 status = smb_raw_open(cli1->tree, tctx, &io);
2557 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2558 fnum = io.ntcreatex.out.file.fnum;
2559 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2561 torture_comment(tctx, "ntrename should trigger a break\n");
2562 ZERO_STRUCT(rn);
2563 rn.generic.level = RAW_RENAME_NTRENAME;
2564 rn.ntrename.in.attrib = 0;
2565 rn.ntrename.in.flags = RENAME_FLAG_RENAME;
2566 rn.ntrename.in.old_name = fname1;
2567 rn.ntrename.in.new_name = fname2;
2568 torture_comment(tctx, "trying rename while first file open\n");
2569 status = smb_raw_rename(cli2->tree, &rn);
2570 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2572 torture_wait_for_oplock_break(tctx);
2573 CHECK_VAL(break_info.count, 1);
2574 CHECK_VAL(break_info.failures, 0);
2575 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2577 smbcli_close(cli1->tree, fnum);
2579 done:
2580 smb_raw_exit(cli1->session);
2581 smb_raw_exit(cli2->session);
2582 smbcli_deltree(cli1->tree, BASEDIR);
2583 return ret;
2586 static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2588 const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2589 const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2590 const char *fname3 = BASEDIR "\\test_batch19_3.dat";
2591 NTSTATUS status;
2592 bool ret = true;
2593 union smb_open io;
2594 union smb_fileinfo qfi;
2595 union smb_setfileinfo sfi;
2596 uint16_t fnum=0;
2598 if (!torture_setup_dir(cli1, BASEDIR)) {
2599 return false;
2602 /* cleanup */
2603 smbcli_unlink(cli1->tree, fname1);
2604 smbcli_unlink(cli1->tree, fname2);
2605 smbcli_unlink(cli1->tree, fname3);
2607 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2610 base ntcreatex parms
2612 io.generic.level = RAW_OPEN_NTCREATEX;
2613 io.ntcreatex.in.root_fid.fnum = 0;
2614 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2615 io.ntcreatex.in.alloc_size = 0;
2616 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2617 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2618 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
2619 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2620 io.ntcreatex.in.create_options = 0;
2621 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2622 io.ntcreatex.in.security_flags = 0;
2623 io.ntcreatex.in.fname = fname1;
2625 torture_comment(tctx, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2626 ZERO_STRUCT(break_info);
2627 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2628 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2629 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2630 status = smb_raw_open(cli1->tree, tctx, &io);
2631 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2632 fnum = io.ntcreatex.out.file.fnum;
2633 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2635 torture_comment(tctx, "setpathinfo rename info should trigger a break "
2636 "to none\n");
2637 ZERO_STRUCT(sfi);
2638 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2639 sfi.generic.in.file.path = fname1;
2640 sfi.rename_information.in.overwrite = 0;
2641 sfi.rename_information.in.root_fid = 0;
2642 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2644 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2645 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2647 torture_wait_for_oplock_break(tctx);
2649 CHECK_VAL(break_info.failures, 0);
2651 if (TARGET_IS_WINXP(tctx) || TARGET_IS_W2K12(tctx)) {
2652 /* Win XP breaks to level2. */
2653 CHECK_VAL(break_info.count, 1);
2654 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2655 } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
2656 TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
2657 /* Win2K3/2k8 incorrectly doesn't break at all. */
2658 CHECK_VAL(break_info.count, 0);
2659 } else {
2660 /* win7/2k8r2 break to none. */
2661 CHECK_VAL(break_info.count, 1);
2662 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2665 ZERO_STRUCT(qfi);
2666 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2667 qfi.generic.in.file.fnum = fnum;
2669 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2670 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2671 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2673 /* Close and re-open file with oplock. */
2674 smbcli_close(cli1->tree, fnum);
2675 status = smb_raw_open(cli1->tree, tctx, &io);
2676 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2677 fnum = io.ntcreatex.out.file.fnum;
2678 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2680 torture_comment(tctx, "setfileinfo rename info on a client's own fid "
2681 "should not trigger a break nor a violation\n");
2682 ZERO_STRUCT(break_info);
2683 ZERO_STRUCT(sfi);
2684 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2685 sfi.generic.in.file.fnum = fnum;
2686 sfi.rename_information.in.overwrite = 0;
2687 sfi.rename_information.in.root_fid = 0;
2688 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2690 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2691 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2693 torture_wait_for_oplock_break(tctx);
2694 if (TARGET_IS_WINXP(tctx)) {
2695 /* XP incorrectly breaks to level2. */
2696 CHECK_VAL(break_info.count, 1);
2697 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2698 } else {
2699 CHECK_VAL(break_info.count, 0);
2702 ZERO_STRUCT(qfi);
2703 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2704 qfi.generic.in.file.fnum = fnum;
2706 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2707 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2708 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2710 done:
2711 smbcli_close(cli1->tree, fnum);
2712 smb_raw_exit(cli1->session);
2713 smb_raw_exit(cli2->session);
2714 smbcli_deltree(cli1->tree, BASEDIR);
2715 return ret;
2718 /****************************************************
2719 Called from raw-rename - we need oplock handling for
2720 this test so this is why it's in oplock.c, not rename.c
2721 ****************************************************/
2723 bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2725 const char *fname1 = BASEDIR "\\test_trans2rename_1.dat";
2726 const char *fname2 = BASEDIR "\\test_trans2rename_2.dat";
2727 const char *fname3 = BASEDIR "\\test_trans2rename_3.dat";
2728 NTSTATUS status;
2729 bool ret = true;
2730 union smb_open io;
2731 union smb_fileinfo qfi;
2732 union smb_setfileinfo sfi;
2733 uint16_t fnum=0;
2735 if (!torture_setup_dir(cli1, BASEDIR)) {
2736 return false;
2739 /* cleanup */
2740 smbcli_unlink(cli1->tree, fname1);
2741 smbcli_unlink(cli1->tree, fname2);
2742 smbcli_unlink(cli1->tree, fname3);
2744 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2747 base ntcreatex parms
2749 io.generic.level = RAW_OPEN_NTCREATEX;
2750 io.ntcreatex.in.root_fid.fnum = 0;
2751 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2752 io.ntcreatex.in.alloc_size = 0;
2753 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2754 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2755 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
2756 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2757 io.ntcreatex.in.create_options = 0;
2758 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2759 io.ntcreatex.in.security_flags = 0;
2760 io.ntcreatex.in.fname = fname1;
2762 torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n");
2763 ZERO_STRUCT(break_info);
2764 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2765 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2766 status = smb_raw_open(cli1->tree, tctx, &io);
2767 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2768 fnum = io.ntcreatex.out.file.fnum;
2769 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2771 torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2772 ZERO_STRUCT(sfi);
2773 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2774 sfi.generic.in.file.path = fname1;
2775 sfi.rename_information.in.overwrite = 0;
2776 sfi.rename_information.in.root_fid = 0;
2777 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2779 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2781 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2783 torture_wait_for_oplock_break(tctx);
2784 CHECK_VAL(break_info.count, 0);
2786 ZERO_STRUCT(qfi);
2787 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2788 qfi.generic.in.file.fnum = fnum;
2790 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2791 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2792 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2794 torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2795 ZERO_STRUCT(sfi);
2796 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2797 sfi.generic.in.file.fnum = fnum;
2798 sfi.rename_information.in.overwrite = 0;
2799 sfi.rename_information.in.root_fid = 0;
2800 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2802 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2803 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2805 torture_wait_for_oplock_break(tctx);
2806 CHECK_VAL(break_info.count, 0);
2808 ZERO_STRUCT(qfi);
2809 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2810 qfi.generic.in.file.fnum = fnum;
2812 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2813 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2814 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2816 done:
2817 smbcli_close(cli1->tree, fnum);
2818 smb_raw_exit(cli1->session);
2819 smb_raw_exit(cli2->session);
2820 smbcli_deltree(cli1->tree, BASEDIR);
2821 return ret;
2824 /****************************************************
2825 Called from raw-rename - we need oplock handling for
2826 this test so this is why it's in oplock.c, not rename.c
2827 ****************************************************/
2829 bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1)
2831 const char *fname1 = BASEDIR "\\test_nttransrename_1.dat";
2832 const char *fname2 = BASEDIR "\\test_nttransrename_2.dat";
2833 NTSTATUS status;
2834 bool ret = true;
2835 union smb_open io;
2836 union smb_fileinfo qfi, qpi;
2837 union smb_rename rn;
2838 uint16_t fnum=0;
2840 if (!torture_setup_dir(cli1, BASEDIR)) {
2841 return false;
2844 /* cleanup */
2845 smbcli_unlink(cli1->tree, fname1);
2846 smbcli_unlink(cli1->tree, fname2);
2848 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2851 base ntcreatex parms
2853 io.generic.level = RAW_OPEN_NTCREATEX;
2854 io.ntcreatex.in.root_fid.fnum = 0;
2855 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2856 io.ntcreatex.in.alloc_size = 0;
2857 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2858 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2859 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2860 io.ntcreatex.in.create_options = 0;
2861 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2862 io.ntcreatex.in.security_flags = 0;
2863 io.ntcreatex.in.fname = fname1;
2865 torture_comment(tctx, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2866 ZERO_STRUCT(break_info);
2867 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2868 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2869 status = smb_raw_open(cli1->tree, tctx, &io);
2870 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2871 fnum = io.ntcreatex.out.file.fnum;
2872 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2874 torture_comment(tctx, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2875 ZERO_STRUCT(rn);
2876 rn.generic.level = RAW_RENAME_NTTRANS;
2877 rn.nttrans.in.file.fnum = fnum;
2878 rn.nttrans.in.flags = 0;
2879 rn.nttrans.in.new_name = fname2+strlen(BASEDIR)+1;
2881 status = smb_raw_rename(cli1->tree, &rn);
2882 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2884 torture_wait_for_oplock_break(tctx);
2885 CHECK_VAL(break_info.count, 0);
2887 /* w2k3 does nothing, it doesn't rename the file */
2888 torture_comment(tctx, "nttrans_rename: the server should have done nothing\n");
2889 ZERO_STRUCT(qfi);
2890 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2891 qfi.generic.in.file.fnum = fnum;
2893 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2894 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2895 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname1);
2897 ZERO_STRUCT(qpi);
2898 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2899 qpi.generic.in.file.path = fname1;
2901 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2902 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2903 CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2905 ZERO_STRUCT(qpi);
2906 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2907 qpi.generic.in.file.path = fname2;
2909 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2910 CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2912 torture_comment(tctx, "nttrans_rename: after closing the file the file is still not renamed\n");
2913 status = smbcli_close(cli1->tree, fnum);
2914 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2916 ZERO_STRUCT(qpi);
2917 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2918 qpi.generic.in.file.path = fname1;
2920 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2921 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2922 CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2924 ZERO_STRUCT(qpi);
2925 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2926 qpi.generic.in.file.path = fname2;
2928 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2929 CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2931 torture_comment(tctx, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
2932 ZERO_STRUCT(rn);
2933 rn.generic.level = RAW_RENAME_NTTRANS;
2934 rn.nttrans.in.file.fnum = fnum+1;
2935 rn.nttrans.in.flags = 0;
2936 rn.nttrans.in.new_name = fname2+strlen(BASEDIR)+1;
2938 status = smb_raw_rename(cli1->tree, &rn);
2940 CHECK_STATUS(tctx, status, NT_STATUS_INVALID_HANDLE);
2942 done:
2943 smb_raw_exit(cli1->session);
2944 smbcli_deltree(cli1->tree, BASEDIR);
2945 return ret;
2949 static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2951 const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2952 const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2953 const char *fname3 = BASEDIR "\\test_batch20_3.dat";
2954 NTSTATUS status;
2955 bool ret = true;
2956 union smb_open io;
2957 union smb_fileinfo qfi;
2958 union smb_setfileinfo sfi;
2959 uint16_t fnum=0,fnum2=0;
2961 if (!torture_setup_dir(cli1, BASEDIR)) {
2962 return false;
2965 /* cleanup */
2966 smbcli_unlink(cli1->tree, fname1);
2967 smbcli_unlink(cli1->tree, fname2);
2968 smbcli_unlink(cli1->tree, fname3);
2970 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2973 base ntcreatex parms
2975 io.generic.level = RAW_OPEN_NTCREATEX;
2976 io.ntcreatex.in.root_fid.fnum = 0;
2977 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2978 io.ntcreatex.in.alloc_size = 0;
2979 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2980 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2981 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2982 io.ntcreatex.in.create_options = 0;
2983 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2984 io.ntcreatex.in.security_flags = 0;
2985 io.ntcreatex.in.fname = fname1;
2987 torture_comment(tctx, "BATCH20: open a file with an batch oplock (share mode: all)\n");
2988 ZERO_STRUCT(break_info);
2989 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2990 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2991 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2992 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2993 NTCREATEX_SHARE_ACCESS_WRITE|
2994 NTCREATEX_SHARE_ACCESS_DELETE;
2995 status = smb_raw_open(cli1->tree, tctx, &io);
2996 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2997 fnum = io.ntcreatex.out.file.fnum;
2998 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3000 ZERO_STRUCT(sfi);
3001 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
3002 sfi.generic.in.file.path = fname1;
3003 sfi.rename_information.in.overwrite = 0;
3004 sfi.rename_information.in.root_fid = 0;
3005 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
3007 status = smb_raw_setpathinfo(cli2->tree, &sfi);
3008 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3010 torture_wait_for_oplock_break(tctx);
3011 CHECK_VAL(break_info.failures, 0);
3013 if (TARGET_IS_WINXP(tctx) || TARGET_IS_W2K12(tctx)) {
3014 /* Win XP breaks to level2. */
3015 CHECK_VAL(break_info.count, 1);
3016 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3017 } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
3018 TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
3019 /* Win2K3/2k8 incorrectly doesn't break at all. */
3020 CHECK_VAL(break_info.count, 0);
3021 } else {
3022 /* win7/2k8r2 break to none. */
3023 CHECK_VAL(break_info.count, 1);
3024 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3027 ZERO_STRUCT(qfi);
3028 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
3029 qfi.generic.in.file.fnum = fnum;
3031 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
3032 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3033 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
3035 torture_comment(tctx, "open a file with the new name an batch oplock (share mode: all)\n");
3036 ZERO_STRUCT(break_info);
3037 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3038 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3039 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3040 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
3041 NTCREATEX_SHARE_ACCESS_WRITE|
3042 NTCREATEX_SHARE_ACCESS_DELETE;
3043 io.ntcreatex.in.fname = fname2;
3044 status = smb_raw_open(cli2->tree, tctx, &io);
3045 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3046 fnum2 = io.ntcreatex.out.file.fnum;
3047 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
3049 torture_wait_for_oplock_break(tctx);
3051 if (TARGET_IS_WINXP(tctx)) {
3052 /* XP broke to level2, and doesn't break again. */
3053 CHECK_VAL(break_info.count, 0);
3054 } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
3055 TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
3056 /* Win2K3 incorrectly didn't break before so break now. */
3057 CHECK_VAL(break_info.count, 1);
3058 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3059 } else {
3060 /* win7/2k8r2 broke to none, and doesn't break again. */
3061 CHECK_VAL(break_info.count, 0);
3064 ZERO_STRUCT(break_info);
3066 ZERO_STRUCT(sfi);
3067 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
3068 sfi.generic.in.file.fnum = fnum;
3069 sfi.rename_information.in.overwrite = 0;
3070 sfi.rename_information.in.root_fid = 0;
3071 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
3073 status = smb_raw_setfileinfo(cli1->tree, &sfi);
3074 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3076 torture_wait_for_oplock_break(tctx);
3077 CHECK_VAL(break_info.count, 0);
3079 ZERO_STRUCT(qfi);
3080 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
3081 qfi.generic.in.file.fnum = fnum;
3083 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
3084 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3085 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
3087 ZERO_STRUCT(qfi);
3088 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
3089 qfi.generic.in.file.fnum = fnum2;
3091 status = smb_raw_fileinfo(cli2->tree, tctx, &qfi);
3092 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3093 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
3096 done:
3097 smbcli_close(cli1->tree, fnum);
3098 smbcli_close(cli2->tree, fnum2);
3099 smb_raw_exit(cli1->session);
3100 smb_raw_exit(cli2->session);
3101 smbcli_deltree(cli1->tree, BASEDIR);
3102 return ret;
3105 static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3107 const char *fname = BASEDIR "\\test_batch21.dat";
3108 NTSTATUS status;
3109 bool ret = true;
3110 union smb_open io;
3111 struct smb_echo e;
3112 uint16_t fnum=0;
3113 char c = 0;
3114 ssize_t wr;
3116 if (!torture_setup_dir(cli1, BASEDIR)) {
3117 return false;
3120 /* cleanup */
3121 smbcli_unlink(cli1->tree, fname);
3123 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3126 base ntcreatex parms
3128 io.generic.level = RAW_OPEN_NTCREATEX;
3129 io.ntcreatex.in.root_fid.fnum = 0;
3130 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3131 io.ntcreatex.in.alloc_size = 0;
3132 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3133 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3134 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3135 io.ntcreatex.in.create_options = 0;
3136 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3137 io.ntcreatex.in.security_flags = 0;
3138 io.ntcreatex.in.fname = fname;
3141 with a batch oplock we get a break
3143 torture_comment(tctx, "BATCH21: open with batch oplock\n");
3144 ZERO_STRUCT(break_info);
3145 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3146 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3147 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3148 status = smb_raw_open(cli1->tree, tctx, &io);
3149 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3150 fnum = io.ntcreatex.out.file.fnum;
3151 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3153 torture_comment(tctx, "writing should not generate a break\n");
3154 wr = smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
3155 CHECK_VAL(wr, 1);
3156 CHECK_STATUS(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_OK);
3158 ZERO_STRUCT(e);
3159 e.in.repeat_count = 1;
3160 status = smb_raw_echo(cli1->transport, &e);
3161 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3163 torture_wait_for_oplock_break(tctx);
3164 CHECK_VAL(break_info.count, 0);
3166 smbcli_close(cli1->tree, fnum);
3168 done:
3169 smb_raw_exit(cli1->session);
3170 smb_raw_exit(cli2->session);
3171 smbcli_deltree(cli1->tree, BASEDIR);
3172 return ret;
3175 static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3177 const char *fname = BASEDIR "\\test_batch22.dat";
3178 NTSTATUS status;
3179 bool ret = true;
3180 union smb_open io;
3181 uint16_t fnum = 0, fnum2 = 0, fnum3 = 0;
3182 struct timeval tv;
3183 int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
3184 int te;
3186 if (!torture_setup_dir(cli1, BASEDIR)) {
3187 return false;
3190 /* cleanup */
3191 smbcli_unlink(cli1->tree, fname);
3193 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3195 base ntcreatex parms
3197 io.generic.level = RAW_OPEN_NTCREATEX;
3198 io.ntcreatex.in.root_fid.fnum = 0;
3199 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3200 io.ntcreatex.in.alloc_size = 0;
3201 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3202 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3203 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3204 io.ntcreatex.in.create_options = 0;
3205 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3206 io.ntcreatex.in.security_flags = 0;
3207 io.ntcreatex.in.fname = fname;
3210 with a batch oplock we get a break
3212 torture_comment(tctx, "BATCH22: open with batch oplock\n");
3213 ZERO_STRUCT(break_info);
3214 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3215 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3216 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3217 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
3218 NTCREATEX_SHARE_ACCESS_WRITE|
3219 NTCREATEX_SHARE_ACCESS_DELETE;
3220 status = smb_raw_open(cli1->tree, tctx, &io);
3221 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3222 fnum = io.ntcreatex.out.file.fnum;
3223 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3225 torture_comment(tctx, "a 2nd open should not succeed after the oplock "
3226 "break timeout\n");
3227 tv = timeval_current();
3228 smbcli_oplock_handler(cli1->transport, oplock_handler_timeout, cli1->tree);
3229 status = smb_raw_open(cli1->tree, tctx, &io);
3231 if (TARGET_IS_W2K3(tctx)) {
3232 /* 2k3 has an issue here. xp/win7 are ok. */
3233 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
3234 } else {
3235 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3238 fnum2 = io.ntcreatex.out.file.fnum;
3240 torture_wait_for_oplock_break(tctx);
3241 te = (int)timeval_elapsed(&tv);
3244 * Some servers detect clients that let oplocks timeout, so this check
3245 * only shows a warning message instead failing the test to eliminate
3246 * failures from repeated runs of the test. This isn't ideal, but
3247 * it's better than not running the test at all.
3249 CHECK_RANGE(te, timeout - 1, timeout + 15);
3251 CHECK_VAL(break_info.count, 1);
3252 CHECK_VAL(break_info.fnum, fnum);
3253 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3254 CHECK_VAL(break_info.failures, 0);
3255 ZERO_STRUCT(break_info);
3257 torture_comment(tctx, "a 2nd open should succeed after the oplock "
3258 "release without break\n");
3259 tv = timeval_current();
3260 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3261 status = smb_raw_open(cli1->tree, tctx, &io);
3262 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3263 #if 0
3264 /* Samba 3.6.0 and above behave as Windows. */
3265 if (TARGET_IS_SAMBA3(tctx)) {
3266 /* samba3 doesn't grant additional oplocks to bad clients. */
3267 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
3268 } else {
3269 CHECK_VAL(io.ntcreatex.out.oplock_level,
3270 LEVEL_II_OPLOCK_RETURN);
3272 #else
3273 CHECK_VAL(io.ntcreatex.out.oplock_level,
3274 LEVEL_II_OPLOCK_RETURN);
3275 #endif
3276 torture_wait_for_oplock_break(tctx);
3277 te = (int)timeval_elapsed(&tv);
3278 /* it should come in without delay */
3279 CHECK_RANGE(te+1, 0, timeout);
3280 fnum3 = io.ntcreatex.out.file.fnum;
3282 CHECK_VAL(break_info.count, 0);
3284 smbcli_close(cli1->tree, fnum);
3285 smbcli_close(cli1->tree, fnum2);
3286 smbcli_close(cli1->tree, fnum3);
3288 done:
3289 smb_raw_exit(cli1->session);
3290 smb_raw_exit(cli2->session);
3291 smbcli_deltree(cli1->tree, BASEDIR);
3292 return ret;
3295 static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3297 const char *fname = BASEDIR "\\test_batch23.dat";
3298 NTSTATUS status;
3299 bool ret = true;
3300 union smb_open io;
3301 uint16_t fnum=0, fnum2=0,fnum3=0;
3302 struct smbcli_state *cli3 = NULL;
3304 if (!torture_setup_dir(cli1, BASEDIR)) {
3305 return false;
3308 /* cleanup */
3309 smbcli_unlink(cli1->tree, fname);
3311 ret = open_connection_no_level2_oplocks(tctx, &cli3);
3312 CHECK_VAL(ret, true);
3314 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3315 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3316 smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
3319 base ntcreatex parms
3321 io.generic.level = RAW_OPEN_NTCREATEX;
3322 io.ntcreatex.in.root_fid.fnum = 0;
3323 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3324 io.ntcreatex.in.alloc_size = 0;
3325 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3326 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3327 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3328 io.ntcreatex.in.create_options = 0;
3329 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3330 io.ntcreatex.in.security_flags = 0;
3331 io.ntcreatex.in.fname = fname;
3333 torture_comment(tctx, "BATCH23: a open and ask for a batch oplock\n");
3334 ZERO_STRUCT(break_info);
3336 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
3337 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
3338 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3339 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3340 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3341 status = smb_raw_open(cli1->tree, tctx, &io);
3342 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3343 fnum = io.ntcreatex.out.file.fnum;
3344 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3346 ZERO_STRUCT(break_info);
3348 torture_comment(tctx, "a 2nd open without level2 oplock support should generate a break to level2\n");
3349 status = smb_raw_open(cli3->tree, tctx, &io);
3350 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3351 fnum3 = io.ntcreatex.out.file.fnum;
3352 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
3354 torture_wait_for_oplock_break(tctx);
3355 CHECK_VAL(break_info.count, 1);
3356 CHECK_VAL(break_info.fnum, fnum);
3357 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3358 CHECK_VAL(break_info.failures, 0);
3360 ZERO_STRUCT(break_info);
3362 torture_comment(tctx, "a 3rd open with level2 oplock support should not generate a break\n");
3363 status = smb_raw_open(cli2->tree, tctx, &io);
3364 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3365 fnum2 = io.ntcreatex.out.file.fnum;
3366 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
3368 torture_wait_for_oplock_break(tctx);
3369 CHECK_VAL(break_info.count, 0);
3371 smbcli_close(cli1->tree, fnum);
3372 smbcli_close(cli2->tree, fnum2);
3373 smbcli_close(cli3->tree, fnum3);
3375 done:
3376 smb_raw_exit(cli1->session);
3377 smb_raw_exit(cli2->session);
3378 smb_raw_exit(cli3->session);
3379 smbcli_deltree(cli1->tree, BASEDIR);
3380 return ret;
3383 static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3385 const char *fname = BASEDIR "\\test_batch24.dat";
3386 NTSTATUS status;
3387 bool ret = true;
3388 union smb_open io;
3389 uint16_t fnum2=0,fnum3=0;
3390 struct smbcli_state *cli3 = NULL;
3392 if (!torture_setup_dir(cli1, BASEDIR)) {
3393 return false;
3396 /* cleanup */
3397 smbcli_unlink(cli1->tree, fname);
3399 ret = open_connection_no_level2_oplocks(tctx, &cli3);
3400 CHECK_VAL(ret, true);
3402 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3403 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3404 smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
3407 base ntcreatex parms
3409 io.generic.level = RAW_OPEN_NTCREATEX;
3410 io.ntcreatex.in.root_fid.fnum = 0;
3411 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3412 io.ntcreatex.in.alloc_size = 0;
3413 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3414 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3415 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3416 io.ntcreatex.in.create_options = 0;
3417 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3418 io.ntcreatex.in.security_flags = 0;
3419 io.ntcreatex.in.fname = fname;
3421 torture_comment(tctx, "BATCH24: a open without level support and ask for a batch oplock\n");
3422 ZERO_STRUCT(break_info);
3424 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
3425 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
3426 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3427 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3428 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3429 status = smb_raw_open(cli3->tree, tctx, &io);
3430 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3431 fnum3 = io.ntcreatex.out.file.fnum;
3432 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3434 ZERO_STRUCT(break_info);
3436 torture_comment(tctx, "a 2nd open with level2 oplock support should generate a break to none\n");
3437 status = smb_raw_open(cli2->tree, tctx, &io);
3438 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3439 fnum2 = io.ntcreatex.out.file.fnum;
3440 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
3442 torture_wait_for_oplock_break(tctx);
3443 CHECK_VAL(break_info.count, 1);
3444 CHECK_VAL(break_info.fnum, fnum3);
3445 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3446 CHECK_VAL(break_info.failures, 0);
3448 smbcli_close(cli3->tree, fnum3);
3449 smbcli_close(cli2->tree, fnum2);
3451 done:
3452 smb_raw_exit(cli1->session);
3453 smb_raw_exit(cli2->session);
3454 smb_raw_exit(cli3->session);
3455 smbcli_deltree(cli1->tree, BASEDIR);
3456 return ret;
3459 static bool test_raw_oplock_batch25(struct torture_context *tctx,
3460 struct smbcli_state *cli1,
3461 struct smbcli_state *cli2)
3463 const char *fname = BASEDIR "\\test_batch25.dat";
3464 NTSTATUS status;
3465 bool ret = true;
3466 union smb_open io;
3467 union smb_setfileinfo sfi;
3468 uint16_t fnum=0;
3470 if (!torture_setup_dir(cli1, BASEDIR)) {
3471 return false;
3474 /* cleanup */
3475 smbcli_unlink(cli1->tree, fname);
3477 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3480 base ntcreatex parms
3482 io.generic.level = RAW_OPEN_NTCREATEX;
3483 io.ntcreatex.in.root_fid.fnum = 0;
3484 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3485 io.ntcreatex.in.alloc_size = 0;
3486 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3487 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3488 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3489 io.ntcreatex.in.create_options = 0;
3490 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3491 io.ntcreatex.in.security_flags = 0;
3492 io.ntcreatex.in.fname = fname;
3494 torture_comment(tctx, "BATCH25: open a file with an batch oplock "
3495 "(share mode: none)\n");
3497 ZERO_STRUCT(break_info);
3498 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3499 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3500 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3501 status = smb_raw_open(cli1->tree, tctx, &io);
3502 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3503 fnum = io.ntcreatex.out.file.fnum;
3504 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3506 torture_comment(tctx, "setpathinfo attribute info should not trigger "
3507 "a break nor a violation\n");
3508 ZERO_STRUCT(sfi);
3509 sfi.generic.level = RAW_SFILEINFO_SETATTR;
3510 sfi.generic.in.file.path = fname;
3511 sfi.setattr.in.attrib = FILE_ATTRIBUTE_HIDDEN;
3512 sfi.setattr.in.write_time = 0;
3514 status = smb_raw_setpathinfo(cli2->tree, &sfi);
3515 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3517 torture_wait_for_oplock_break(tctx);
3518 CHECK_VAL(break_info.count, 0);
3520 smbcli_close(cli1->tree, fnum);
3522 done:
3523 smb_raw_exit(cli1->session);
3524 smb_raw_exit(cli2->session);
3525 smbcli_deltree(cli1->tree, BASEDIR);
3526 return ret;
3530 * Similar to batch17/18, but test with open share mode rather than
3531 * share_none.
3533 static bool test_raw_oplock_batch26(struct torture_context *tctx,
3534 struct smbcli_state *cli1, struct smbcli_state *cli2)
3536 const char *fname1 = BASEDIR "\\test_batch26_1.dat";
3537 const char *fname2 = BASEDIR "\\test_batch26_2.dat";
3538 NTSTATUS status;
3539 bool ret = true;
3540 union smb_open io;
3541 union smb_rename rn;
3542 uint16_t fnum=0;
3544 if (!torture_setup_dir(cli1, BASEDIR)) {
3545 return false;
3548 /* cleanup */
3549 smbcli_unlink(cli1->tree, fname1);
3550 smbcli_unlink(cli1->tree, fname2);
3552 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3553 cli1->tree);
3556 base ntcreatex parms
3558 io.generic.level = RAW_OPEN_NTCREATEX;
3559 io.ntcreatex.in.root_fid.fnum = 0;
3560 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3561 io.ntcreatex.in.alloc_size = 0;
3562 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3563 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3564 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
3565 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3566 io.ntcreatex.in.create_options = 0;
3567 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3568 io.ntcreatex.in.security_flags = 0;
3569 io.ntcreatex.in.fname = fname1;
3571 torture_comment(tctx, "BATCH26: open a file with an batch oplock "
3572 "(share mode: none)\n");
3574 ZERO_STRUCT(break_info);
3575 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3576 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3577 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3580 status = smb_raw_open(cli1->tree, tctx, &io);
3581 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3582 fnum = io.ntcreatex.out.file.fnum;
3583 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3585 torture_comment(tctx, "rename should trigger a break\n");
3586 ZERO_STRUCT(rn);
3587 rn.generic.level = RAW_RENAME_RENAME;
3588 rn.rename.in.pattern1 = fname1;
3589 rn.rename.in.pattern2 = fname2;
3590 rn.rename.in.attrib = 0;
3592 torture_comment(tctx, "trying rename while first file open\n");
3593 status = smb_raw_rename(cli2->tree, &rn);
3594 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
3596 torture_wait_for_oplock_break(tctx);
3597 CHECK_VAL(break_info.count, 1);
3598 CHECK_VAL(break_info.failures, 0);
3599 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3601 /* Close and reopen with batch again. */
3602 smbcli_close(cli1->tree, fnum);
3603 ZERO_STRUCT(break_info);
3605 status = smb_raw_open(cli1->tree, tctx, &io);
3606 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3607 fnum = io.ntcreatex.out.file.fnum;
3608 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3610 /* Now try ntrename. */
3611 torture_comment(tctx, "ntrename should trigger a break\n");
3612 ZERO_STRUCT(rn);
3613 rn.generic.level = RAW_RENAME_NTRENAME;
3614 rn.ntrename.in.attrib = 0;
3615 rn.ntrename.in.flags = RENAME_FLAG_RENAME;
3616 rn.ntrename.in.old_name = fname1;
3617 rn.ntrename.in.new_name = fname2;
3618 torture_comment(tctx, "trying rename while first file open\n");
3619 status = smb_raw_rename(cli2->tree, &rn);
3620 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
3622 torture_wait_for_oplock_break(tctx);
3623 CHECK_VAL(break_info.count, 1);
3624 CHECK_VAL(break_info.failures, 0);
3625 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3627 smbcli_close(cli1->tree, fnum);
3629 done:
3630 smb_raw_exit(cli1->session);
3631 smb_raw_exit(cli2->session);
3632 smbcli_deltree(cli1->tree, BASEDIR);
3633 return ret;
3636 /* Test how oplocks work on streams. */
3637 static bool test_raw_oplock_stream1(struct torture_context *tctx,
3638 struct smbcli_state *cli1,
3639 struct smbcli_state *cli2)
3641 NTSTATUS status;
3642 union smb_open io;
3643 const char *fname_base = BASEDIR "\\test_stream1.txt";
3644 const char *stream = "Stream One:$DATA";
3645 const char *fname_stream, *fname_default_stream;
3646 const char *default_stream = "::$DATA";
3647 bool ret = true;
3648 int fnum = -1;
3649 int i;
3650 int stream_fnum = -1;
3651 uint32_t batch_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
3652 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK | NTCREATEX_FLAGS_EXTENDED;
3653 uint32_t exclusive_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
3654 NTCREATEX_FLAGS_EXTENDED;
3656 #define NSTREAM_OPLOCK_RESULTS 8
3657 struct {
3658 const char **fname;
3659 bool open_base_file;
3660 uint32_t oplock_req;
3661 uint32_t oplock_granted;
3662 } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
3663 /* Request oplock on stream without the base file open. */
3664 {&fname_stream, false, batch_req, NO_OPLOCK_RETURN},
3665 {&fname_default_stream, false, batch_req, NO_OPLOCK_RETURN},
3666 {&fname_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3667 {&fname_default_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3669 /* Request oplock on stream with the base file open. */
3670 {&fname_stream, true, batch_req, NO_OPLOCK_RETURN},
3671 {&fname_default_stream, true, batch_req, NO_OPLOCK_RETURN},
3672 {&fname_stream, true, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3673 {&fname_default_stream, true, exclusive_req, LEVEL_II_OPLOCK_RETURN},
3678 /* Only passes against windows at the moment. */
3679 if (torture_setting_bool(tctx, "samba3", false) ||
3680 torture_setting_bool(tctx, "samba4", false)) {
3681 torture_skip(tctx, "STREAM1 disabled against samba3+4\n");
3684 fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
3685 fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
3686 default_stream);
3688 if (!torture_setup_dir(cli1, BASEDIR)) {
3689 return false;
3691 smbcli_unlink(cli1->tree, fname_base);
3693 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3694 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3696 /* Setup generic open parameters. */
3697 io.generic.level = RAW_OPEN_NTCREATEX;
3698 io.ntcreatex.in.root_fid.fnum = 0;
3699 io.ntcreatex.in.access_mask = (SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|
3700 SEC_FILE_APPEND_DATA|SEC_STD_READ_CONTROL);
3701 io.ntcreatex.in.create_options = 0;
3702 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3703 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3704 NTCREATEX_SHARE_ACCESS_WRITE;
3705 io.ntcreatex.in.alloc_size = 0;
3706 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3707 io.ntcreatex.in.security_flags = 0;
3709 /* Create the file with a stream */
3710 io.ntcreatex.in.fname = fname_stream;
3711 io.ntcreatex.in.flags = 0;
3712 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
3713 status = smb_raw_open(cli1->tree, tctx, &io);
3714 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3715 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3717 /* Change the disposition to open now that the file has been created. */
3718 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
3720 /* Try some permutations of taking oplocks on streams. */
3721 for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
3722 const char *fname = *stream_oplock_results[i].fname;
3723 bool open_base_file = stream_oplock_results[i].open_base_file;
3724 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
3725 uint32_t oplock_granted =
3726 stream_oplock_results[i].oplock_granted;
3727 int base_fnum = -1;
3729 if (open_base_file) {
3730 torture_comment(tctx, "Opening base file: %s with "
3731 "%d\n", fname_base, batch_req);
3732 io.ntcreatex.in.fname = fname_base;
3733 io.ntcreatex.in.flags = batch_req;
3734 status = smb_raw_open(cli2->tree, tctx, &io);
3735 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3736 CHECK_VAL(io.ntcreatex.out.oplock_level,
3737 BATCH_OPLOCK_RETURN);
3738 base_fnum = io.ntcreatex.out.file.fnum;
3741 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
3742 fname, oplock_req);
3743 io.ntcreatex.in.fname = fname;
3744 io.ntcreatex.in.flags = oplock_req;
3746 /* Do the open with the desired oplock on the stream. */
3747 status = smb_raw_open(cli1->tree, tctx, &io);
3748 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3749 CHECK_VAL(io.ntcreatex.out.oplock_level, oplock_granted);
3750 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3752 /* Cleanup the base file if it was opened. */
3753 if (base_fnum != -1) {
3754 smbcli_close(cli2->tree, base_fnum);
3758 /* Open the stream with an exclusive oplock. */
3759 torture_comment(tctx, "Opening stream: %s with %d\n",
3760 fname_stream, exclusive_req);
3761 io.ntcreatex.in.fname = fname_stream;
3762 io.ntcreatex.in.flags = exclusive_req;
3763 status = smb_raw_open(cli1->tree, tctx, &io);
3764 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3765 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
3766 stream_fnum = io.ntcreatex.out.file.fnum;
3768 /* Open the base file and see if it contends. */
3769 ZERO_STRUCT(break_info);
3770 torture_comment(tctx, "Opening base file: %s with "
3771 "%d\n", fname_base, batch_req);
3772 io.ntcreatex.in.fname = fname_base;
3773 io.ntcreatex.in.flags = batch_req;
3774 status = smb_raw_open(cli2->tree, tctx, &io);
3775 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3776 CHECK_VAL(io.ntcreatex.out.oplock_level,
3777 BATCH_OPLOCK_RETURN);
3778 smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3780 torture_wait_for_oplock_break(tctx);
3781 CHECK_VAL(break_info.count, 0);
3782 CHECK_VAL(break_info.failures, 0);
3784 /* Open the stream again to see if it contends. */
3785 ZERO_STRUCT(break_info);
3786 torture_comment(tctx, "Opening stream again: %s with "
3787 "%d\n", fname_base, batch_req);
3788 io.ntcreatex.in.fname = fname_stream;
3789 io.ntcreatex.in.flags = exclusive_req;
3790 status = smb_raw_open(cli2->tree, tctx, &io);
3791 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3792 CHECK_VAL(io.ntcreatex.out.oplock_level,
3793 LEVEL_II_OPLOCK_RETURN);
3794 smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3796 torture_wait_for_oplock_break(tctx);
3797 CHECK_VAL(break_info.count, 1);
3798 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3799 CHECK_VAL(break_info.failures, 0);
3801 /* Close the stream. */
3802 if (stream_fnum != -1) {
3803 smbcli_close(cli1->tree, stream_fnum);
3806 done:
3807 smbcli_close(cli1->tree, fnum);
3808 smb_raw_exit(cli1->session);
3809 smb_raw_exit(cli2->session);
3810 smbcli_deltree(cli1->tree, BASEDIR);
3811 return ret;
3814 static bool test_raw_oplock_doc(struct torture_context *tctx,
3815 struct smbcli_state *cli,
3816 struct smbcli_state *cli2)
3818 const char *fname = BASEDIR "\\test_oplock_doc.dat";
3819 NTSTATUS status;
3820 bool ret = true;
3821 union smb_open io;
3822 uint16_t fnum=0;
3824 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
3826 /* cleanup */
3827 smbcli_unlink(cli->tree, fname);
3829 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_given,
3830 cli->tree);
3833 base ntcreatex parms
3835 io.generic.level = RAW_OPEN_NTCREATEX;
3836 io.ntcreatex.in.root_fid.fnum = 0;
3837 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3838 io.ntcreatex.in.alloc_size = 0;
3839 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3840 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
3841 NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
3842 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3843 io.ntcreatex.in.create_options = 0;
3844 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3845 io.ntcreatex.in.security_flags = 0;
3846 io.ntcreatex.in.fname = fname;
3848 torture_comment(tctx, "open a file with a batch oplock\n");
3849 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3850 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3851 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3853 status = smb_raw_open(cli->tree, tctx, &io);
3854 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3855 fnum = io.ntcreatex.out.file.fnum;
3856 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3858 torture_comment(tctx, "Set delete-on-close\n");
3859 status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
3860 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3862 torture_comment(tctx, "2nd open should not break and get "
3863 "DELETE_PENDING\n");
3864 ZERO_STRUCT(break_info);
3865 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
3866 io.ntcreatex.in.create_options = 0;
3867 io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
3868 status = smb_raw_open(cli2->tree, tctx, &io);
3869 CHECK_STATUS(tctx, status, NT_STATUS_DELETE_PENDING);
3870 CHECK_VAL(break_info.count, 0);
3872 smbcli_close(cli->tree, fnum);
3874 done:
3875 smb_raw_exit(cli->session);
3876 smbcli_deltree(cli->tree, BASEDIR);
3877 return ret;
3880 /* Open a file with a batch oplock, then open it again from a second client
3881 * requesting no oplock. Having two open file handles should break our own
3882 * oplock during BRL acquisition.
3884 static bool test_raw_oplock_brl1(struct torture_context *tctx,
3885 struct smbcli_state *cli1,
3886 struct smbcli_state *cli2)
3888 const char *fname = BASEDIR "\\test_batch_brl.dat";
3889 /*int fname, f;*/
3890 bool ret = true;
3891 uint8_t buf[1000];
3892 union smb_open io;
3893 NTSTATUS status;
3894 uint16_t fnum=0;
3895 uint16_t fnum2=0;
3897 if (!torture_setup_dir(cli1, BASEDIR)) {
3898 return false;
3901 /* cleanup */
3902 smbcli_unlink(cli1->tree, fname);
3904 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3905 cli1->tree);
3908 base ntcreatex parms
3910 io.generic.level = RAW_OPEN_NTCREATEX;
3911 io.ntcreatex.in.root_fid.fnum = 0;
3912 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3913 SEC_RIGHTS_FILE_WRITE;
3914 io.ntcreatex.in.alloc_size = 0;
3915 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3916 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3917 NTCREATEX_SHARE_ACCESS_WRITE;
3918 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3919 io.ntcreatex.in.create_options = 0;
3920 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3921 io.ntcreatex.in.security_flags = 0;
3922 io.ntcreatex.in.fname = fname;
3925 with a batch oplock we get a break
3927 torture_comment(tctx, "open with batch oplock\n");
3928 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3929 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3930 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3932 status = smb_raw_open(cli1->tree, tctx, &io);
3933 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3934 fnum = io.ntcreatex.out.file.fnum;
3935 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3936 /* create a file with bogus data */
3937 memset(buf, 0, sizeof(buf));
3939 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3940 sizeof(buf))
3942 torture_comment(tctx, "Failed to create file\n");
3943 goto done;
3946 torture_comment(tctx, "a 2nd open should give a break\n");
3947 ZERO_STRUCT(break_info);
3949 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3950 status = smb_raw_open(cli2->tree, tctx, &io);
3951 fnum2 = io.ntcreatex.out.file.fnum;
3952 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3953 CHECK_VAL(break_info.count, 1);
3954 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3955 CHECK_VAL(break_info.failures, 0);
3956 CHECK_VAL(break_info.fnum, fnum);
3958 ZERO_STRUCT(break_info);
3960 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3962 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3963 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3965 torture_wait_for_oplock_break(tctx);
3966 CHECK_VAL(break_info.count, 1);
3967 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3968 CHECK_VAL(break_info.fnum, fnum);
3969 CHECK_VAL(break_info.failures, 0);
3971 /* expect no oplock break */
3972 ZERO_STRUCT(break_info);
3973 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3974 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3976 torture_wait_for_oplock_break(tctx);
3977 CHECK_VAL(break_info.count, 0);
3978 CHECK_VAL(break_info.level, 0);
3979 CHECK_VAL(break_info.fnum, 0);
3980 CHECK_VAL(break_info.failures, 0);
3982 smbcli_close(cli1->tree, fnum);
3983 smbcli_close(cli2->tree, fnum2);
3985 done:
3986 smb_raw_exit(cli1->session);
3987 smb_raw_exit(cli2->session);
3988 smbcli_deltree(cli1->tree, BASEDIR);
3989 return ret;
3993 /* Open a file with a batch oplock on one client and then acquire a brl.
3994 * We should not contend our own oplock.
3996 static bool test_raw_oplock_brl2(struct torture_context *tctx, struct smbcli_state *cli1)
3998 const char *fname = BASEDIR "\\test_batch_brl.dat";
3999 /*int fname, f;*/
4000 bool ret = true;
4001 uint8_t buf[1000];
4002 union smb_open io;
4003 NTSTATUS status;
4004 uint16_t fnum=0;
4006 if (!torture_setup_dir(cli1, BASEDIR)) {
4007 return false;
4010 /* cleanup */
4011 smbcli_unlink(cli1->tree, fname);
4013 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
4014 cli1->tree);
4017 base ntcreatex parms
4019 io.generic.level = RAW_OPEN_NTCREATEX;
4020 io.ntcreatex.in.root_fid.fnum = 0;
4021 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
4022 SEC_RIGHTS_FILE_WRITE;
4023 io.ntcreatex.in.alloc_size = 0;
4024 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4025 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
4026 NTCREATEX_SHARE_ACCESS_WRITE;
4027 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4028 io.ntcreatex.in.create_options = 0;
4029 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4030 io.ntcreatex.in.security_flags = 0;
4031 io.ntcreatex.in.fname = fname;
4034 with a batch oplock we get a break
4036 torture_comment(tctx, "open with batch oplock\n");
4037 ZERO_STRUCT(break_info);
4038 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4039 NTCREATEX_FLAGS_REQUEST_OPLOCK |
4040 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4042 status = smb_raw_open(cli1->tree, tctx, &io);
4043 CHECK_STATUS(tctx, status, NT_STATUS_OK);
4044 fnum = io.ntcreatex.out.file.fnum;
4045 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
4047 /* create a file with bogus data */
4048 memset(buf, 0, sizeof(buf));
4050 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
4051 sizeof(buf))
4053 torture_comment(tctx, "Failed to create file\n");
4054 goto done;
4057 torture_comment(tctx, "a self BRL acquisition should not break to "
4058 "none\n");
4060 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
4061 CHECK_STATUS(tctx, status, NT_STATUS_OK);
4063 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
4064 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
4066 /* With one file handle open a BRL should not contend our oplock.
4067 * Thus, no oplock break will be received and the entire break_info
4068 * struct will be 0 */
4069 torture_wait_for_oplock_break(tctx);
4070 CHECK_VAL(break_info.fnum, 0);
4071 CHECK_VAL(break_info.count, 0);
4072 CHECK_VAL(break_info.level, 0);
4073 CHECK_VAL(break_info.failures, 0);
4075 smbcli_close(cli1->tree, fnum);
4077 done:
4078 smb_raw_exit(cli1->session);
4079 smbcli_deltree(cli1->tree, BASEDIR);
4080 return ret;
4083 /* Open a file with a batch oplock twice from one client and then acquire a
4084 * brl. BRL acquisition should break our own oplock.
4086 static bool test_raw_oplock_brl3(struct torture_context *tctx,
4087 struct smbcli_state *cli1)
4089 const char *fname = BASEDIR "\\test_batch_brl.dat";
4090 bool ret = true;
4091 uint8_t buf[1000];
4092 union smb_open io;
4093 NTSTATUS status;
4094 uint16_t fnum=0;
4095 uint16_t fnum2=0;
4097 if (!torture_setup_dir(cli1, BASEDIR)) {
4098 return false;
4101 /* cleanup */
4102 smbcli_unlink(cli1->tree, fname);
4104 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
4105 cli1->tree);
4108 base ntcreatex parms
4110 io.generic.level = RAW_OPEN_NTCREATEX;
4111 io.ntcreatex.in.root_fid.fnum = 0;
4112 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
4113 SEC_RIGHTS_FILE_WRITE;
4114 io.ntcreatex.in.alloc_size = 0;
4115 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4116 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
4117 NTCREATEX_SHARE_ACCESS_WRITE;
4118 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4119 io.ntcreatex.in.create_options = 0;
4120 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4121 io.ntcreatex.in.security_flags = 0;
4122 io.ntcreatex.in.fname = fname;
4125 with a batch oplock we get a break
4127 torture_comment(tctx, "open with batch oplock\n");
4128 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4129 NTCREATEX_FLAGS_REQUEST_OPLOCK |
4130 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4132 status = smb_raw_open(cli1->tree, tctx, &io);
4133 CHECK_STATUS(tctx, status, NT_STATUS_OK);
4134 fnum = io.ntcreatex.out.file.fnum;
4135 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
4137 /* create a file with bogus data */
4138 memset(buf, 0, sizeof(buf));
4140 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
4141 sizeof(buf))
4143 torture_comment(tctx, "Failed to create file\n");
4144 ret = false;
4145 goto done;
4148 torture_comment(tctx, "a 2nd open should give a break\n");
4149 ZERO_STRUCT(break_info);
4151 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
4152 status = smb_raw_open(cli1->tree, tctx, &io);
4153 fnum2 = io.ntcreatex.out.file.fnum;
4154 CHECK_STATUS(tctx, status, NT_STATUS_OK);
4155 CHECK_VAL(break_info.count, 1);
4156 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
4157 CHECK_VAL(break_info.failures, 0);
4158 CHECK_VAL(break_info.fnum, fnum);
4160 ZERO_STRUCT(break_info);
4162 torture_comment(tctx, "a self BRL acquisition should break to none\n");
4164 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
4165 CHECK_STATUS(tctx, status, NT_STATUS_OK);
4167 torture_wait_for_oplock_break(tctx);
4168 CHECK_VAL(break_info.count, 1);
4169 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
4170 CHECK_VAL(break_info.fnum, fnum);
4171 CHECK_VAL(break_info.failures, 0);
4173 /* expect no oplock break */
4174 ZERO_STRUCT(break_info);
4175 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
4176 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
4178 torture_wait_for_oplock_break(tctx);
4179 CHECK_VAL(break_info.count, 0);
4180 CHECK_VAL(break_info.level, 0);
4181 CHECK_VAL(break_info.fnum, 0);
4182 CHECK_VAL(break_info.failures, 0);
4184 smbcli_close(cli1->tree, fnum);
4185 smbcli_close(cli1->tree, fnum2);
4187 done:
4188 smb_raw_exit(cli1->session);
4189 smbcli_deltree(cli1->tree, BASEDIR);
4190 return ret;
4194 * Open a file with an exclusive oplock from the 1st client and acquire a
4195 * brl. Then open the same file from the 2nd client that should give oplock
4196 * break with level2 to the 1st and return no oplock to the 2nd.
4198 static bool test_raw_oplock_brl4(struct torture_context *tctx,
4199 struct smbcli_state *cli1,
4200 struct smbcli_state *cli2)
4202 const char *fname = BASEDIR "\\test_batch_brl.dat";
4203 bool ret = true;
4204 uint8_t buf[1000];
4205 union smb_open io;
4206 NTSTATUS status;
4207 uint16_t fnum = 0;
4208 uint16_t fnum2 = 0;
4210 if (!torture_setup_dir(cli1, BASEDIR)) {
4211 return false;
4214 /* cleanup */
4215 smbcli_unlink(cli1->tree, fname);
4217 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
4218 cli1->tree);
4221 base ntcreatex parms
4223 io.generic.level = RAW_OPEN_NTCREATEX;
4224 io.ntcreatex.in.root_fid.fnum = 0;
4225 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
4226 SEC_RIGHTS_FILE_WRITE;
4227 io.ntcreatex.in.alloc_size = 0;
4228 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4229 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
4230 NTCREATEX_SHARE_ACCESS_WRITE;
4231 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4232 io.ntcreatex.in.create_options = 0;
4233 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4234 io.ntcreatex.in.security_flags = 0;
4235 io.ntcreatex.in.fname = fname;
4237 torture_comment(tctx, "open with exclusive oplock\n");
4238 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4239 NTCREATEX_FLAGS_REQUEST_OPLOCK;
4241 status = smb_raw_open(cli1->tree, tctx, &io);
4243 CHECK_STATUS(tctx, status, NT_STATUS_OK);
4244 fnum = io.ntcreatex.out.file.fnum;
4245 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
4247 /* create a file with bogus data */
4248 memset(buf, 0, sizeof(buf));
4250 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
4251 sizeof(buf))
4253 torture_comment(tctx, "Failed to create file\n");
4254 goto done;
4257 status = smbcli_lock(cli1->tree, fnum, 0, 1, 0, WRITE_LOCK);
4258 CHECK_STATUS(tctx, status, NT_STATUS_OK);
4260 torture_comment(tctx, "a 2nd open should give a break to the 1st\n");
4261 ZERO_STRUCT(break_info);
4263 status = smb_raw_open(cli2->tree, tctx, &io);
4265 CHECK_STATUS(tctx, status, NT_STATUS_OK);
4266 CHECK_VAL(break_info.count, 1);
4267 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
4268 CHECK_VAL(break_info.failures, 0);
4269 CHECK_VAL(break_info.fnum, fnum);
4271 torture_comment(tctx, "and return no oplock to the 2nd\n");
4272 fnum2 = io.ntcreatex.out.file.fnum;
4273 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
4275 smbcli_close(cli1->tree, fnum);
4276 smbcli_close(cli2->tree, fnum2);
4278 done:
4279 smb_raw_exit(cli1->session);
4280 smb_raw_exit(cli2->session);
4281 smbcli_deltree(cli1->tree, BASEDIR);
4282 return ret;
4286 basic testing of oplocks
4288 struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
4290 struct torture_suite *suite = torture_suite_create(mem_ctx, "oplock");
4292 torture_suite_add_2smb_test(suite, "exclusive1", test_raw_oplock_exclusive1);
4293 torture_suite_add_2smb_test(suite, "exclusive2", test_raw_oplock_exclusive2);
4294 torture_suite_add_2smb_test(suite, "exclusive3", test_raw_oplock_exclusive3);
4295 torture_suite_add_2smb_test(suite, "exclusive4", test_raw_oplock_exclusive4);
4296 torture_suite_add_2smb_test(suite, "exclusive5", test_raw_oplock_exclusive5);
4297 torture_suite_add_2smb_test(suite, "exclusive6", test_raw_oplock_exclusive6);
4298 torture_suite_add_2smb_test(suite, "exclusive7", test_raw_oplock_exclusive7);
4299 torture_suite_add_2smb_test(suite, "exclusive8",
4300 test_raw_oplock_exclusive8);
4301 torture_suite_add_2smb_test(suite, "exclusive9",
4302 test_raw_oplock_exclusive9);
4303 torture_suite_add_2smb_test(suite, "level_ii_1",
4304 test_raw_oplock_level_ii_1);
4305 torture_suite_add_2smb_test(suite, "batch1", test_raw_oplock_batch1);
4306 torture_suite_add_2smb_test(suite, "batch2", test_raw_oplock_batch2);
4307 torture_suite_add_2smb_test(suite, "batch3", test_raw_oplock_batch3);
4308 torture_suite_add_2smb_test(suite, "batch4", test_raw_oplock_batch4);
4309 torture_suite_add_2smb_test(suite, "batch5", test_raw_oplock_batch5);
4310 torture_suite_add_2smb_test(suite, "batch6", test_raw_oplock_batch6);
4311 torture_suite_add_2smb_test(suite, "batch7", test_raw_oplock_batch7);
4312 torture_suite_add_2smb_test(suite, "batch8", test_raw_oplock_batch8);
4313 torture_suite_add_2smb_test(suite, "batch9", test_raw_oplock_batch9);
4314 torture_suite_add_2smb_test(suite, "batch10", test_raw_oplock_batch10);
4315 torture_suite_add_2smb_test(suite, "batch11", test_raw_oplock_batch11);
4316 torture_suite_add_2smb_test(suite, "batch12", test_raw_oplock_batch12);
4317 torture_suite_add_2smb_test(suite, "batch13", test_raw_oplock_batch13);
4318 torture_suite_add_2smb_test(suite, "batch14", test_raw_oplock_batch14);
4319 torture_suite_add_2smb_test(suite, "batch15", test_raw_oplock_batch15);
4320 torture_suite_add_2smb_test(suite, "batch16", test_raw_oplock_batch16);
4321 torture_suite_add_2smb_test(suite, "batch17", test_raw_oplock_batch17);
4322 torture_suite_add_2smb_test(suite, "batch18", test_raw_oplock_batch18);
4323 torture_suite_add_2smb_test(suite, "batch19", test_raw_oplock_batch19);
4324 torture_suite_add_2smb_test(suite, "batch20", test_raw_oplock_batch20);
4325 torture_suite_add_2smb_test(suite, "batch21", test_raw_oplock_batch21);
4326 torture_suite_add_2smb_test(suite, "batch22", test_raw_oplock_batch22);
4327 torture_suite_add_2smb_test(suite, "batch23", test_raw_oplock_batch23);
4328 torture_suite_add_2smb_test(suite, "batch24", test_raw_oplock_batch24);
4329 torture_suite_add_2smb_test(suite, "batch25", test_raw_oplock_batch25);
4330 torture_suite_add_2smb_test(suite, "batch26", test_raw_oplock_batch26);
4331 torture_suite_add_2smb_test(suite, "stream1", test_raw_oplock_stream1);
4332 torture_suite_add_2smb_test(suite, "doc1", test_raw_oplock_doc);
4333 torture_suite_add_2smb_test(suite, "brl1", test_raw_oplock_brl1);
4334 torture_suite_add_1smb_test(suite, "brl2", test_raw_oplock_brl2);
4335 torture_suite_add_1smb_test(suite, "brl3", test_raw_oplock_brl3);
4336 torture_suite_add_2smb_test(suite, "brl4", test_raw_oplock_brl4);
4338 return suite;
4342 stress testing of oplocks
4344 bool torture_bench_oplock(struct torture_context *torture)
4346 struct smbcli_state **cli;
4347 bool ret = true;
4348 TALLOC_CTX *mem_ctx = talloc_new(torture);
4349 int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
4350 int i, count=0;
4351 int timelimit = torture_setting_int(torture, "timelimit", 10);
4352 union smb_open io;
4353 struct timeval tv;
4355 cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
4357 torture_comment(torture, "Opening %d connections\n", torture_nprocs);
4358 for (i=0;i<torture_nprocs;i++) {
4359 if (!torture_open_connection_ev(&cli[i], i, torture, torture->ev)) {
4360 return false;
4362 talloc_steal(mem_ctx, cli[i]);
4363 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close,
4364 cli[i]->tree);
4367 if (!torture_setup_dir(cli[0], BASEDIR)) {
4368 ret = false;
4369 goto done;
4372 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
4373 io.ntcreatex.in.root_fid.fnum = 0;
4374 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
4375 io.ntcreatex.in.alloc_size = 0;
4376 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4377 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
4378 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4379 io.ntcreatex.in.create_options = 0;
4380 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4381 io.ntcreatex.in.security_flags = 0;
4382 io.ntcreatex.in.fname = BASEDIR "\\test.dat";
4383 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4384 NTCREATEX_FLAGS_REQUEST_OPLOCK |
4385 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4387 tv = timeval_current();
4390 we open the same file with SHARE_ACCESS_NONE from all the
4391 connections in a round robin fashion. Each open causes an
4392 oplock break on the previous connection, which is answered
4393 by the oplock_handler_close() to close the file.
4395 This measures how fast we can pass on oplocks, and stresses
4396 the oplock handling code
4398 torture_comment(torture, "Running for %d seconds\n", timelimit);
4399 while (timeval_elapsed(&tv) < timelimit) {
4400 for (i=0;i<torture_nprocs;i++) {
4401 NTSTATUS status;
4403 status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
4404 CHECK_STATUS(torture, status, NT_STATUS_OK);
4405 count++;
4408 if (torture_setting_bool(torture, "progress", true)) {
4409 torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
4413 torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
4415 smb_raw_exit(cli[torture_nprocs-1]->session);
4417 done:
4418 smb_raw_exit(cli[0]->session);
4419 smbcli_deltree(cli[0]->tree, BASEDIR);
4420 talloc_free(mem_ctx);
4421 return ret;
4425 static struct hold_oplock_info {
4426 const char *fname;
4427 bool close_on_break;
4428 uint32_t share_access;
4429 uint16_t fnum;
4430 } hold_info[] = {
4431 { BASEDIR "\\notshared_close", true,
4432 NTCREATEX_SHARE_ACCESS_NONE, },
4433 { BASEDIR "\\notshared_noclose", false,
4434 NTCREATEX_SHARE_ACCESS_NONE, },
4435 { BASEDIR "\\shared_close", true,
4436 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
4437 { BASEDIR "\\shared_noclose", false,
4438 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
4441 static bool oplock_handler_hold(struct smbcli_transport *transport,
4442 uint16_t tid, uint16_t fnum, uint8_t level,
4443 void *private_data)
4445 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
4446 struct hold_oplock_info *info;
4447 int i;
4449 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4450 if (hold_info[i].fnum == fnum) break;
4453 if (i == ARRAY_SIZE(hold_info)) {
4454 printf("oplock break for unknown fnum %u\n", fnum);
4455 return false;
4458 info = &hold_info[i];
4460 if (info->close_on_break) {
4461 printf("oplock break on %s - closing\n",
4462 info->fname);
4463 oplock_handler_close(transport, tid, fnum, level, private_data);
4464 return true;
4467 printf("oplock break on %s - acking break\n", info->fname);
4469 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
4474 used for manual testing of oplocks - especially interaction with
4475 other filesystems (such as NFS and local access)
4477 bool torture_hold_oplock(struct torture_context *torture,
4478 struct smbcli_state *cli)
4480 struct tevent_context *ev = torture->ev;
4481 int i;
4483 printf("Setting up open files with oplocks in %s\n", BASEDIR);
4485 torture_assert(torture, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
4487 smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
4489 /* setup the files */
4490 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4491 union smb_open io;
4492 NTSTATUS status;
4493 char c = 1;
4495 io.generic.level = RAW_OPEN_NTCREATEX;
4496 io.ntcreatex.in.root_fid.fnum = 0;
4497 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
4498 io.ntcreatex.in.alloc_size = 0;
4499 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4500 io.ntcreatex.in.share_access = hold_info[i].share_access;
4501 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4502 io.ntcreatex.in.create_options = 0;
4503 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4504 io.ntcreatex.in.security_flags = 0;
4505 io.ntcreatex.in.fname = hold_info[i].fname;
4506 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4507 NTCREATEX_FLAGS_REQUEST_OPLOCK |
4508 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4509 printf("opening %s\n", hold_info[i].fname);
4511 status = smb_raw_open(cli->tree, cli, &io);
4512 if (!NT_STATUS_IS_OK(status)) {
4513 printf("Failed to open %s - %s\n",
4514 hold_info[i].fname, nt_errstr(status));
4515 return false;
4518 if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
4519 printf("Oplock not granted for %s - expected %d but got %d\n",
4520 hold_info[i].fname, BATCH_OPLOCK_RETURN,
4521 io.ntcreatex.out.oplock_level);
4522 return false;
4524 hold_info[i].fnum = io.ntcreatex.out.file.fnum;
4526 /* make the file non-zero size */
4527 if (smbcli_write(cli->tree, hold_info[i].fnum, 0, &c, 0, 1) != 1) {
4528 printf("Failed to write to file\n");
4529 return false;
4533 printf("Waiting for oplock events\n");
4534 tevent_loop_wait(ev);
4536 return true;