s4:torture/smb2: remove samba specific stuff from smb2.oplock
[metze/samba/wip.git] / source4 / torture / smb2 / oplock.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    test suite for SMB2 oplocks
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Stefan Metzmacher 2008
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24
25 #include "libcli/smb2/smb2.h"
26 #include "libcli/smb2/smb2_calls.h"
27 #include "libcli/smb_composite/smb_composite.h"
28 #include "libcli/resolve/resolve.h"
29
30 #include "lib/cmdline/popt_common.h"
31 #include "lib/events/events.h"
32
33 #include "param/param.h"
34 #include "system/filesys.h"
35
36 #include "torture/torture.h"
37 #include "torture/smb2/proto.h"
38
39 #define CHECK_RANGE(v, min, max) do { \
40         if ((v) < (min) || (v) > (max)) { \
41                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s " \
42                                "got %d - should be between %d and %d\n", \
43                                 __location__, #v, (int)v, (int)min, (int)max); \
44                 ret = false; \
45         }} while (0)
46
47 #define CHECK_STRMATCH(v, correct) do { \
48         if (!v || strstr((v),(correct)) == NULL) { \
49                 torture_result(tctx, TORTURE_FAIL,  "(%s): wrong value for %s "\
50                                "got '%s' - should be '%s'\n", \
51                                 __location__, #v, v?v:"NULL", correct); \
52                 ret = false; \
53         }} while (0)
54
55 #define CHECK_VAL(v, correct) do { \
56         if ((v) != (correct)) { \
57                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s " \
58                                "got 0x%x - should be 0x%x\n", \
59                                 __location__, #v, (int)v, (int)correct); \
60                 ret = false; \
61         }} while (0)
62
63 #define BASEDIR "oplock_test"
64
65 static struct {
66         struct smb2_handle handle;
67         uint8_t level;
68         struct smb2_break br;
69         int count;
70         int failures;
71         NTSTATUS failure_status;
72 } break_info;
73
74 static void torture_oplock_break_callback(struct smb2_request *req)
75 {
76         NTSTATUS status;
77         struct smb2_break br;
78
79         ZERO_STRUCT(br);
80         status = smb2_break_recv(req, &break_info.br);
81         if (!NT_STATUS_IS_OK(status)) {
82                 break_info.failures++;
83                 break_info.failure_status = status;
84         }
85
86         return;
87 }
88
89 /* A general oplock break notification handler.  This should be used when a
90  * test expects to break from batch or exclusive to a lower level. */
91 static bool torture_oplock_handler(struct smb2_transport *transport,
92                                    const struct smb2_handle *handle,
93                                    uint8_t level,
94                                    void *private_data)
95 {
96         struct smb2_tree *tree = private_data;
97         const char *name;
98         struct smb2_request *req;
99         ZERO_STRUCT(break_info.br);
100
101         break_info.handle       = *handle;
102         break_info.level        = level;
103         break_info.count++;
104
105         switch (level) {
106         case SMB2_OPLOCK_LEVEL_II:
107                 name = "level II";
108                 break;
109         case SMB2_OPLOCK_LEVEL_NONE:
110                 name = "none";
111                 break;
112         default:
113                 name = "unknown";
114                 break_info.failures++;
115         }
116         printf("Acking to %s [0x%02X] in oplock handler\n", name, level);
117
118         break_info.br.in.file.handle    = *handle;
119         break_info.br.in.oplock_level   = level;
120         break_info.br.in.reserved       = 0;
121         break_info.br.in.reserved2      = 0;
122
123         req = smb2_break_send(tree, &break_info.br);
124         req->async.fn = torture_oplock_break_callback;
125         req->async.private_data = NULL;
126         return true;
127 }
128
129 /*
130   A handler function for oplock break notifications. Send a break to none
131   request.
132 */
133 static bool torture_oplock_handler_ack_to_none(struct smb2_transport *transport,
134                                                const struct smb2_handle *handle,
135                                                uint8_t level,
136                                                void *private_data)
137 {
138         struct smb2_tree *tree = private_data;
139         struct smb2_request *req;
140
141         break_info.handle = *handle;
142         break_info.level = level;
143         break_info.count++;
144
145         printf("Acking to none in oplock handler\n");
146
147         ZERO_STRUCT(break_info.br);
148         break_info.br.in.file.handle    = *handle;
149         break_info.br.in.oplock_level   = SMB2_OPLOCK_LEVEL_NONE;
150         break_info.br.in.reserved       = 0;
151         break_info.br.in.reserved2      = 0;
152
153         req = smb2_break_send(tree, &break_info.br);
154         req->async.fn = torture_oplock_break_callback;
155         req->async.private_data = NULL;
156
157         return true;
158 }
159
160 /*
161   A handler function for oplock break notifications. Break from level II to
162   none.  SMB2 requires that the client does not send an oplock break request to
163   the server in this case.
164 */
165 static bool torture_oplock_handler_level2_to_none(
166                                                struct smb2_transport *transport,
167                                                const struct smb2_handle *handle,
168                                                uint8_t level,
169                                                void *private_data)
170 {
171         break_info.handle = *handle;
172         break_info.level = level;
173         break_info.count++;
174
175         printf("Break from level II to none in oplock handler\n");
176
177         return true;
178 }
179
180 /* A handler function for oplock break notifications.  This should be used when
181  * test expects two break notifications, first to level II, then to none. */
182 static bool torture_oplock_handler_two_notifications(
183                                         struct smb2_transport *transport,
184                                         const struct smb2_handle *handle,
185                                         uint8_t level,
186                                         void *private_data)
187 {
188         struct smb2_tree *tree = private_data;
189         const char *name;
190         struct smb2_request *req;
191         ZERO_STRUCT(break_info.br);
192
193         break_info.handle       = *handle;
194         break_info.level        = level;
195         break_info.count++;
196
197         switch (level) {
198         case SMB2_OPLOCK_LEVEL_II:
199                 name = "level II";
200                 break;
201         case SMB2_OPLOCK_LEVEL_NONE:
202                 name = "none";
203                 break;
204         default:
205                 name = "unknown";
206                 break_info.failures++;
207         }
208         printf("Breaking to %s [0x%02X] in oplock handler\n", name, level);
209
210         if (level == SMB2_OPLOCK_LEVEL_NONE)
211                 return true;
212
213         break_info.br.in.file.handle    = *handle;
214         break_info.br.in.oplock_level   = level;
215         break_info.br.in.reserved       = 0;
216         break_info.br.in.reserved2      = 0;
217
218         req = smb2_break_send(tree, &break_info.br);
219         req->async.fn = torture_oplock_break_callback;
220         req->async.private_data = NULL;
221         return true;
222 }
223 static void torture_oplock_handler_close_recv(struct smb2_request *req)
224 {
225         if (!smb2_request_receive(req)) {
226                 printf("close failed in oplock_handler_close\n");
227                 break_info.failures++;
228         }
229 }
230
231 /*
232   a handler function for oplock break requests - close the file
233 */
234 static bool torture_oplock_handler_close(struct smb2_transport *transport,
235                                          const struct smb2_handle *handle,
236                                          uint8_t level,
237                                          void *private_data)
238 {
239         struct smb2_close io;
240         struct smb2_tree *tree = private_data;
241         struct smb2_request *req;
242
243         break_info.handle = *handle;
244         break_info.level = level;
245         break_info.count++;
246
247         ZERO_STRUCT(io);
248         io.in.file.handle       = *handle;
249         io.in.flags          = RAW_CLOSE_SMB2;
250         req = smb2_close_send(tree, &io);
251         if (req == NULL) {
252                 printf("failed to send close in oplock_handler_close\n");
253                 return false;
254         }
255
256         req->async.fn = torture_oplock_handler_close_recv;
257         req->async.private_data = NULL;
258
259         return true;
260 }
261
262 /*
263   a handler function for oplock break requests. Let it timeout
264 */
265 static bool torture_oplock_handler_timeout(struct smb2_transport *transport,
266                                            const struct smb2_handle *handle,
267                                            uint8_t level,
268                                            void *private_data)
269 {
270         break_info.handle = *handle;
271         break_info.level = level;
272         break_info.count++;
273
274         printf("Let oplock break timeout\n");
275         return true;
276 }
277
278 static bool open_smb2_connection_no_level2_oplocks(struct torture_context *tctx,
279                                                    struct smb2_tree **tree)
280 {
281         NTSTATUS status;
282         const char *host = torture_setting_string(tctx, "host", NULL);
283         const char *share = torture_setting_string(tctx, "share", NULL);
284         struct cli_credentials *credentials = cmdline_credentials;
285         struct smbcli_options options;
286
287         lpcfg_smbcli_options(tctx->lp_ctx, &options);
288         options.use_level2_oplocks = false;
289
290         status = smb2_connect(tctx, host,
291                               lpcfg_smb_ports(tctx->lp_ctx), share,
292                               lpcfg_resolve_context(tctx->lp_ctx),
293                               credentials, tree, tctx->ev, &options,
294                               lpcfg_socket_options(tctx->lp_ctx),
295                               lpcfg_gensec_settings(tctx, tctx->lp_ctx));
296         if (!NT_STATUS_IS_OK(status)) {
297                 torture_comment(tctx, "Failed to connect to SMB2 share "
298                                 "\\\\%s\\%s - %s\n", host, share,
299                                 nt_errstr(status));
300                 return false;
301         }
302         return true;
303 }
304
305 /*
306    Timer handler function notifies the registering function that time is up
307 */
308 static void timeout_cb(struct tevent_context *ev,
309                        struct tevent_timer *te,
310                        struct timeval current_time,
311                        void *private_data)
312 {
313         bool *timesup = (bool *)private_data;
314         *timesup = true;
315         return;
316 }
317
318 /*
319    Wait a short period of time to receive a single oplock break request
320 */
321 static void torture_wait_for_oplock_break(struct torture_context *tctx)
322 {
323         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
324         struct tevent_timer *te = NULL;
325         struct timeval ne;
326         bool timesup = false;
327         int old_count = break_info.count;
328
329         /* Wait .1 seconds for an oplock break */
330         ne = tevent_timeval_current_ofs(0, 100000);
331
332         if ((te = event_add_timed(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup))
333             == NULL)
334         {
335                 torture_comment(tctx, "Failed to wait for an oplock break. "
336                                       "test results may not be accurate.");
337                 goto done;
338         }
339
340         while (!timesup && break_info.count < old_count + 1) {
341                 if (event_loop_once(tctx->ev) != 0) {
342                         torture_comment(tctx, "Failed to wait for an oplock "
343                                               "break. test results may not be "
344                                               "accurate.");
345                         goto done;
346                 }
347         }
348
349 done:
350         /* We don't know if the timed event fired and was freed, we received
351          * our oplock break, or some other event triggered the loop.  Thus,
352          * we create a tmp_ctx to be able to safely free/remove the timed
353          * event in all 3 cases. */
354         talloc_free(tmp_ctx);
355
356         return;
357 }
358
359 static bool test_smb2_oplock_exclusive1(struct torture_context *tctx,
360                                         struct smb2_tree *tree1,
361                                         struct smb2_tree *tree2)
362 {
363         const char *fname = BASEDIR "\\test_exclusive1.dat";
364         NTSTATUS status;
365         bool ret = true;
366         union smb_open io;
367         union smb_unlink unl;
368         struct smb2_handle h1;
369         struct smb2_handle h;
370
371         status = torture_smb2_testdir(tree1, BASEDIR, &h);
372         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
373
374         /* cleanup */
375         smb2_util_unlink(tree1, fname);
376
377         tree1->session->transport->oplock.handler = torture_oplock_handler;
378         tree1->session->transport->oplock.private_data = tree1;
379
380         /*
381           base ntcreatex parms
382         */
383         ZERO_STRUCT(io.smb2);
384         io.generic.level = RAW_OPEN_SMB2;
385         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
386         io.smb2.in.alloc_size = 0;
387         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
388         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
389         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
390         io.smb2.in.create_options = 0;
391         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
392         io.smb2.in.security_flags = 0;
393         io.smb2.in.fname = fname;
394
395         torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive "
396                         "oplock (share mode: none)\n");
397         ZERO_STRUCT(break_info);
398         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
399
400         status = smb2_create(tree1, tctx, &(io.smb2));
401         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
402         h1 = io.smb2.out.file.handle;
403         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
404
405         torture_comment(tctx, "a 2nd open should not cause a break\n");
406         status = smb2_create(tree2, tctx, &(io.smb2));
407         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
408                                       "Incorrect status");
409         torture_wait_for_oplock_break(tctx);
410         CHECK_VAL(break_info.count, 0);
411         CHECK_VAL(break_info.failures, 0);
412
413         torture_comment(tctx, "unlink it - should also be no break\n");
414         unl.unlink.in.pattern = fname;
415         unl.unlink.in.attrib = 0;
416         status = smb2_util_unlink(tree2, fname);
417         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
418                                       "Incorrect status");
419         torture_wait_for_oplock_break(tctx);
420         CHECK_VAL(break_info.count, 0);
421         CHECK_VAL(break_info.failures, 0);
422
423         smb2_util_close(tree1, h1);
424         smb2_util_close(tree1, h);
425
426         smb2_deltree(tree1, BASEDIR);
427         return ret;
428 }
429
430 static bool test_smb2_oplock_exclusive2(struct torture_context *tctx,
431                                         struct smb2_tree *tree1,
432                                         struct smb2_tree *tree2)
433 {
434         const char *fname = BASEDIR "\\test_exclusive2.dat";
435         NTSTATUS status;
436         bool ret = true;
437         union smb_open io;
438         union smb_unlink unl;
439         struct smb2_handle h, h1, h2;
440
441         status = torture_smb2_testdir(tree1, BASEDIR, &h);
442         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
443
444         /* cleanup */
445         smb2_util_unlink(tree1, fname);
446
447         tree1->session->transport->oplock.handler = torture_oplock_handler;
448         tree1->session->transport->oplock.private_data = tree1;
449
450         /*
451           base ntcreatex parms
452         */
453         ZERO_STRUCT(io.smb2);
454         io.generic.level = RAW_OPEN_SMB2;
455         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
456         io.smb2.in.alloc_size = 0;
457         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
458         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
459         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
460         io.smb2.in.create_options = 0;
461         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
462         io.smb2.in.security_flags = 0;
463         io.smb2.in.fname = fname;
464
465         torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive "
466                         "oplock (share mode: all)\n");
467         ZERO_STRUCT(break_info);
468         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
469         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
470                 NTCREATEX_SHARE_ACCESS_WRITE|
471                 NTCREATEX_SHARE_ACCESS_DELETE;
472         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
473
474         status = smb2_create(tree1, tctx, &(io.smb2));
475         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
476         h1 = io.smb2.out.file.handle;
477         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
478
479         torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
480         status = smb2_create(tree2, tctx, &(io.smb2));
481         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
482         h2 = io.smb2.out.file.handle;
483         torture_wait_for_oplock_break(tctx);
484         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
485         CHECK_VAL(break_info.count, 1);
486         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
487         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
488         CHECK_VAL(break_info.failures, 0);
489         ZERO_STRUCT(break_info);
490
491         /* now we have 2 level II oplocks... */
492         torture_comment(tctx, "try to unlink it - should cause a break\n");
493         unl.unlink.in.pattern = fname;
494         unl.unlink.in.attrib = 0;
495         status = smb2_util_unlink(tree2, fname);
496         torture_assert_ntstatus_ok(tctx, status, "Error unlinking the file");
497         torture_wait_for_oplock_break(tctx);
498         CHECK_VAL(break_info.count, 0);
499         CHECK_VAL(break_info.failures, 0);
500
501         torture_comment(tctx, "close both handles\n");
502         smb2_util_close(tree1, h1);
503         smb2_util_close(tree1, h2);
504         smb2_util_close(tree1, h);
505
506         smb2_deltree(tree1, BASEDIR);
507         return ret;
508 }
509
510 static bool test_smb2_oplock_exclusive3(struct torture_context *tctx,
511                                         struct smb2_tree *tree1,
512                                         struct smb2_tree *tree2)
513 {
514         const char *fname = BASEDIR "\\test_exclusive3.dat";
515         NTSTATUS status;
516         bool ret = true;
517         union smb_open io;
518         union smb_setfileinfo sfi;
519         struct smb2_handle h, h1;
520
521         status = torture_smb2_testdir(tree1, BASEDIR, &h);
522         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
523
524         /* cleanup */
525         smb2_util_unlink(tree1, fname);
526
527         tree1->session->transport->oplock.handler = torture_oplock_handler;
528         tree1->session->transport->oplock.private_data = tree1;
529
530         /*
531           base ntcreatex parms
532         */
533         ZERO_STRUCT(io.smb2);
534         io.generic.level = RAW_OPEN_SMB2;
535         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
536         io.smb2.in.alloc_size = 0;
537         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
538         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
539         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
540         io.smb2.in.create_options = 0;
541         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
542         io.smb2.in.security_flags = 0;
543         io.smb2.in.fname = fname;
544
545         torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive "
546                         "oplock (share mode: none)\n");
547
548         ZERO_STRUCT(break_info);
549         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
550         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
551
552         status = smb2_create(tree1, tctx, &(io.smb2));
553         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
554         h1 = io.smb2.out.file.handle;
555         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
556
557         torture_comment(tctx, "setpathinfo EOF should trigger a break to "
558                         "none\n");
559         ZERO_STRUCT(sfi);
560         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
561         sfi.generic.in.file.path = fname;
562         sfi.end_of_file_info.in.size = 100;
563
564         status = smb2_composite_setpathinfo(tree2, &sfi);
565
566         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
567                                       "Incorrect status");
568         torture_wait_for_oplock_break(tctx);
569         CHECK_VAL(break_info.count, 0);
570         CHECK_VAL(break_info.failures, 0);
571         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
572
573         smb2_util_close(tree1, h1);
574         smb2_util_close(tree1, h);
575
576         smb2_deltree(tree1, BASEDIR);
577         return ret;
578 }
579
580 static bool test_smb2_oplock_exclusive4(struct torture_context *tctx,
581                                         struct smb2_tree *tree1,
582                                         struct smb2_tree *tree2)
583 {
584         const char *fname = BASEDIR "\\test_exclusive4.dat";
585         NTSTATUS status;
586         bool ret = true;
587         union smb_open io;
588         struct smb2_handle h, h1, h2;
589
590         status = torture_smb2_testdir(tree1, BASEDIR, &h);
591         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
592
593         /* cleanup */
594         smb2_util_unlink(tree1, fname);
595
596         tree1->session->transport->oplock.handler = torture_oplock_handler;
597         tree1->session->transport->oplock.private_data = tree1;
598
599         /*
600           base ntcreatex parms
601         */
602         ZERO_STRUCT(io.smb2);
603         io.generic.level = RAW_OPEN_SMB2;
604         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
605         io.smb2.in.alloc_size = 0;
606         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
607         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
608         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
609         io.smb2.in.create_options = 0;
610         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
611         io.smb2.in.security_flags = 0;
612         io.smb2.in.fname = fname;
613
614         torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
615         ZERO_STRUCT(break_info);
616
617         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
618         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
619         status = smb2_create(tree1, tctx, &(io.smb2));
620         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
621         h1 = io.smb2.out.file.handle;
622         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
623
624         ZERO_STRUCT(break_info);
625         torture_comment(tctx, "second open with attributes only shouldn't "
626                         "cause oplock break\n");
627
628         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
629         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
630                                 SEC_FILE_WRITE_ATTRIBUTE |
631                                 SEC_STD_SYNCHRONIZE;
632         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
633         status = smb2_create(tree2, tctx, &(io.smb2));
634         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
635         h2 = io.smb2.out.file.handle;
636         CHECK_VAL(io.smb2.out.oplock_level, NO_OPLOCK_RETURN);
637         torture_wait_for_oplock_break(tctx);
638         CHECK_VAL(break_info.count, 0);
639         CHECK_VAL(break_info.failures, 0);
640
641         smb2_util_close(tree1, h1);
642         smb2_util_close(tree2, h2);
643         smb2_util_close(tree1, h);
644
645         smb2_deltree(tree1, BASEDIR);
646         return ret;
647 }
648
649 static bool test_smb2_oplock_exclusive5(struct torture_context *tctx,
650                                         struct smb2_tree *tree1,
651                                         struct smb2_tree *tree2)
652 {
653         const char *fname = BASEDIR "\\test_exclusive5.dat";
654         NTSTATUS status;
655         bool ret = true;
656         union smb_open io;
657         struct smb2_handle h, h1, h2;
658
659         status = torture_smb2_testdir(tree1, BASEDIR, &h);
660         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
661
662         /* cleanup */
663         smb2_util_unlink(tree1, fname);
664
665         tree1->session->transport->oplock.handler = torture_oplock_handler;
666         tree1->session->transport->oplock.private_data = tree1;
667
668         tree2->session->transport->oplock.handler = torture_oplock_handler;
669         tree2->session->transport->oplock.private_data = tree2;
670
671         /*
672           base ntcreatex parms
673         */
674         ZERO_STRUCT(io.smb2);
675         io.generic.level = RAW_OPEN_SMB2;
676         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
677         io.smb2.in.alloc_size = 0;
678         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
679         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
680         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
681         io.smb2.in.create_options = 0;
682         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
683         io.smb2.in.security_flags = 0;
684         io.smb2.in.fname = fname;
685
686         torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
687         ZERO_STRUCT(break_info);
688
689         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
690         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
691                 NTCREATEX_SHARE_ACCESS_WRITE|
692                 NTCREATEX_SHARE_ACCESS_DELETE;
693         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
694         status = smb2_create(tree1, tctx, &(io.smb2));
695         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
696         h1 = io.smb2.out.file.handle;
697         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
698
699         ZERO_STRUCT(break_info);
700
701         torture_comment(tctx, "second open with attributes only and "
702                         "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
703                         "oplock break\n");
704
705         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
706         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
707                                 SEC_FILE_WRITE_ATTRIBUTE |
708                                 SEC_STD_SYNCHRONIZE;
709         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
710         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
711         status = smb2_create(tree2, tctx, &(io.smb2));
712         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
713         h2 = io.smb2.out.file.handle;
714         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
715         torture_wait_for_oplock_break(tctx);
716         CHECK_VAL(break_info.count, 1);
717         CHECK_VAL(break_info.failures, 0);
718
719         smb2_util_close(tree1, h1);
720         smb2_util_close(tree2, h2);
721         smb2_util_close(tree1, h);
722
723         smb2_deltree(tree1, BASEDIR);
724         return ret;
725 }
726
727 static bool test_smb2_oplock_exclusive6(struct torture_context *tctx,
728                                         struct smb2_tree *tree1,
729                                         struct smb2_tree *tree2)
730 {
731         const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
732         const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
733         NTSTATUS status;
734         bool ret = true;
735         union smb_open io;
736         union smb_setfileinfo sinfo;
737         struct smb2_handle h, h1;
738
739         status = torture_smb2_testdir(tree1, BASEDIR, &h);
740         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
741
742         /* cleanup */
743         smb2_util_unlink(tree1, fname1);
744         smb2_util_unlink(tree2, fname2);
745
746         tree1->session->transport->oplock.handler = torture_oplock_handler;
747         tree1->session->transport->oplock.private_data = tree1;
748
749         /*
750           base ntcreatex parms
751         */
752         ZERO_STRUCT(io.smb2);
753         io.generic.level = RAW_OPEN_SMB2;
754         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
755         io.smb2.in.alloc_size = 0;
756         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
757         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
758         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
759         io.smb2.in.create_options = 0;
760         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
761         io.smb2.in.security_flags = 0;
762         io.smb2.in.fname = fname1;
763
764         torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
765                         "oplock (share mode: none)\n");
766         ZERO_STRUCT(break_info);
767         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
768         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
769
770         status = smb2_create(tree1, tctx, &(io.smb2));
771         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
772         h1 = io.smb2.out.file.handle;
773         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
774
775         torture_comment(tctx, "rename should not generate a break but get "
776                         "a sharing violation\n");
777         ZERO_STRUCT(sinfo);
778         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
779         sinfo.rename_information.in.file.handle = h1;
780         sinfo.rename_information.in.overwrite = true;
781         sinfo.rename_information.in.new_name = fname2;
782         status = smb2_setinfo_file(tree1, &sinfo);
783
784         torture_comment(tctx, "trying rename while first file open\n");
785         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
786                                       "Incorrect status");
787         torture_wait_for_oplock_break(tctx);
788         CHECK_VAL(break_info.count, 0);
789         CHECK_VAL(break_info.failures, 0);
790
791         smb2_util_close(tree1, h1);
792         smb2_util_close(tree1, h);
793
794         smb2_deltree(tree1, BASEDIR);
795         return ret;
796 }
797
798 static bool test_smb2_oplock_batch1(struct torture_context *tctx,
799                                     struct smb2_tree *tree1,
800                                     struct smb2_tree *tree2)
801 {
802         const char *fname = BASEDIR "\\test_batch1.dat";
803         NTSTATUS status;
804         bool ret = true;
805         union smb_open io;
806         struct smb2_handle h, h1;
807         char c = 0;
808
809         status = torture_smb2_testdir(tree1, BASEDIR, &h);
810         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
811
812         /* cleanup */
813         smb2_util_unlink(tree1, fname);
814
815         tree1->session->transport->oplock.handler = torture_oplock_handler;
816         tree1->session->transport->oplock.private_data = tree1;
817
818         /*
819           base ntcreatex parms
820         */
821         ZERO_STRUCT(io.smb2);
822         io.generic.level = RAW_OPEN_SMB2;
823         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
824         io.smb2.in.alloc_size = 0;
825         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
826         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
827         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
828         io.smb2.in.create_options = 0;
829         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
830         io.smb2.in.security_flags = 0;
831         io.smb2.in.fname = fname;
832
833         /*
834           with a batch oplock we get a break
835         */
836         torture_comment(tctx, "BATCH1: open with batch oplock\n");
837         ZERO_STRUCT(break_info);
838         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
839         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
840         status = smb2_create(tree1, tctx, &(io.smb2));
841         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
842         h1 = io.smb2.out.file.handle;
843         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
844
845         torture_comment(tctx, "unlink should generate a break\n");
846         status = smb2_util_unlink(tree2, fname);
847         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
848                                       "Incorrect status");
849
850         torture_wait_for_oplock_break(tctx);
851         CHECK_VAL(break_info.count, 1);
852         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
853         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
854         CHECK_VAL(break_info.failures, 0);
855
856         torture_comment(tctx, "2nd unlink should not generate a break\n");
857         ZERO_STRUCT(break_info);
858         status = smb2_util_unlink(tree2, fname);
859         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
860                                       "Incorrect status");
861
862         torture_wait_for_oplock_break(tctx);
863         CHECK_VAL(break_info.count, 0);
864
865         torture_comment(tctx, "writing should generate a self break to none\n");
866         tree1->session->transport->oplock.handler =
867             torture_oplock_handler_level2_to_none;
868         smb2_util_write(tree1, h1, &c, 0, 1);
869
870         torture_wait_for_oplock_break(tctx);
871
872         CHECK_VAL(break_info.count, 1);
873         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
874         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
875         CHECK_VAL(break_info.failures, 0);
876
877         smb2_util_close(tree1, h1);
878         smb2_util_close(tree1, h);
879
880         smb2_deltree(tree1, BASEDIR);
881         return ret;
882 }
883
884 static bool test_smb2_oplock_batch2(struct torture_context *tctx,
885                                     struct smb2_tree *tree1,
886                                     struct smb2_tree *tree2)
887 {
888         const char *fname = BASEDIR "\\test_batch2.dat";
889         NTSTATUS status;
890         bool ret = true;
891         union smb_open io;
892         char c = 0;
893         struct smb2_handle h, h1;
894
895         status = torture_smb2_testdir(tree1, BASEDIR, &h);
896         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
897
898         /* cleanup */
899         smb2_util_unlink(tree1, fname);
900
901         tree1->session->transport->oplock.handler = torture_oplock_handler;
902         tree1->session->transport->oplock.private_data = tree1;
903
904         /*
905           base ntcreatex parms
906         */
907         ZERO_STRUCT(io.smb2);
908         io.generic.level = RAW_OPEN_SMB2;
909         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
910         io.smb2.in.alloc_size = 0;
911         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
912         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
913         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
914         io.smb2.in.create_options = 0;
915         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
916         io.smb2.in.security_flags = 0;
917         io.smb2.in.fname = fname;
918
919         torture_comment(tctx, "BATCH2: open with batch oplock\n");
920         ZERO_STRUCT(break_info);
921         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
922         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
923         status = smb2_create(tree1, tctx, &(io.smb2));
924         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
925         h1 = io.smb2.out.file.handle;
926         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
927
928         torture_comment(tctx, "unlink should generate a break, which we ack "
929                         "as break to none\n");
930         tree1->session->transport->oplock.handler =
931                                 torture_oplock_handler_ack_to_none;
932         tree1->session->transport->oplock.private_data = tree1;
933         status = smb2_util_unlink(tree2, fname);
934         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
935                                      "Incorrect status");
936
937         torture_wait_for_oplock_break(tctx);
938         CHECK_VAL(break_info.count, 1);
939         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
940         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
941         CHECK_VAL(break_info.failures, 0);
942
943         torture_comment(tctx, "2nd unlink should not generate a break\n");
944         ZERO_STRUCT(break_info);
945         status = smb2_util_unlink(tree2, fname);
946         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
947                                       "Incorrect status");
948
949         torture_wait_for_oplock_break(tctx);
950         CHECK_VAL(break_info.count, 0);
951
952         torture_comment(tctx, "writing should not generate a break\n");
953         smb2_util_write(tree1, h1, &c, 0, 1);
954
955         torture_wait_for_oplock_break(tctx);
956         CHECK_VAL(break_info.count, 0);
957
958         smb2_util_close(tree1, h1);
959         smb2_util_close(tree1, h);
960
961         smb2_deltree(tree1, BASEDIR);
962         return ret;
963 }
964
965 static bool test_smb2_oplock_batch3(struct torture_context *tctx,
966                                     struct smb2_tree *tree1,
967                                     struct smb2_tree *tree2)
968 {
969         const char *fname = BASEDIR "\\test_batch3.dat";
970         NTSTATUS status;
971         bool ret = true;
972         union smb_open io;
973         struct smb2_handle h, h1;
974
975         status = torture_smb2_testdir(tree1, BASEDIR, &h);
976         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
977
978         /* cleanup */
979         smb2_util_unlink(tree1, fname);
980         tree1->session->transport->oplock.handler = torture_oplock_handler;
981         tree1->session->transport->oplock.private_data = tree1;
982
983         /*
984           base ntcreatex parms
985         */
986         ZERO_STRUCT(io.smb2);
987         io.generic.level = RAW_OPEN_SMB2;
988         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
989         io.smb2.in.alloc_size = 0;
990         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
991         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
992         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
993         io.smb2.in.create_options = 0;
994         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
995         io.smb2.in.security_flags = 0;
996         io.smb2.in.fname = fname;
997
998         torture_comment(tctx, "BATCH3: if we close on break then the unlink "
999                         "can succeed\n");
1000         ZERO_STRUCT(break_info);
1001         tree1->session->transport->oplock.handler =
1002                                         torture_oplock_handler_close;
1003         tree1->session->transport->oplock.private_data = tree1;
1004
1005         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1006         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1007         status = smb2_create(tree1, tctx, &(io.smb2));
1008         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1009         h1 = io.smb2.out.file.handle;
1010         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1011
1012         ZERO_STRUCT(break_info);
1013         status = smb2_util_unlink(tree2, fname);
1014         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1015
1016         torture_wait_for_oplock_break(tctx);
1017         CHECK_VAL(break_info.count, 1);
1018         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1019         CHECK_VAL(break_info.level, 1);
1020         CHECK_VAL(break_info.failures, 0);
1021
1022         smb2_util_close(tree1, h1);
1023         smb2_util_close(tree1, h);
1024
1025         smb2_deltree(tree1, BASEDIR);
1026         return ret;
1027 }
1028
1029 static bool test_smb2_oplock_batch4(struct torture_context *tctx,
1030                                     struct smb2_tree *tree1,
1031                                     struct smb2_tree *tree2)
1032 {
1033         const char *fname = BASEDIR "\\test_batch4.dat";
1034         NTSTATUS status;
1035         bool ret = true;
1036         union smb_open io;
1037         struct smb2_read r;
1038         struct smb2_handle h, h1;
1039
1040         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1041         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1042
1043         /* cleanup */
1044         smb2_util_unlink(tree1, fname);
1045
1046         tree1->session->transport->oplock.handler = torture_oplock_handler;
1047         tree1->session->transport->oplock.private_data = tree1;
1048
1049         /*
1050           base ntcreatex parms
1051         */
1052         ZERO_STRUCT(io.smb2);
1053         io.generic.level = RAW_OPEN_SMB2;
1054         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1055         io.smb2.in.alloc_size = 0;
1056         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1057         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1058         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1059         io.smb2.in.create_options = 0;
1060         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1061         io.smb2.in.security_flags = 0;
1062         io.smb2.in.fname = fname;
1063
1064         torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
1065         ZERO_STRUCT(break_info);
1066
1067         tree1->session->transport->oplock.handler = torture_oplock_handler;
1068         tree1->session->transport->oplock.private_data = tree1;
1069
1070         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1071         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1072         status = smb2_create(tree1, tctx, &(io.smb2));
1073         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1074         h1 = io.smb2.out.file.handle;
1075         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1076
1077         ZERO_STRUCT(r);
1078         r.in.file.handle = h1;
1079         r.in.offset      = 0;
1080
1081         status = smb2_read(tree1, tree1, &r);
1082         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1083         torture_wait_for_oplock_break(tctx);
1084         CHECK_VAL(break_info.count, 0);
1085         CHECK_VAL(break_info.failures, 0);
1086
1087         smb2_util_close(tree1, h1);
1088         smb2_util_close(tree1, h);
1089
1090         smb2_deltree(tree1, BASEDIR);
1091         return ret;
1092 }
1093
1094 static bool test_smb2_oplock_batch5(struct torture_context *tctx,
1095                                     struct smb2_tree *tree1,
1096                                     struct smb2_tree *tree2)
1097 {
1098         const char *fname = BASEDIR "\\test_batch5.dat";
1099         NTSTATUS status;
1100         bool ret = true;
1101         union smb_open io;
1102         struct smb2_handle h, h1;
1103
1104         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1105         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1106
1107         /* cleanup */
1108         smb2_util_unlink(tree1, fname);
1109
1110         tree1->session->transport->oplock.handler = torture_oplock_handler;
1111         tree1->session->transport->oplock.private_data = tree1;
1112
1113         /*
1114           base ntcreatex parms
1115         */
1116         ZERO_STRUCT(io.smb2);
1117         io.generic.level = RAW_OPEN_SMB2;
1118         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1119         io.smb2.in.alloc_size = 0;
1120         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1121         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1122         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1123         io.smb2.in.create_options = 0;
1124         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1125         io.smb2.in.security_flags = 0;
1126         io.smb2.in.fname = fname;
1127
1128         torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1129         ZERO_STRUCT(break_info);
1130
1131         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1132         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1133         status = smb2_create(tree1, tctx, &(io.smb2));
1134         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1135         h1 = io.smb2.out.file.handle;
1136         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1137
1138         ZERO_STRUCT(break_info);
1139
1140         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1141         status = smb2_create(tree2, tctx, &(io.smb2));
1142         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
1143                                       "Incorrect status");
1144
1145         torture_wait_for_oplock_break(tctx);
1146         CHECK_VAL(break_info.count, 1);
1147         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1148         CHECK_VAL(break_info.level, 1);
1149         CHECK_VAL(break_info.failures, 0);
1150
1151         smb2_util_close(tree1, h1);
1152         smb2_util_close(tree1, h);
1153
1154         smb2_deltree(tree1, BASEDIR);
1155         return ret;
1156 }
1157
1158 static bool test_smb2_oplock_batch6(struct torture_context *tctx,
1159                                     struct smb2_tree *tree1,
1160                                     struct smb2_tree *tree2)
1161 {
1162         const char *fname = BASEDIR "\\test_batch6.dat";
1163         NTSTATUS status;
1164         bool ret = true;
1165         union smb_open io;
1166         struct smb2_handle h, h1, h2;
1167         char c = 0;
1168
1169         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1170         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1171
1172         /* cleanup */
1173         smb2_util_unlink(tree1, fname);
1174
1175         tree1->session->transport->oplock.handler = torture_oplock_handler;
1176         tree1->session->transport->oplock.private_data = tree1;
1177
1178         /*
1179           base ntcreatex parms
1180         */
1181         ZERO_STRUCT(io.smb2);
1182         io.generic.level = RAW_OPEN_SMB2;
1183         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1184         io.smb2.in.alloc_size = 0;
1185         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1186         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1187         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1188         io.smb2.in.create_options = 0;
1189         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1190         io.smb2.in.security_flags = 0;
1191         io.smb2.in.fname = fname;
1192
1193         torture_comment(tctx, "BATCH6: a 2nd open should give a break to "
1194                         "level II if the first open allowed shared read\n");
1195         ZERO_STRUCT(break_info);
1196         tree2->session->transport->oplock.handler = torture_oplock_handler;
1197         tree2->session->transport->oplock.private_data = tree2;
1198
1199         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
1200                                 SEC_RIGHTS_FILE_WRITE;
1201         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1202                                 NTCREATEX_SHARE_ACCESS_WRITE;
1203         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1204         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1205         status = smb2_create(tree1, tctx, &(io.smb2));
1206         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1207         h1 = io.smb2.out.file.handle;
1208         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1209
1210         ZERO_STRUCT(break_info);
1211
1212         status = smb2_create(tree2, tctx, &(io.smb2));
1213         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1214         h2 = io.smb2.out.file.handle;
1215         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1216
1217         torture_wait_for_oplock_break(tctx);
1218         CHECK_VAL(break_info.count, 1);
1219         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1220         CHECK_VAL(break_info.level, 1);
1221         CHECK_VAL(break_info.failures, 0);
1222         ZERO_STRUCT(break_info);
1223
1224         torture_comment(tctx, "write should trigger a break to none on both\n");
1225         tree1->session->transport->oplock.handler =
1226             torture_oplock_handler_level2_to_none;
1227         tree2->session->transport->oplock.handler =
1228             torture_oplock_handler_level2_to_none;
1229         smb2_util_write(tree1, h1, &c, 0, 1);
1230
1231         /* We expect two breaks */
1232         torture_wait_for_oplock_break(tctx);
1233         torture_wait_for_oplock_break(tctx);
1234
1235         CHECK_VAL(break_info.count, 2);
1236         CHECK_VAL(break_info.level, 0);
1237         CHECK_VAL(break_info.failures, 0);
1238
1239         smb2_util_close(tree1, h1);
1240         smb2_util_close(tree2, h2);
1241         smb2_util_close(tree1, h);
1242
1243         smb2_deltree(tree1, BASEDIR);
1244         return ret;
1245 }
1246
1247 static bool test_smb2_oplock_batch7(struct torture_context *tctx,
1248                                     struct smb2_tree *tree1,
1249                                     struct smb2_tree *tree2)
1250 {
1251         const char *fname = BASEDIR "\\test_batch7.dat";
1252         NTSTATUS status;
1253         bool ret = true;
1254         union smb_open io;
1255         struct smb2_handle h, h1, h2;
1256
1257         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1258         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1259
1260         /* cleanup */
1261         smb2_util_unlink(tree1, fname);
1262
1263         tree1->session->transport->oplock.handler = torture_oplock_handler;
1264         tree1->session->transport->oplock.private_data = tree1;
1265
1266         /*
1267           base ntcreatex parms
1268         */
1269         ZERO_STRUCT(io.smb2);
1270         io.generic.level = RAW_OPEN_SMB2;
1271         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1272         io.smb2.in.alloc_size = 0;
1273         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1274         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1275         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1276         io.smb2.in.create_options = 0;
1277         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1278         io.smb2.in.security_flags = 0;
1279         io.smb2.in.fname = fname;
1280
1281         torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when "
1282                         "we close instead of ack\n");
1283         ZERO_STRUCT(break_info);
1284         tree1->session->transport->oplock.handler =
1285                         torture_oplock_handler_close;
1286         tree1->session->transport->oplock.private_data = tree1;
1287
1288         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1289         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1290         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1291         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1292         status = smb2_create(tree1, tctx, &(io.smb2));
1293         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1294         h2 = io.smb2.out.file.handle;
1295         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1296
1297         ZERO_STRUCT(break_info);
1298
1299         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1300         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1301         status = smb2_create(tree2, tctx, &(io.smb2));
1302         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1303         h1 = io.smb2.out.file.handle;
1304         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1305
1306         torture_wait_for_oplock_break(tctx);
1307         CHECK_VAL(break_info.count, 1);
1308         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1309         CHECK_VAL(break_info.level, 1);
1310         CHECK_VAL(break_info.failures, 0);
1311
1312         smb2_util_close(tree2, h1);
1313         smb2_util_close(tree2, h);
1314
1315         smb2_deltree(tree1, BASEDIR);
1316         return ret;
1317 }
1318
1319 static bool test_smb2_oplock_batch8(struct torture_context *tctx,
1320                                     struct smb2_tree *tree1,
1321                                     struct smb2_tree *tree2)
1322 {
1323         const char *fname = BASEDIR "\\test_batch8.dat";
1324         NTSTATUS status;
1325         bool ret = true;
1326         union smb_open io;
1327         struct smb2_handle h, h1, h2;
1328
1329         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1330         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1331
1332         /* cleanup */
1333         smb2_util_unlink(tree1, fname);
1334
1335         tree1->session->transport->oplock.handler = torture_oplock_handler;
1336         tree1->session->transport->oplock.private_data = tree1;
1337
1338         /*
1339           base ntcreatex parms
1340         */
1341         ZERO_STRUCT(io.smb2);
1342         io.generic.level = RAW_OPEN_SMB2;
1343         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1344         io.smb2.in.alloc_size = 0;
1345         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1346         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1347         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1348         io.smb2.in.create_options = 0;
1349         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1350         io.smb2.in.security_flags = 0;
1351         io.smb2.in.fname = fname;
1352
1353         torture_comment(tctx, "BATCH8: open with batch oplock\n");
1354         ZERO_STRUCT(break_info);
1355
1356         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1357         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1358         status = smb2_create(tree1, tctx, &(io.smb2));
1359         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1360         h1 = io.smb2.out.file.handle;
1361         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1362
1363         ZERO_STRUCT(break_info);
1364         torture_comment(tctx, "second open with attributes only shouldn't "
1365                         "cause oplock break\n");
1366
1367         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1368         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1369                                 SEC_FILE_WRITE_ATTRIBUTE |
1370                                 SEC_STD_SYNCHRONIZE;
1371         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1372         status = smb2_create(tree2, tctx, &(io.smb2));
1373         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1374         h2 = io.smb2.out.file.handle;
1375         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1376         torture_wait_for_oplock_break(tctx);
1377         CHECK_VAL(break_info.count, 0);
1378         CHECK_VAL(break_info.failures, 0);
1379
1380         smb2_util_close(tree1, h1);
1381         smb2_util_close(tree2, h2);
1382         smb2_util_close(tree1, h);
1383
1384         smb2_deltree(tree1, BASEDIR);
1385         return ret;
1386 }
1387
1388 static bool test_smb2_oplock_batch9(struct torture_context *tctx,
1389                                      struct smb2_tree *tree1,
1390                                      struct smb2_tree *tree2)
1391 {
1392         const char *fname = BASEDIR "\\test_batch9.dat";
1393         NTSTATUS status;
1394         bool ret = true;
1395         union smb_open io;
1396         struct smb2_handle h, h1, h2;
1397         char c = 0;
1398
1399         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1400         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1401
1402         /* cleanup */
1403         smb2_util_unlink(tree1, fname);
1404
1405         tree1->session->transport->oplock.handler = torture_oplock_handler;
1406         tree1->session->transport->oplock.private_data = tree1;
1407
1408         /*
1409           base ntcreatex parms
1410         */
1411         ZERO_STRUCT(io.smb2);
1412         io.generic.level = RAW_OPEN_SMB2;
1413         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1414         io.smb2.in.alloc_size = 0;
1415         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1416         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1417         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1418         io.smb2.in.create_options = 0;
1419         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1420         io.smb2.in.security_flags = 0;
1421         io.smb2.in.fname = fname;
1422
1423         torture_comment(tctx, "BATCH9: open with attributes only can create "
1424                         "file\n");
1425
1426         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1427         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1428         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1429                                 SEC_FILE_WRITE_ATTRIBUTE |
1430                                 SEC_STD_SYNCHRONIZE;
1431         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1432         status = smb2_create(tree1, tctx, &(io.smb2));
1433         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1434         h1 = io.smb2.out.file.handle;
1435         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1436
1437         torture_comment(tctx, "Subsequent normal open should break oplock on "
1438                         "attribute only open to level II\n");
1439
1440         ZERO_STRUCT(break_info);
1441
1442         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1443         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1444         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1445         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1446         status = smb2_create(tree2, tctx, &(io.smb2));
1447         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1448         h2 = io.smb2.out.file.handle;
1449         torture_wait_for_oplock_break(tctx);
1450         CHECK_VAL(break_info.count, 1);
1451         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
1452         CHECK_VAL(break_info.failures, 0);
1453         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
1454         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1455         smb2_util_close(tree2, h2);
1456
1457         torture_comment(tctx, "third oplocked open should grant level2 without "
1458                         "break\n");
1459         ZERO_STRUCT(break_info);
1460
1461         tree2->session->transport->oplock.handler = torture_oplock_handler;
1462         tree2->session->transport->oplock.private_data = tree2;
1463
1464         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1465         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1466         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1467         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1468         status = smb2_create(tree2, tctx, &(io.smb2));
1469         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1470         h2 = io.smb2.out.file.handle;
1471         torture_wait_for_oplock_break(tctx);
1472         CHECK_VAL(break_info.count, 0);
1473         CHECK_VAL(break_info.failures, 0);
1474         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1475
1476         ZERO_STRUCT(break_info);
1477
1478         torture_comment(tctx, "write should trigger a break to none on both\n");
1479         tree1->session->transport->oplock.handler =
1480             torture_oplock_handler_level2_to_none;
1481         tree2->session->transport->oplock.handler =
1482             torture_oplock_handler_level2_to_none;
1483         smb2_util_write(tree2, h2, &c, 0, 1);
1484
1485         /* We expect two breaks */
1486         torture_wait_for_oplock_break(tctx);
1487         torture_wait_for_oplock_break(tctx);
1488
1489         CHECK_VAL(break_info.count, 2);
1490         CHECK_VAL(break_info.level, 0);
1491         CHECK_VAL(break_info.failures, 0);
1492
1493         smb2_util_close(tree1, h1);
1494         smb2_util_close(tree2, h2);
1495         smb2_util_close(tree1, h);
1496
1497         smb2_deltree(tree1, BASEDIR);
1498         return ret;
1499 }
1500
1501 static bool test_smb2_oplock_batch10(struct torture_context *tctx,
1502                                      struct smb2_tree *tree1,
1503                                      struct smb2_tree *tree2)
1504 {
1505         const char *fname = BASEDIR "\\test_batch10.dat";
1506         NTSTATUS status;
1507         bool ret = true;
1508         union smb_open io;
1509         struct smb2_handle h, h1, h2;
1510
1511         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1512         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1513
1514         /* cleanup */
1515         smb2_util_unlink(tree1, fname);
1516
1517         tree1->session->transport->oplock.handler = torture_oplock_handler;
1518         tree1->session->transport->oplock.private_data = tree1;
1519
1520         /*
1521           base ntcreatex parms
1522         */
1523         ZERO_STRUCT(io.smb2);
1524         io.generic.level = RAW_OPEN_SMB2;
1525         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1526         io.smb2.in.alloc_size = 0;
1527         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1528         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1529         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1530         io.smb2.in.create_options = 0;
1531         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1532         io.smb2.in.security_flags = 0;
1533         io.smb2.in.fname = fname;
1534
1535         torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock "
1536                         "open should grant level2\n");
1537         ZERO_STRUCT(break_info);
1538         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1539         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1540         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1541                 NTCREATEX_SHARE_ACCESS_WRITE|
1542                 NTCREATEX_SHARE_ACCESS_DELETE;
1543         status = smb2_create(tree1, tctx, &(io.smb2));
1544         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1545         h1 = io.smb2.out.file.handle;
1546         torture_wait_for_oplock_break(tctx);
1547         CHECK_VAL(break_info.count, 0);
1548         CHECK_VAL(break_info.failures, 0);
1549         CHECK_VAL(io.smb2.out.oplock_level, 0);
1550
1551         tree2->session->transport->oplock.handler =
1552             torture_oplock_handler_level2_to_none;
1553         tree2->session->transport->oplock.private_data = tree2;
1554
1555         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1556         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1557         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1558         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1559                 NTCREATEX_SHARE_ACCESS_WRITE|
1560                 NTCREATEX_SHARE_ACCESS_DELETE;
1561         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1562         status = smb2_create(tree2, tctx, &(io.smb2));
1563         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1564         h2 = io.smb2.out.file.handle;
1565         torture_wait_for_oplock_break(tctx);
1566         CHECK_VAL(break_info.count, 0);
1567         CHECK_VAL(break_info.failures, 0);
1568         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1569
1570         torture_comment(tctx, "write should trigger a break to none\n");
1571         {
1572                 struct smb2_write wr;
1573                 DATA_BLOB data;
1574                 data = data_blob_talloc(tree1, NULL, UINT16_MAX);
1575                 data.data[0] = (const uint8_t)'x';
1576                 ZERO_STRUCT(wr);
1577                 wr.in.file.handle = h1;
1578                 wr.in.offset      = 0;
1579                 wr.in.data        = data;
1580                 status = smb2_write(tree1, &wr);
1581                 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1582         }
1583
1584         torture_wait_for_oplock_break(tctx);
1585
1586         CHECK_VAL(break_info.count, 1);
1587         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
1588         CHECK_VAL(break_info.level, 0);
1589         CHECK_VAL(break_info.failures, 0);
1590
1591         smb2_util_close(tree1, h1);
1592         smb2_util_close(tree2, h2);
1593         smb2_util_close(tree1, h);
1594
1595         smb2_deltree(tree1, BASEDIR);
1596         return ret;
1597 }
1598
1599 static bool test_smb2_oplock_batch11(struct torture_context *tctx,
1600                                      struct smb2_tree *tree1,
1601                                      struct smb2_tree *tree2)
1602 {
1603         const char *fname = BASEDIR "\\test_batch11.dat";
1604         NTSTATUS status;
1605         bool ret = true;
1606         union smb_open io;
1607         union smb_setfileinfo sfi;
1608         struct smb2_handle h, h1;
1609
1610         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1611         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1612
1613         /* cleanup */
1614         smb2_util_unlink(tree1, fname);
1615
1616         tree1->session->transport->oplock.handler =
1617             torture_oplock_handler_two_notifications;
1618         tree1->session->transport->oplock.private_data = tree1;
1619
1620         /*
1621           base ntcreatex parms
1622         */
1623         ZERO_STRUCT(io.smb2);
1624         io.generic.level = RAW_OPEN_SMB2;
1625         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1626         io.smb2.in.alloc_size = 0;
1627         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1628         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1629         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1630         io.smb2.in.create_options = 0;
1631         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1632         io.smb2.in.security_flags = 0;
1633         io.smb2.in.fname = fname;
1634
1635         /* Test if a set-eof on pathname breaks an exclusive oplock. */
1636         torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks "
1637                         "oplocks.\n");
1638
1639         ZERO_STRUCT(break_info);
1640
1641         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1642         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1643         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1644         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1645                                 NTCREATEX_SHARE_ACCESS_WRITE|
1646                                 NTCREATEX_SHARE_ACCESS_DELETE;
1647         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1648         status = smb2_create(tree1, tctx, &(io.smb2));
1649         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1650         h1 = io.smb2.out.file.handle;
1651         torture_wait_for_oplock_break(tctx);
1652         CHECK_VAL(break_info.count, 0);
1653         CHECK_VAL(break_info.failures, 0);
1654         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1655
1656         ZERO_STRUCT(sfi);
1657         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1658         sfi.generic.in.file.path = fname;
1659         sfi.end_of_file_info.in.size = 100;
1660
1661         status = smb2_composite_setpathinfo(tree2, &sfi);
1662         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1663
1664         /* We expect two breaks */
1665         torture_wait_for_oplock_break(tctx);
1666         torture_wait_for_oplock_break(tctx);
1667
1668         CHECK_VAL(break_info.count, 2);
1669         CHECK_VAL(break_info.failures, 0);
1670         CHECK_VAL(break_info.level, 0);
1671
1672         smb2_util_close(tree1, h1);
1673         smb2_util_close(tree1, h);
1674
1675         smb2_deltree(tree1, BASEDIR);
1676         return ret;
1677 }
1678
1679 static bool test_smb2_oplock_batch12(struct torture_context *tctx,
1680                                      struct smb2_tree *tree1,
1681                                      struct smb2_tree *tree2)
1682 {
1683         const char *fname = BASEDIR "\\test_batch12.dat";
1684         NTSTATUS status;
1685         bool ret = true;
1686         union smb_open io;
1687         union smb_setfileinfo sfi;
1688         struct smb2_handle h, h1;
1689
1690         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1691         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1692
1693         /* cleanup */
1694         smb2_util_unlink(tree1, fname);
1695
1696         tree1->session->transport->oplock.handler =
1697             torture_oplock_handler_two_notifications;
1698         tree1->session->transport->oplock.private_data = tree1;
1699
1700         /*
1701           base ntcreatex parms
1702         */
1703         ZERO_STRUCT(io.smb2);
1704         io.generic.level = RAW_OPEN_SMB2;
1705         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1706         io.smb2.in.alloc_size = 0;
1707         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1708         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1709         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1710         io.smb2.in.create_options = 0;
1711         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1712         io.smb2.in.security_flags = 0;
1713         io.smb2.in.fname = fname;
1714
1715         /* Test if a set-allocation size on pathname breaks an exclusive
1716          * oplock. */
1717         torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size "
1718                         "breaks oplocks.\n");
1719
1720         ZERO_STRUCT(break_info);
1721
1722         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1723         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1724         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1725         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1726                                 NTCREATEX_SHARE_ACCESS_WRITE|
1727                                 NTCREATEX_SHARE_ACCESS_DELETE;
1728         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1729         status = smb2_create(tree1, tctx, &(io.smb2));
1730         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1731         h1 = io.smb2.out.file.handle;
1732         torture_wait_for_oplock_break(tctx);
1733         CHECK_VAL(break_info.count, 0);
1734         CHECK_VAL(break_info.failures, 0);
1735         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1736
1737         ZERO_STRUCT(sfi);
1738         sfi.generic.level = RAW_SFILEINFO_ALLOCATION_INFORMATION;
1739         sfi.generic.in.file.path = fname;
1740         sfi.allocation_info.in.alloc_size = 65536 * 8;
1741
1742         status = smb2_composite_setpathinfo(tree2, &sfi);
1743         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1744
1745         /* We expect two breaks */
1746         torture_wait_for_oplock_break(tctx);
1747         torture_wait_for_oplock_break(tctx);
1748
1749         CHECK_VAL(break_info.count, 2);
1750         CHECK_VAL(break_info.failures, 0);
1751         CHECK_VAL(break_info.level, 0);
1752
1753         smb2_util_close(tree1, h1);
1754         smb2_util_close(tree1, h);
1755
1756         smb2_deltree(tree1, BASEDIR);
1757         return ret;
1758 }
1759
1760 static bool test_smb2_oplock_batch13(struct torture_context *tctx,
1761                                      struct smb2_tree *tree1,
1762                                      struct smb2_tree *tree2)
1763 {
1764         const char *fname = BASEDIR "\\test_batch13.dat";
1765         NTSTATUS status;
1766         bool ret = true;
1767         union smb_open io;
1768         struct smb2_handle h, h1, h2;
1769
1770         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1771         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1772
1773         /* cleanup */
1774         smb2_util_unlink(tree1, fname);
1775
1776         tree1->session->transport->oplock.handler = torture_oplock_handler;
1777         tree1->session->transport->oplock.private_data = tree1;
1778
1779         tree2->session->transport->oplock.handler = torture_oplock_handler;
1780         tree2->session->transport->oplock.private_data = tree2;
1781
1782         /*
1783           base ntcreatex parms
1784         */
1785         ZERO_STRUCT(io.smb2);
1786         io.generic.level = RAW_OPEN_SMB2;
1787         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1788         io.smb2.in.alloc_size = 0;
1789         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1790         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1791         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1792         io.smb2.in.create_options = 0;
1793         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1794         io.smb2.in.security_flags = 0;
1795         io.smb2.in.fname = fname;
1796
1797         torture_comment(tctx, "BATCH13: open with batch oplock\n");
1798         ZERO_STRUCT(break_info);
1799
1800         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1801         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1802         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1803                 NTCREATEX_SHARE_ACCESS_WRITE|
1804                 NTCREATEX_SHARE_ACCESS_DELETE;
1805         status = smb2_create(tree1, tctx, &(io.smb2));
1806         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1807         h1 = io.smb2.out.file.handle;
1808         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1809
1810         ZERO_STRUCT(break_info);
1811
1812         torture_comment(tctx, "second open with attributes only and "
1813                         "NTCREATEX_DISP_OVERWRITE dispostion causes "
1814                         "oplock break\n");
1815
1816         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1817         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1818         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1819                                 SEC_FILE_WRITE_ATTRIBUTE |
1820                                 SEC_STD_SYNCHRONIZE;
1821         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1822                                 NTCREATEX_SHARE_ACCESS_WRITE|
1823                                 NTCREATEX_SHARE_ACCESS_DELETE;
1824         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
1825         status = smb2_create(tree2, tctx, &(io.smb2));
1826         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1827         h2 = io.smb2.out.file.handle;
1828         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1829         torture_wait_for_oplock_break(tctx);
1830         CHECK_VAL(break_info.count, 1);
1831         CHECK_VAL(break_info.failures, 0);
1832
1833         smb2_util_close(tree1, h1);
1834         smb2_util_close(tree2, h2);
1835         smb2_util_close(tree1, h);
1836
1837         smb2_deltree(tree1, BASEDIR);
1838
1839         return ret;
1840 }
1841
1842 static bool test_smb2_oplock_batch14(struct torture_context *tctx,
1843                                      struct smb2_tree *tree1,
1844                                      struct smb2_tree *tree2)
1845 {
1846         const char *fname = BASEDIR "\\test_batch14.dat";
1847         NTSTATUS status;
1848         bool ret = true;
1849         union smb_open io;
1850         struct smb2_handle h, h1, h2;
1851
1852         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1853         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1854
1855         /* cleanup */
1856         smb2_util_unlink(tree1, fname);
1857
1858         tree1->session->transport->oplock.handler = torture_oplock_handler;
1859         tree1->session->transport->oplock.private_data = tree1;
1860
1861         /*
1862           base ntcreatex parms
1863         */
1864         ZERO_STRUCT(io.smb2);
1865         io.generic.level = RAW_OPEN_SMB2;
1866         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1867         io.smb2.in.alloc_size = 0;
1868         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1869         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1870         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1871         io.smb2.in.create_options = 0;
1872         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1873         io.smb2.in.security_flags = 0;
1874         io.smb2.in.fname = fname;
1875
1876         torture_comment(tctx, "BATCH14: open with batch oplock\n");
1877         ZERO_STRUCT(break_info);
1878
1879         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1880         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1881         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1882                 NTCREATEX_SHARE_ACCESS_WRITE|
1883                 NTCREATEX_SHARE_ACCESS_DELETE;
1884         status = smb2_create(tree1, tctx, &(io.smb2));
1885         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1886         h1 = io.smb2.out.file.handle;
1887         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1888
1889         ZERO_STRUCT(break_info);
1890
1891         torture_comment(tctx, "second open with attributes only and "
1892                         "NTCREATEX_DISP_SUPERSEDE dispostion causes "
1893                         "oplock break\n");
1894
1895         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1896         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1897         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1898                                 SEC_FILE_WRITE_ATTRIBUTE |
1899                                 SEC_STD_SYNCHRONIZE;
1900         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1901                                 NTCREATEX_SHARE_ACCESS_WRITE|
1902                                 NTCREATEX_SHARE_ACCESS_DELETE;
1903         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
1904         status = smb2_create(tree2, tctx, &(io.smb2));
1905         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
1906         h2 = io.smb2.out.file.handle;
1907         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
1908
1909         torture_wait_for_oplock_break(tctx);
1910         CHECK_VAL(break_info.count, 1);
1911         CHECK_VAL(break_info.failures, 0);
1912
1913         smb2_util_close(tree1, h1);
1914         smb2_util_close(tree2, h2);
1915         smb2_util_close(tree1, h);
1916
1917         smb2_deltree(tree1, BASEDIR);
1918         return ret;
1919 }
1920
1921 static bool test_smb2_oplock_batch15(struct torture_context *tctx,
1922                                      struct smb2_tree *tree1,
1923                                      struct smb2_tree *tree2)
1924 {
1925         const char *fname = BASEDIR "\\test_batch15.dat";
1926         NTSTATUS status;
1927         bool ret = true;
1928         union smb_open io;
1929         union smb_fileinfo qfi;
1930         struct smb2_handle h, h1;
1931
1932         status = torture_smb2_testdir(tree1, BASEDIR, &h);
1933         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
1934
1935         /* cleanup */
1936         smb2_util_unlink(tree1, fname);
1937
1938         tree1->session->transport->oplock.handler = torture_oplock_handler;
1939         tree1->session->transport->oplock.private_data = tree1;
1940
1941         /*
1942           base ntcreatex parms
1943         */
1944         ZERO_STRUCT(io.smb2);
1945         io.generic.level = RAW_OPEN_SMB2;
1946         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1947         io.smb2.in.alloc_size = 0;
1948         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1949         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1950         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1951         io.smb2.in.create_options = 0;
1952         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1953         io.smb2.in.security_flags = 0;
1954         io.smb2.in.fname = fname;
1955
1956         /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
1957         torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks "
1958                         "a batch oplock (should not).\n");
1959
1960         ZERO_STRUCT(break_info);
1961
1962         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1963         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
1964         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1965         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1966                                 NTCREATEX_SHARE_ACCESS_WRITE|
1967                                 NTCREATEX_SHARE_ACCESS_DELETE;
1968         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1969         status = smb2_create(tree1, tctx, &(io.smb2));
1970         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
1971         h1 = io.smb2.out.file.handle;
1972
1973         torture_wait_for_oplock_break(tctx);
1974         CHECK_VAL(break_info.count, 0);
1975         CHECK_VAL(break_info.failures, 0);
1976         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1977
1978         ZERO_STRUCT(qfi);
1979         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
1980         qfi.generic.in.file.handle = h1;
1981         status = smb2_getinfo_file(tree2, tctx, &qfi);
1982
1983         torture_wait_for_oplock_break(tctx);
1984         CHECK_VAL(break_info.count, 0);
1985
1986         smb2_util_close(tree1, h1);
1987         smb2_util_close(tree1, h);
1988
1989         smb2_deltree(tree1, BASEDIR);
1990         return ret;
1991 }
1992
1993 static bool test_smb2_oplock_batch16(struct torture_context *tctx,
1994                                      struct smb2_tree *tree1,
1995                                      struct smb2_tree *tree2)
1996 {
1997         const char *fname = BASEDIR "\\test_batch16.dat";
1998         NTSTATUS status;
1999         bool ret = true;
2000         union smb_open io;
2001         struct smb2_handle h, h1, h2;
2002
2003         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2004         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2005
2006         /* cleanup */
2007         smb2_util_unlink(tree1, fname);
2008
2009         tree1->session->transport->oplock.handler = torture_oplock_handler;
2010         tree1->session->transport->oplock.private_data = tree1;
2011
2012         tree2->session->transport->oplock.handler = torture_oplock_handler;
2013         tree2->session->transport->oplock.private_data = tree2;
2014
2015         /*
2016           base ntcreatex parms
2017         */
2018         ZERO_STRUCT(io.smb2);
2019         io.generic.level = RAW_OPEN_SMB2;
2020         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2021         io.smb2.in.alloc_size = 0;
2022         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2023         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2024         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2025         io.smb2.in.create_options = 0;
2026         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2027         io.smb2.in.security_flags = 0;
2028         io.smb2.in.fname = fname;
2029
2030         torture_comment(tctx, "BATCH16: open with batch oplock\n");
2031         ZERO_STRUCT(break_info);
2032
2033         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2034         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2035         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2036                 NTCREATEX_SHARE_ACCESS_WRITE|
2037                 NTCREATEX_SHARE_ACCESS_DELETE;
2038         status = smb2_create(tree1, tctx, &(io.smb2));
2039         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2040         h1 = io.smb2.out.file.handle;
2041         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2042
2043         ZERO_STRUCT(break_info);
2044
2045         torture_comment(tctx, "second open with attributes only and "
2046                         "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
2047                         "oplock break\n");
2048
2049         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2050         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2051         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
2052                                 SEC_FILE_WRITE_ATTRIBUTE |
2053                                 SEC_STD_SYNCHRONIZE;
2054         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2055                                 NTCREATEX_SHARE_ACCESS_WRITE|
2056                                 NTCREATEX_SHARE_ACCESS_DELETE;
2057         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2058         status = smb2_create(tree2, tctx, &(io.smb2));
2059         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2060         h2 = io.smb2.out.file.handle;
2061         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2062
2063         torture_wait_for_oplock_break(tctx);
2064         CHECK_VAL(break_info.count, 1);
2065         CHECK_VAL(break_info.failures, 0);
2066
2067         smb2_util_close(tree1, h1);
2068         smb2_util_close(tree2, h2);
2069         smb2_util_close(tree1, h);
2070
2071         smb2_deltree(tree1, BASEDIR);
2072         return ret;
2073 }
2074
2075 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH17 test.  Since
2076  * SMB2 doesn't have a RENAME command this test isn't applicable.  However,
2077  * it's much less confusing, when comparing test, to keep the SMB1 and SMB2
2078  * test numbers in sync. */
2079 #if 0
2080 static bool test_raw_oplock_batch17(struct torture_context *tctx,
2081                                     struct smb2_tree *tree1,
2082                                     struct smb2_tree *tree2)
2083 {
2084         return true;
2085 }
2086 #endif
2087
2088 /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH18 test.  Since
2089  * SMB2 doesn't have an NTRENAME command this test isn't applicable.  However,
2090  * it's much less confusing, when comparing tests, to keep the SMB1 and SMB2
2091  * test numbers in sync. */
2092 #if 0
2093 static bool test_raw_oplock_batch18(struct torture_context *tctx,
2094                                     struct smb2_tree *tree1,
2095                                     struct smb2_tree *tree2)
2096 {
2097         return true;
2098 }
2099 #endif
2100
2101 static bool test_smb2_oplock_batch19(struct torture_context *tctx,
2102                                      struct smb2_tree *tree1)
2103 {
2104         const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2105         const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2106         NTSTATUS status;
2107         bool ret = true;
2108         union smb_open io;
2109         union smb_fileinfo qfi;
2110         union smb_setfileinfo sfi;
2111         struct smb2_handle h, h1;
2112
2113         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2114         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2115
2116         /* cleanup */
2117         smb2_util_unlink(tree1, fname1);
2118         smb2_util_unlink(tree1, fname2);
2119
2120         tree1->session->transport->oplock.handler = torture_oplock_handler;
2121         tree1->session->transport->oplock.private_data = tree1;
2122
2123         /*
2124           base ntcreatex parms
2125         */
2126         ZERO_STRUCT(io.smb2);
2127         io.generic.level = RAW_OPEN_SMB2;
2128         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2129         io.smb2.in.alloc_size = 0;
2130         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2131         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2132         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2133         io.smb2.in.create_options = 0;
2134         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2135         io.smb2.in.security_flags = 0;
2136         io.smb2.in.fname = fname1;
2137
2138         torture_comment(tctx, "BATCH19: open a file with an batch oplock "
2139                         "(share mode: none)\n");
2140         ZERO_STRUCT(break_info);
2141         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2142         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2143         status = smb2_create(tree1, tctx, &(io.smb2));
2144         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2145         h1 = io.smb2.out.file.handle;
2146         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2147
2148         torture_comment(tctx, "setfileinfo rename info should not trigger "
2149                         "a break but should cause a sharing violation\n");
2150         ZERO_STRUCT(sfi);
2151         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2152         sfi.generic.in.file.path = fname1;
2153         sfi.rename_information.in.file.handle   = h1;
2154         sfi.rename_information.in.overwrite     = 0;
2155         sfi.rename_information.in.root_fid      = 0;
2156         sfi.rename_information.in.new_name      = fname2;
2157
2158         status = smb2_setinfo_file(tree1, &sfi);
2159
2160         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2161                                       "Incorrect status");
2162
2163         torture_wait_for_oplock_break(tctx);
2164         CHECK_VAL(break_info.count, 0);
2165
2166         ZERO_STRUCT(qfi);
2167         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2168         qfi.generic.in.file.handle = h1;
2169
2170         status = smb2_getinfo_file(tree1, tctx, &qfi);
2171         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2172         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2173
2174         smb2_util_close(tree1, h1);
2175         smb2_util_close(tree1, h);
2176
2177         smb2_deltree(tree1, fname1);
2178         smb2_deltree(tree1, fname2);
2179         return ret;
2180 }
2181
2182 static bool test_smb2_oplock_batch20(struct torture_context *tctx,
2183                                      struct smb2_tree *tree1,
2184                                      struct smb2_tree *tree2)
2185 {
2186         const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2187         const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2188         NTSTATUS status;
2189         bool ret = true;
2190         union smb_open io;
2191         union smb_fileinfo qfi;
2192         union smb_setfileinfo sfi;
2193         struct smb2_handle h, h1, h2;
2194
2195         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2196         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2197
2198         /* cleanup */
2199         smb2_util_unlink(tree1, fname1);
2200         smb2_util_unlink(tree1, fname2);
2201
2202         tree1->session->transport->oplock.handler = torture_oplock_handler;
2203         tree1->session->transport->oplock.private_data = tree1;
2204
2205         /*
2206           base ntcreatex parms
2207         */
2208         ZERO_STRUCT(io.smb2);
2209         io.generic.level = RAW_OPEN_SMB2;
2210         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2211         io.smb2.in.alloc_size = 0;
2212         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2213         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2214         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2215         io.smb2.in.create_options = 0;
2216         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2217         io.smb2.in.security_flags = 0;
2218         io.smb2.in.fname = fname1;
2219
2220         torture_comment(tctx, "BATCH20: open a file with an batch oplock "
2221                         "(share mode: all)\n");
2222         ZERO_STRUCT(break_info);
2223         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2224         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2225         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2226                                 NTCREATEX_SHARE_ACCESS_WRITE|
2227                                 NTCREATEX_SHARE_ACCESS_DELETE;
2228         status = smb2_create(tree1, tctx, &(io.smb2));
2229         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2230         h1 = io.smb2.out.file.handle;
2231         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2232
2233         torture_comment(tctx, "setfileinfo rename info should not trigger "
2234                         "a break but should cause a sharing violation\n");
2235         ZERO_STRUCT(sfi);
2236         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2237         sfi.rename_information.in.file.handle   = h1;
2238         sfi.rename_information.in.overwrite     = 0;
2239         sfi.rename_information.in.new_name      = fname2;
2240
2241         status = smb2_setinfo_file(tree1, &sfi);
2242         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2243                                       "Incorrect status");
2244
2245         torture_wait_for_oplock_break(tctx);
2246         CHECK_VAL(break_info.count, 0);
2247
2248         ZERO_STRUCT(qfi);
2249         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2250         qfi.generic.in.file.handle = h1;
2251
2252         status = smb2_getinfo_file(tree1, tctx, &qfi);
2253         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2254         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2255
2256         torture_comment(tctx, "open the file a second time requesting batch "
2257                         "(share mode: all)\n");
2258         ZERO_STRUCT(break_info);
2259         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2260         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2261         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2262                                 NTCREATEX_SHARE_ACCESS_WRITE|
2263                                 NTCREATEX_SHARE_ACCESS_DELETE;
2264         io.smb2.in.fname = fname1;
2265         status = smb2_create(tree2, tctx, &(io.smb2));
2266         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2267         h2 = io.smb2.out.file.handle;
2268         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2269
2270         torture_wait_for_oplock_break(tctx);
2271         CHECK_VAL(break_info.count, 1);
2272         CHECK_VAL(break_info.failures, 0);
2273         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2274
2275         torture_comment(tctx, "setfileinfo rename info should not trigger "
2276                         "a break but should cause a sharing violation\n");
2277         ZERO_STRUCT(break_info);
2278         ZERO_STRUCT(sfi);
2279         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2280         sfi.rename_information.in.file.handle   = h2;
2281         sfi.rename_information.in.overwrite     = 0;
2282         sfi.rename_information.in.new_name      = fname2;
2283
2284         status = smb2_setinfo_file(tree2, &sfi);
2285         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2286                                       "Incorrect status");
2287
2288         torture_wait_for_oplock_break(tctx);
2289         CHECK_VAL(break_info.count, 0);
2290
2291         ZERO_STRUCT(qfi);
2292         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2293         qfi.generic.in.file.handle = h1;
2294
2295         status = smb2_getinfo_file(tree1, tctx, &qfi);
2296         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2297         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2298
2299         ZERO_STRUCT(qfi);
2300         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
2301         qfi.generic.in.file.handle = h2;
2302
2303         status = smb2_getinfo_file(tree2, tctx, &qfi);
2304         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2305         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
2306
2307         smb2_util_close(tree1, h1);
2308         smb2_util_close(tree2, h2);
2309         smb2_util_close(tree1, h);
2310
2311         smb2_deltree(tree1, fname1);
2312         return ret;
2313 }
2314
2315 static bool test_smb2_oplock_batch21(struct torture_context *tctx,
2316                                      struct smb2_tree *tree1)
2317 {
2318         const char *fname = BASEDIR "\\test_batch21.dat";
2319         NTSTATUS status;
2320         bool ret = true;
2321         union smb_open io;
2322         struct smb2_handle h, h1;
2323         char c = 0;
2324
2325         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2326         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2327
2328         /* cleanup */
2329         smb2_util_unlink(tree1, fname);
2330
2331         tree1->session->transport->oplock.handler = torture_oplock_handler;
2332         tree1->session->transport->oplock.private_data = tree1;
2333
2334         /*
2335           base ntcreatex parms
2336         */
2337         ZERO_STRUCT(io.smb2);
2338         io.generic.level = RAW_OPEN_SMB2;
2339         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2340         io.smb2.in.alloc_size = 0;
2341         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2342         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2343         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2344         io.smb2.in.create_options = 0;
2345         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2346         io.smb2.in.security_flags = 0;
2347         io.smb2.in.fname = fname;
2348
2349         /*
2350           with a batch oplock we get a break
2351         */
2352         torture_comment(tctx, "BATCH21: open with batch oplock\n");
2353         ZERO_STRUCT(break_info);
2354         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2355         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2356         status = smb2_create(tree1, tctx, &(io.smb2));
2357         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2358         h1 = io.smb2.out.file.handle;
2359         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2360
2361         torture_comment(tctx, "writing should not generate a break\n");
2362         status = smb2_util_write(tree1, h1, &c, 0, 1);
2363         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2364
2365         torture_wait_for_oplock_break(tctx);
2366         CHECK_VAL(break_info.count, 0);
2367
2368         smb2_util_close(tree1, h1);
2369         smb2_util_close(tree1, h);
2370
2371         smb2_deltree(tree1, BASEDIR);
2372         return ret;
2373 }
2374
2375 static bool test_smb2_oplock_batch22(struct torture_context *tctx,
2376                                      struct smb2_tree *tree1)
2377 {
2378         const char *fname = BASEDIR "\\test_batch22.dat";
2379         NTSTATUS status;
2380         bool ret = true;
2381         union smb_open io;
2382         struct smb2_handle h, h1, h2;
2383         struct timeval tv;
2384         int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2385         int te;
2386
2387         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2388         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2389
2390         /* cleanup */
2391         smb2_util_unlink(tree1, fname);
2392
2393         tree1->session->transport->oplock.handler = torture_oplock_handler;
2394         tree1->session->transport->oplock.private_data = tree1;
2395         /*
2396           base ntcreatex parms
2397         */
2398         ZERO_STRUCT(io.smb2);
2399         io.generic.level = RAW_OPEN_SMB2;
2400         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2401         io.smb2.in.alloc_size = 0;
2402         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2403         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2404         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2405         io.smb2.in.create_options = 0;
2406         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2407         io.smb2.in.security_flags = 0;
2408         io.smb2.in.fname = fname;
2409
2410         /*
2411           with a batch oplock we get a break
2412         */
2413         torture_comment(tctx, "BATCH22: open with batch oplock\n");
2414         ZERO_STRUCT(break_info);
2415         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2416         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2417         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2418                 NTCREATEX_SHARE_ACCESS_WRITE|
2419                 NTCREATEX_SHARE_ACCESS_DELETE;
2420         status = smb2_create(tree1, tctx, &(io.smb2));
2421         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2422         h1 = io.smb2.out.file.handle;
2423         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2424
2425         torture_comment(tctx, "a 2nd open should succeed after the oplock "
2426                         "break timeout\n");
2427         tv = timeval_current();
2428         tree1->session->transport->oplock.handler =
2429                                 torture_oplock_handler_timeout;
2430         status = smb2_create(tree1, tctx, &(io.smb2));
2431         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2432         h2 = io.smb2.out.file.handle;
2433         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2434
2435         torture_wait_for_oplock_break(tctx);
2436         te = (int)timeval_elapsed(&tv);
2437         CHECK_RANGE(te, timeout - 1, timeout + 15);
2438         torture_comment(tctx, "waited %d seconds for oplock timeout\n", te);
2439
2440         CHECK_VAL(break_info.count, 1);
2441         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2442         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2443         CHECK_VAL(break_info.failures, 0);
2444
2445         smb2_util_close(tree1, h1);
2446         smb2_util_close(tree1, h2);
2447         smb2_util_close(tree1, h);
2448
2449         smb2_deltree(tree1, BASEDIR);
2450         return ret;
2451 }
2452
2453 static bool test_smb2_oplock_batch23(struct torture_context *tctx,
2454                                      struct smb2_tree *tree1,
2455                                      struct smb2_tree *tree2)
2456 {
2457         const char *fname = BASEDIR "\\test_batch23.dat";
2458         NTSTATUS status;
2459         bool ret = true;
2460         union smb_open io;
2461         struct smb2_handle h, h1, h2, h3;
2462         struct smb2_tree *tree3 = NULL;
2463
2464         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2465         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2466
2467         /* cleanup */
2468         smb2_util_unlink(tree1, fname);
2469
2470         ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2471         CHECK_VAL(ret, true);
2472
2473         tree1->session->transport->oplock.handler = torture_oplock_handler;
2474         tree1->session->transport->oplock.private_data = tree1;
2475
2476         tree2->session->transport->oplock.handler = torture_oplock_handler;
2477         tree2->session->transport->oplock.private_data = tree2;
2478
2479         tree3->session->transport->oplock.handler = torture_oplock_handler;
2480         tree3->session->transport->oplock.private_data = tree3;
2481
2482         /*
2483           base ntcreatex parms
2484         */
2485         ZERO_STRUCT(io.smb2);
2486         io.generic.level = RAW_OPEN_SMB2;
2487         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2488         io.smb2.in.alloc_size = 0;
2489         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2490         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2491         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2492         io.smb2.in.create_options = 0;
2493         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2494         io.smb2.in.security_flags = 0;
2495         io.smb2.in.fname = fname;
2496
2497         torture_comment(tctx, "BATCH23: an open and ask for a batch oplock\n");
2498         ZERO_STRUCT(break_info);
2499
2500         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2501                                 SEC_RIGHTS_FILE_WRITE;
2502         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2503                                 NTCREATEX_SHARE_ACCESS_WRITE;
2504         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2505         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2506         status = smb2_create(tree1, tctx, &(io.smb2));
2507         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2508         h1 = io.smb2.out.file.handle;
2509         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2510
2511         ZERO_STRUCT(break_info);
2512
2513         torture_comment(tctx, "a 2nd open without level2 oplock support "
2514                         "should generate a break to level2\n");
2515         status = smb2_create(tree3, tctx, &(io.smb2));
2516         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2517         h3 = io.smb2.out.file.handle;
2518
2519         torture_wait_for_oplock_break(tctx);
2520         CHECK_VAL(break_info.count, 1);
2521         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2522         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2523         CHECK_VAL(break_info.failures, 0);
2524
2525         ZERO_STRUCT(break_info);
2526
2527         torture_comment(tctx, "a 3rd open with level2 oplock support should "
2528                         "not generate a break\n");
2529         status = smb2_create(tree2, tctx, &(io.smb2));
2530         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2531         h2 = io.smb2.out.file.handle;
2532         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2533
2534         torture_wait_for_oplock_break(tctx);
2535         CHECK_VAL(break_info.count, 0);
2536
2537         smb2_util_close(tree1, h1);
2538         smb2_util_close(tree2, h2);
2539         smb2_util_close(tree3, h3);
2540         smb2_util_close(tree1, h);
2541
2542         smb2_deltree(tree1, BASEDIR);
2543         return ret;
2544 }
2545
2546 static bool test_smb2_oplock_batch24(struct torture_context *tctx,
2547                                      struct smb2_tree *tree1,
2548                                      struct smb2_tree *tree2)
2549 {
2550         const char *fname = BASEDIR "\\test_batch24.dat";
2551         NTSTATUS status;
2552         bool ret = true;
2553         union smb_open io;
2554         struct smb2_handle h, h1, h2;
2555         struct smb2_tree *tree3 = NULL;
2556
2557         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2558         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2559
2560         /* cleanup */
2561         smb2_util_unlink(tree1, fname);
2562
2563         ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
2564         CHECK_VAL(ret, true);
2565
2566         tree1->session->transport->oplock.handler = torture_oplock_handler;
2567         tree1->session->transport->oplock.private_data = tree1;
2568
2569         tree2->session->transport->oplock.handler = torture_oplock_handler;
2570         tree2->session->transport->oplock.private_data = tree2;
2571
2572         tree3->session->transport->oplock.handler = torture_oplock_handler;
2573         tree3->session->transport->oplock.private_data = tree3;
2574
2575         /*
2576           base ntcreatex parms
2577         */
2578         ZERO_STRUCT(io.smb2);
2579         io.generic.level = RAW_OPEN_SMB2;
2580         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2581         io.smb2.in.alloc_size = 0;
2582         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2583         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2584         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2585         io.smb2.in.create_options = 0;
2586         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2587         io.smb2.in.security_flags = 0;
2588         io.smb2.in.fname = fname;
2589
2590         torture_comment(tctx, "BATCH24: a open without level support and "
2591                         "ask for a batch oplock\n");
2592         ZERO_STRUCT(break_info);
2593
2594         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2595                                 SEC_RIGHTS_FILE_WRITE;
2596         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2597                                 NTCREATEX_SHARE_ACCESS_WRITE;
2598         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2599         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2600
2601         status = smb2_create(tree3, tctx, &(io.smb2));
2602         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2603         h2 = io.smb2.out.file.handle;
2604         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2605
2606         ZERO_STRUCT(break_info);
2607
2608         torture_comment(tctx, "a 2nd open with level2 oplock support should "
2609                         "generate a break\n");
2610         status = smb2_create(tree2, tctx, &(io.smb2));
2611         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2612         h1 = io.smb2.out.file.handle;
2613         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2614
2615         torture_wait_for_oplock_break(tctx);
2616         CHECK_VAL(break_info.count, 1);
2617         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
2618         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2619         CHECK_VAL(break_info.failures, 0);
2620
2621         smb2_util_close(tree3, h2);
2622         smb2_util_close(tree2, h1);
2623         smb2_util_close(tree1, h);
2624
2625         smb2_deltree(tree1, BASEDIR);
2626         return ret;
2627 }
2628
2629 static bool test_smb2_oplock_batch25(struct torture_context *tctx,
2630                                      struct smb2_tree *tree1)
2631 {
2632         const char *fname = BASEDIR "\\test_batch25.dat";
2633         NTSTATUS status;
2634         bool ret = true;
2635         union smb_open io;
2636         struct smb2_handle h, h1;
2637
2638         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2639         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2640
2641         /* cleanup */
2642         smb2_util_unlink(tree1, fname);
2643
2644         tree1->session->transport->oplock.handler = torture_oplock_handler;
2645         tree1->session->transport->oplock.private_data = tree1;
2646
2647         /*
2648           base ntcreatex parms
2649         */
2650         ZERO_STRUCT(io.smb2);
2651         io.generic.level = RAW_OPEN_SMB2;
2652         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2653         io.smb2.in.alloc_size = 0;
2654         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2655         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2656         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2657         io.smb2.in.create_options = 0;
2658         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2659         io.smb2.in.security_flags = 0;
2660         io.smb2.in.fname = fname;
2661
2662         torture_comment(tctx, "BATCH25: open a file with an batch oplock "
2663                         "(share mode: none)\n");
2664
2665         ZERO_STRUCT(break_info);
2666         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2667         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2668
2669         status = smb2_create(tree1, tctx, &(io.smb2));
2670         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2671         h1 = io.smb2.out.file.handle;
2672         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2673
2674         torture_comment(tctx, "changing the file attribute info should trigger "
2675                         "a break and a violation\n");
2676
2677         status = smb2_util_setatr(tree1, fname, FILE_ATTRIBUTE_HIDDEN);
2678         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
2679                                       "Incorrect status");
2680
2681         torture_wait_for_oplock_break(tctx);
2682         CHECK_VAL(break_info.count, 1);
2683
2684         smb2_util_close(tree1, h1);
2685         smb2_util_close(tree1, h);
2686
2687         smb2_deltree(tree1, fname);
2688         return ret;
2689 }
2690
2691 /* Test how oplocks work on streams. */
2692 static bool test_raw_oplock_stream1(struct torture_context *tctx,
2693                                     struct smb2_tree *tree1,
2694                                     struct smb2_tree *tree2)
2695 {
2696         NTSTATUS status;
2697         union smb_open io;
2698         const char *fname_base = BASEDIR "\\test_stream1.txt";
2699         const char *fname_stream, *fname_default_stream;
2700         const char *default_stream = "::$DATA";
2701         const char *stream = "Stream One:$DATA";
2702         bool ret = true;
2703         struct smb2_handle h, h_base, h_stream;
2704         int i;
2705
2706 #define NSTREAM_OPLOCK_RESULTS 8
2707         struct {
2708                 const char **fname;
2709                 bool open_base_file;
2710                 uint32_t oplock_req;
2711                 uint32_t oplock_granted;
2712         } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
2713                 /* Request oplock on stream without the base file open. */
2714                 {&fname_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2715                 {&fname_default_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2716                 {&fname_stream, false, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2717                 {&fname_default_stream, false,  SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2718
2719                 /* Request oplock on stream with the base file open. */
2720                 {&fname_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
2721                 {&fname_default_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_II},
2722                 {&fname_stream, true, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
2723                 {&fname_default_stream, true,  SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_II},
2724         };
2725
2726         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
2727         fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
2728                                                default_stream);
2729
2730         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2731         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2732
2733         /* Initialize handles to "closed".  Using -1 in the first 64-bytes
2734          * as the sentry for this */
2735         h_stream.data[0] = -1;
2736
2737         /* cleanup */
2738         smb2_util_unlink(tree1, fname_base);
2739
2740         tree1->session->transport->oplock.handler = torture_oplock_handler;
2741         tree1->session->transport->oplock.private_data = tree1;
2742
2743         tree2->session->transport->oplock.handler = torture_oplock_handler;
2744         tree2->session->transport->oplock.private_data = tree2;
2745
2746         /* Setup generic open parameters. */
2747         ZERO_STRUCT(io.smb2);
2748         io.generic.level = RAW_OPEN_SMB2;
2749         io.smb2.in.desired_access = (SEC_FILE_READ_DATA |
2750                                      SEC_FILE_WRITE_DATA |
2751                                      SEC_FILE_APPEND_DATA |
2752                                      SEC_STD_READ_CONTROL);
2753         io.smb2.in.alloc_size = 0;
2754         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2755         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2756                                   NTCREATEX_SHARE_ACCESS_WRITE;
2757         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2758         io.smb2.in.create_options = 0;
2759         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2760         io.smb2.in.security_flags = 0;
2761
2762         /* Create the file with a stream */
2763         io.smb2.in.fname = fname_stream;
2764         io.smb2.in.create_flags = 0;
2765         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2766         status = smb2_create(tree1, tctx, &(io.smb2));
2767         torture_assert_ntstatus_ok(tctx, status, "Error creating file");
2768         smb2_util_close(tree1, io.smb2.out.file.handle);
2769
2770         /* Change the disposition to open now that the file has been created. */
2771         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
2772
2773         /* Try some permutations of taking oplocks on streams. */
2774         for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
2775                 const char *fname = *stream_oplock_results[i].fname;
2776                 bool open_base_file = stream_oplock_results[i].open_base_file;
2777                 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
2778                 uint32_t oplock_granted =
2779                     stream_oplock_results[i].oplock_granted;
2780
2781                 if (open_base_file) {
2782                         torture_comment(tctx, "Opening base file: %s with "
2783                             "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2784                         io.smb2.in.fname = fname_base;
2785                         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2786                         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2787                         status = smb2_create(tree2, tctx, &(io.smb2));
2788                         torture_assert_ntstatus_ok(tctx, status,
2789                             "Error opening file");
2790                         CHECK_VAL(io.smb2.out.oplock_level,
2791                             SMB2_OPLOCK_LEVEL_BATCH);
2792                         h_base = io.smb2.out.file.handle;
2793                 }
2794
2795                 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
2796                     fname, oplock_req);
2797                 io.smb2.in.fname = fname;
2798                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2799                 io.smb2.in.oplock_level = oplock_req;
2800
2801                 /* Do the open with the desired oplock on the stream. */
2802                 status = smb2_create(tree1, tctx, &(io.smb2));
2803                 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2804                 CHECK_VAL(io.smb2.out.oplock_level, oplock_granted);
2805                 smb2_util_close(tree1, io.smb2.out.file.handle);
2806
2807                 /* Cleanup the base file if it was opened. */
2808                 if (open_base_file)
2809                         smb2_util_close(tree2, h_base);
2810         }
2811
2812         /* Open the stream with an exclusive oplock. */
2813         torture_comment(tctx, "Opening stream: %s with %d\n",
2814             fname_stream, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
2815         io.smb2.in.fname = fname_stream;
2816         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2817         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
2818         status = smb2_create(tree1, tctx, &(io.smb2));
2819         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2820         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
2821         h_stream = io.smb2.out.file.handle;
2822
2823         /* Open the base file and see if it contends. */
2824         ZERO_STRUCT(break_info);
2825         torture_comment(tctx, "Opening base file: %s with %d\n",
2826             fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2827         io.smb2.in.fname = fname_base;
2828         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2829         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2830         status = smb2_create(tree2, tctx, &(io.smb2));
2831         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2832         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2833         smb2_util_close(tree2, io.smb2.out.file.handle);
2834
2835         torture_wait_for_oplock_break(tctx);
2836         CHECK_VAL(break_info.count, 0);
2837         CHECK_VAL(break_info.failures, 0);
2838
2839         /* Open the stream again to see if it contends. */
2840         ZERO_STRUCT(break_info);
2841         torture_comment(tctx, "Opening stream again: %s with "
2842             "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
2843         io.smb2.in.fname = fname_stream;
2844         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2845         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
2846         status = smb2_create(tree2, tctx, &(io.smb2));
2847         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
2848         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
2849         smb2_util_close(tree2, io.smb2.out.file.handle);
2850
2851         torture_wait_for_oplock_break(tctx);
2852         CHECK_VAL(break_info.count, 1);
2853         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2854         CHECK_VAL(break_info.failures, 0);
2855
2856         /* Close the stream. */
2857         if (h_stream.data[0] != -1) {
2858                 smb2_util_close(tree1, h_stream);
2859         }
2860
2861         smb2_util_close(tree1, h);
2862
2863         smb2_deltree(tree1, BASEDIR);
2864         return ret;
2865 }
2866
2867 static bool test_smb2_oplock_doc(struct torture_context *tctx, struct smb2_tree *tree)
2868 {
2869         const char *fname = BASEDIR "\\test_oplock_doc.dat";
2870         NTSTATUS status;
2871         bool ret = true;
2872         union smb_open io;
2873         struct smb2_handle h, h1;
2874
2875         status = torture_smb2_testdir(tree, BASEDIR, &h);
2876         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2877
2878         /* cleanup */
2879         smb2_util_unlink(tree, fname);
2880         tree->session->transport->oplock.handler = torture_oplock_handler;
2881         tree->session->transport->oplock.private_data = tree;
2882
2883         /*
2884           base ntcreatex parms
2885         */
2886         ZERO_STRUCT(io.smb2);
2887         io.generic.level = RAW_OPEN_SMB2;
2888         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2889         io.smb2.in.alloc_size = 0;
2890         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2891         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2892         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2893         io.smb2.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
2894         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2895         io.smb2.in.security_flags = 0;
2896         io.smb2.in.fname = fname;
2897
2898         torture_comment(tctx, "open a delete-on-close file with a batch "
2899                         "oplock\n");
2900         ZERO_STRUCT(break_info);
2901         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2902         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2903
2904         status = smb2_create(tree, tctx, &(io.smb2));
2905         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2906         h1 = io.smb2.out.file.handle;
2907         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2908
2909         smb2_util_close(tree, h1);
2910
2911         smb2_util_unlink(tree, fname);
2912         smb2_deltree(tree, BASEDIR);
2913         return ret;
2914 }
2915
2916 /* Open a file with a batch oplock, then open it again from a second client
2917  * requesting no oplock. Having two open file handles should break our own
2918  * oplock during BRL acquisition.
2919  */
2920 static bool test_smb2_oplock_brl1(struct torture_context *tctx,
2921                                 struct smb2_tree *tree1,
2922                                 struct smb2_tree *tree2)
2923 {
2924         const char *fname = BASEDIR "\\test_batch_brl.dat";
2925         /*int fname, f;*/
2926         bool ret = true;
2927         uint8_t buf[1000];
2928         bool correct = true;
2929         union smb_open io;
2930         NTSTATUS status;
2931         struct smb2_lock lck;
2932         struct smb2_lock_element lock[1];
2933         struct smb2_handle h, h1, h2;
2934
2935         status = torture_smb2_testdir(tree1, BASEDIR, &h);
2936         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
2937
2938         /* cleanup */
2939         smb2_util_unlink(tree1, fname);
2940
2941         tree1->session->transport->oplock.handler =
2942             torture_oplock_handler_two_notifications;
2943         tree1->session->transport->oplock.private_data = tree1;
2944
2945         /*
2946           base ntcreatex parms
2947         */
2948         ZERO_STRUCT(io.smb2);
2949         io.generic.level = RAW_OPEN_SMB2;
2950         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
2951                                     SEC_RIGHTS_FILE_WRITE;
2952         io.smb2.in.alloc_size = 0;
2953         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2954         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2955                                   NTCREATEX_SHARE_ACCESS_WRITE;
2956         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2957         io.smb2.in.create_options = 0;
2958         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2959         io.smb2.in.security_flags = 0;
2960         io.smb2.in.fname = fname;
2961
2962         /*
2963           with a batch oplock we get a break
2964         */
2965         torture_comment(tctx, "open with batch oplock\n");
2966         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2967         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
2968
2969         status = smb2_create(tree1, tctx, &(io.smb2));
2970         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
2971         h1 = io.smb2.out.file.handle;
2972         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2973
2974         /* create a file with bogus data */
2975         memset(buf, 0, sizeof(buf));
2976
2977         status = smb2_util_write(tree1, h1,buf, 0, sizeof(buf));
2978         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
2979                 torture_comment(tctx, "Failed to create file\n");
2980                 correct = false;
2981                 goto done;
2982         }
2983
2984         torture_comment(tctx, "a 2nd open should give a break\n");
2985         ZERO_STRUCT(break_info);
2986
2987         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
2988         io.smb2.in.oplock_level = 0;
2989         status = smb2_create(tree2, tctx, &(io.smb2));
2990         h2 = io.smb2.out.file.handle;
2991         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
2992
2993         torture_wait_for_oplock_break(tctx);
2994         CHECK_VAL(break_info.count, 1);
2995         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2996         CHECK_VAL(break_info.failures, 0);
2997         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
2998
2999         ZERO_STRUCT(break_info);
3000
3001         torture_comment(tctx, "a self BRL acquisition should break to none\n");
3002         lock[0].offset = 0;
3003         lock[0].length = 4;
3004         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3005                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3006
3007         ZERO_STRUCT(lck);
3008         lck.in.file.handle = h1;
3009         lck.in.locks = &lock[0];
3010         lck.in.lock_count = 1;
3011         status = smb2_lock(tree1, &lck);
3012         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3013
3014         torture_wait_for_oplock_break(tctx);
3015         CHECK_VAL(break_info.count, 1);
3016         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3017         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3018         CHECK_VAL(break_info.failures, 0);
3019
3020         /* expect no oplock break */
3021         ZERO_STRUCT(break_info);
3022         lock[0].offset = 2;
3023         status = smb2_lock(tree1, &lck);
3024         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3025                                       "Incorrect status");
3026
3027         torture_wait_for_oplock_break(tctx);
3028         CHECK_VAL(break_info.count, 0);
3029         CHECK_VAL(break_info.level, 0);
3030         CHECK_VAL(break_info.failures, 0);
3031
3032         smb2_util_close(tree1, h1);
3033         smb2_util_close(tree2, h2);
3034         smb2_util_close(tree1, h);
3035
3036 done:
3037         smb2_deltree(tree1, BASEDIR);
3038         return ret;
3039
3040 }
3041
3042 /* Open a file with a batch oplock on one tree and then acquire a brl.
3043  * We should not contend our own oplock.
3044  */
3045 static bool test_smb2_oplock_brl2(struct torture_context *tctx, struct smb2_tree *tree1)
3046 {
3047         const char *fname = BASEDIR "\\test_batch_brl.dat";
3048         /*int fname, f;*/
3049         bool ret = true;
3050         uint8_t buf[1000];
3051         bool correct = true;
3052         union smb_open io;
3053         NTSTATUS status;
3054         struct smb2_handle h, h1;
3055         struct smb2_lock lck;
3056         struct smb2_lock_element lock[1];
3057
3058         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3059         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3060
3061         /* cleanup */
3062         smb2_util_unlink(tree1, fname);
3063
3064         tree1->session->transport->oplock.handler = torture_oplock_handler;
3065         tree1->session->transport->oplock.private_data = tree1;
3066
3067         /*
3068           base ntcreatex parms
3069         */
3070         ZERO_STRUCT(io.smb2);
3071         io.generic.level = RAW_OPEN_SMB2;
3072         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3073                                     SEC_RIGHTS_FILE_WRITE;
3074         io.smb2.in.alloc_size = 0;
3075         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3076         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3077                                   NTCREATEX_SHARE_ACCESS_WRITE;
3078         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3079         io.smb2.in.create_options = 0;
3080         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3081         io.smb2.in.security_flags = 0;
3082         io.smb2.in.fname = fname;
3083
3084         /*
3085           with a batch oplock we get a break
3086         */
3087         torture_comment(tctx, "open with batch oplock\n");
3088         ZERO_STRUCT(break_info);
3089         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3090         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3091
3092         status = smb2_create(tree1, tctx, &(io.smb2));
3093         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3094         h1 = io.smb2.out.file.handle;
3095         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3096
3097         /* create a file with bogus data */
3098         memset(buf, 0, sizeof(buf));
3099
3100         status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3101         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3102                 torture_comment(tctx, "Failed to create file\n");
3103                 correct = false;
3104                 goto done;
3105         }
3106
3107         ZERO_STRUCT(break_info);
3108
3109         torture_comment(tctx, "a self BRL acquisition should not break to "
3110                         "none\n");
3111
3112         lock[0].offset = 0;
3113         lock[0].length = 4;
3114         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3115                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3116
3117         ZERO_STRUCT(lck);
3118         lck.in.file.handle = h1;
3119         lck.in.locks = &lock[0];
3120         lck.in.lock_count = 1;
3121         status = smb2_lock(tree1, &lck);
3122         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3123
3124         lock[0].offset = 2;
3125         status = smb2_lock(tree1, &lck);
3126         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3127                                       "Incorrect status");
3128
3129         /* With one file handle open a BRL should not contend our oplock.
3130          * Thus, no oplock break will be received and the entire break_info
3131          * struct will be 0 */
3132         torture_wait_for_oplock_break(tctx);
3133         CHECK_VAL(break_info.count, 0);
3134         CHECK_VAL(break_info.level, 0);
3135         CHECK_VAL(break_info.failures, 0);
3136
3137         smb2_util_close(tree1, h1);
3138         smb2_util_close(tree1, h);
3139
3140 done:
3141         smb2_deltree(tree1, BASEDIR);
3142         return ret;
3143 }
3144
3145 /* Open a file with a batch oplock twice from one tree and then acquire a
3146  * brl. BRL acquisition should break our own oplock.
3147  */
3148 static bool test_smb2_oplock_brl3(struct torture_context *tctx, struct smb2_tree *tree1)
3149 {
3150         const char *fname = BASEDIR "\\test_batch_brl.dat";
3151         bool ret = true;
3152         uint8_t buf[1000];
3153         bool correct = true;
3154         union smb_open io;
3155         NTSTATUS status;
3156         struct smb2_handle h, h1, h2;
3157         struct smb2_lock lck;
3158         struct smb2_lock_element lock[1];
3159
3160         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3161         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3162
3163         /* cleanup */
3164         smb2_util_unlink(tree1, fname);
3165         tree1->session->transport->oplock.handler =
3166             torture_oplock_handler_two_notifications;
3167         tree1->session->transport->oplock.private_data = tree1;
3168
3169         /*
3170           base ntcreatex parms
3171         */
3172         ZERO_STRUCT(io.smb2);
3173         io.generic.level = RAW_OPEN_SMB2;
3174         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3175                                     SEC_RIGHTS_FILE_WRITE;
3176         io.smb2.in.alloc_size = 0;
3177         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3178         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3179                                   NTCREATEX_SHARE_ACCESS_WRITE;
3180         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3181         io.smb2.in.create_options = 0;
3182         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3183         io.smb2.in.security_flags = 0;
3184         io.smb2.in.fname = fname;
3185
3186         /*
3187           with a batch oplock we get a break
3188         */
3189         torture_comment(tctx, "open with batch oplock\n");
3190         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3191         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3192
3193         status = smb2_create(tree1, tctx, &(io.smb2));
3194         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3195         h1 = io.smb2.out.file.handle;
3196         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3197
3198         /* create a file with bogus data */
3199         memset(buf, 0, sizeof(buf));
3200         status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
3201
3202         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3203                 torture_comment(tctx, "Failed to create file\n");
3204                 correct = false;
3205                 goto done;
3206         }
3207
3208         torture_comment(tctx, "a 2nd open should give a break\n");
3209         ZERO_STRUCT(break_info);
3210
3211         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3212         io.smb2.in.oplock_level = 0;
3213         status = smb2_create(tree1, tctx, &(io.smb2));
3214         h2 = io.smb2.out.file.handle;
3215         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3216         CHECK_VAL(break_info.count, 1);
3217         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3218         CHECK_VAL(break_info.failures, 0);
3219         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3220
3221         ZERO_STRUCT(break_info);
3222
3223         torture_comment(tctx, "a self BRL acquisition should break to none\n");
3224
3225         lock[0].offset = 0;
3226         lock[0].length = 4;
3227         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
3228                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
3229
3230         ZERO_STRUCT(lck);
3231         lck.in.file.handle = h1;
3232         lck.in.locks = &lock[0];
3233         lck.in.lock_count = 1;
3234         status = smb2_lock(tree1, &lck);
3235         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3236
3237         torture_wait_for_oplock_break(tctx);
3238         CHECK_VAL(break_info.count, 1);
3239         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
3240         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
3241         CHECK_VAL(break_info.failures, 0);
3242
3243         /* expect no oplock break */
3244         ZERO_STRUCT(break_info);
3245         lock[0].offset = 2;
3246         status = smb2_lock(tree1, &lck);
3247         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
3248                                       "Incorrect status");
3249
3250         torture_wait_for_oplock_break(tctx);
3251         CHECK_VAL(break_info.count, 0);
3252         CHECK_VAL(break_info.level, 0);
3253         CHECK_VAL(break_info.failures, 0);
3254
3255         smb2_util_close(tree1, h1);
3256         smb2_util_close(tree1, h2);
3257         smb2_util_close(tree1, h);
3258
3259 done:
3260         smb2_deltree(tree1, BASEDIR);
3261         return ret;
3262
3263 }
3264
3265 /* Starting the SMB2 specific oplock tests at 500 so we can keep the SMB1
3266  * tests in sync with an identically numbered SMB2 test */
3267
3268 /* Test whether the server correctly returns an error when we send
3269  * a response to a levelII to none oplock notification. */
3270 static bool test_smb2_oplock_levelII500(struct torture_context *tctx,
3271                                       struct smb2_tree *tree1)
3272 {
3273         const char *fname = BASEDIR "\\test_levelII500.dat";
3274         NTSTATUS status;
3275         bool ret = true;
3276         union smb_open io;
3277         struct smb2_handle h, h1;
3278         char c = 0;
3279
3280         status = torture_smb2_testdir(tree1, BASEDIR, &h);
3281         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3282
3283         /* cleanup */
3284         smb2_util_unlink(tree1, fname);
3285
3286         tree1->session->transport->oplock.handler = torture_oplock_handler;
3287         tree1->session->transport->oplock.private_data = tree1;
3288
3289         /*
3290           base ntcreatex parms
3291         */
3292         ZERO_STRUCT(io.smb2);
3293         io.generic.level = RAW_OPEN_SMB2;
3294         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3295         io.smb2.in.alloc_size = 0;
3296         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3297         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3298         io.smb2.in.create_options = 0;
3299         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3300         io.smb2.in.security_flags = 0;
3301         io.smb2.in.fname = fname;
3302
3303         torture_comment(tctx, "LEVELII500: acknowledging a break from II to "
3304                         "none should return an error\n");
3305         ZERO_STRUCT(break_info);
3306
3307         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
3308                                 SEC_RIGHTS_FILE_WRITE;
3309         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3310                                 NTCREATEX_SHARE_ACCESS_WRITE;
3311         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3312         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
3313         status = smb2_create(tree1, tctx, &(io.smb2));
3314         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
3315         h1 = io.smb2.out.file.handle;
3316         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
3317
3318         ZERO_STRUCT(break_info);
3319
3320         torture_comment(tctx, "write should trigger a break to none and when "
3321                         "we reply, an oplock break failure\n");
3322         smb2_util_write(tree1, h1, &c, 0, 1);
3323
3324         /* Wait several times to receive both the break notification, and the
3325          * NT_STATUS_INVALID_OPLOCK_PROTOCOL error in the break response */
3326         torture_wait_for_oplock_break(tctx);
3327         torture_wait_for_oplock_break(tctx);
3328         torture_wait_for_oplock_break(tctx);
3329         torture_wait_for_oplock_break(tctx);
3330
3331         /* There appears to be a race condition in W2K8 and W2K8R2 where
3332          * sometimes the server will happily reply to our break response with
3333          * NT_STATUS_OK, and sometimes it will return the OPLOCK_PROTOCOL
3334          * error.  As the MS-SMB2 doc states that a client should not reply to
3335          * a level2 to none break notification, I'm leaving the protocol error
3336          * as the expected behavior. */
3337         CHECK_VAL(break_info.count, 1);
3338         CHECK_VAL(break_info.level, 0);
3339         CHECK_VAL(break_info.failures, 1);
3340         torture_assert_ntstatus_equal(tctx, break_info.failure_status,
3341                                       NT_STATUS_INVALID_OPLOCK_PROTOCOL,
3342                                       "Incorrect status");
3343
3344         smb2_util_close(tree1, h1);
3345         smb2_util_close(tree1, h);
3346
3347         smb2_deltree(tree1, BASEDIR);
3348         return ret;
3349 }
3350
3351 struct torture_suite *torture_smb2_oplocks_init(void)
3352 {
3353         struct torture_suite *suite =
3354             torture_suite_create(talloc_autofree_context(), "oplock");
3355
3356         torture_suite_add_2smb2_test(suite, "exclusive1", test_smb2_oplock_exclusive1);
3357         torture_suite_add_2smb2_test(suite, "exclusive2", test_smb2_oplock_exclusive2);
3358         torture_suite_add_2smb2_test(suite, "exclusive3", test_smb2_oplock_exclusive3);
3359         torture_suite_add_2smb2_test(suite, "exclusive4", test_smb2_oplock_exclusive4);
3360         torture_suite_add_2smb2_test(suite, "exclusive5", test_smb2_oplock_exclusive5);
3361         torture_suite_add_2smb2_test(suite, "exclusive6", test_smb2_oplock_exclusive6);
3362         torture_suite_add_2smb2_test(suite, "batch1", test_smb2_oplock_batch1);
3363         torture_suite_add_2smb2_test(suite, "batch2", test_smb2_oplock_batch2);
3364         torture_suite_add_2smb2_test(suite, "batch3", test_smb2_oplock_batch3);
3365         torture_suite_add_2smb2_test(suite, "batch4", test_smb2_oplock_batch4);
3366         torture_suite_add_2smb2_test(suite, "batch5", test_smb2_oplock_batch5);
3367         torture_suite_add_2smb2_test(suite, "batch6", test_smb2_oplock_batch6);
3368         torture_suite_add_2smb2_test(suite, "batch7", test_smb2_oplock_batch7);
3369         torture_suite_add_2smb2_test(suite, "batch8", test_smb2_oplock_batch8);
3370         torture_suite_add_2smb2_test(suite, "batch9", test_smb2_oplock_batch9);
3371         torture_suite_add_2smb2_test(suite, "batch10", test_smb2_oplock_batch10);
3372         torture_suite_add_2smb2_test(suite, "batch11", test_smb2_oplock_batch11);
3373         torture_suite_add_2smb2_test(suite, "batch12", test_smb2_oplock_batch12);
3374         torture_suite_add_2smb2_test(suite, "batch13", test_smb2_oplock_batch13);
3375         torture_suite_add_2smb2_test(suite, "batch14", test_smb2_oplock_batch14);
3376         torture_suite_add_2smb2_test(suite, "batch15", test_smb2_oplock_batch15);
3377         torture_suite_add_2smb2_test(suite, "batch16", test_smb2_oplock_batch16);
3378         torture_suite_add_1smb2_test(suite, "batch19", test_smb2_oplock_batch19);
3379         torture_suite_add_2smb2_test(suite, "batch20", test_smb2_oplock_batch20);
3380         torture_suite_add_1smb2_test(suite, "batch21", test_smb2_oplock_batch21);
3381         torture_suite_add_1smb2_test(suite, "batch22", test_smb2_oplock_batch22);
3382         torture_suite_add_2smb2_test(suite, "batch23", test_smb2_oplock_batch23);
3383         torture_suite_add_2smb2_test(suite, "batch24", test_smb2_oplock_batch24);
3384         torture_suite_add_1smb2_test(suite, "batch25", test_smb2_oplock_batch25);
3385         torture_suite_add_2smb2_test(suite, "stream1", test_raw_oplock_stream1);
3386         torture_suite_add_1smb2_test(suite, "doc", test_smb2_oplock_doc);
3387         torture_suite_add_2smb2_test(suite, "brl1", test_smb2_oplock_brl1);
3388         torture_suite_add_1smb2_test(suite, "brl2", test_smb2_oplock_brl2);
3389         torture_suite_add_1smb2_test(suite, "brl3", test_smb2_oplock_brl3);
3390         torture_suite_add_1smb2_test(suite, "levelii500", test_smb2_oplock_levelII500);
3391
3392         suite->description = talloc_strdup(suite, "SMB2-OPLOCK tests");
3393
3394         return suite;
3395 }
3396
3397 /*
3398    stress testing of oplocks
3399 */
3400 bool test_smb2_bench_oplock(struct torture_context *tctx,
3401                                    struct smb2_tree *tree)
3402 {
3403         struct smb2_tree **trees;
3404         bool ret = true;
3405         NTSTATUS status;
3406         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3407         int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
3408         int i, count=0;
3409         int timelimit = torture_setting_int(tctx, "timelimit", 10);
3410         union smb_open io;
3411         struct timeval tv;
3412         struct smb2_handle h;
3413
3414         trees = talloc_array(mem_ctx, struct smb2_tree *, torture_nprocs);
3415
3416         torture_comment(tctx, "Opening %d connections\n", torture_nprocs);
3417         for (i=0;i<torture_nprocs;i++) {
3418                 if (!torture_smb2_connection(tctx, &trees[i])) {
3419                         return false;
3420                 }
3421                 talloc_steal(mem_ctx, trees[i]);
3422                 trees[i]->session->transport->oplock.handler =
3423                                         torture_oplock_handler_close;
3424                 trees[i]->session->transport->oplock.private_data = trees[i];
3425         }
3426
3427         status = torture_smb2_testdir(trees[0], BASEDIR, &h);
3428         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3429
3430         ZERO_STRUCT(io.smb2);
3431         io.smb2.level = RAW_OPEN_SMB2;
3432         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3433         io.smb2.in.alloc_size = 0;
3434         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3435         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3436         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3437         io.smb2.in.create_options = 0;
3438         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3439         io.smb2.in.security_flags = 0;
3440         io.smb2.in.fname = BASEDIR "\\test.dat";
3441         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3442         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3443
3444         tv = timeval_current();
3445
3446         /*
3447           we open the same file with SHARE_ACCESS_NONE from all the
3448           connections in a round robin fashion. Each open causes an
3449           oplock break on the previous connection, which is answered
3450           by the oplock_handler_close() to close the file.
3451
3452           This measures how fast we can pass on oplocks, and stresses
3453           the oplock handling code
3454         */
3455         torture_comment(tctx, "Running for %d seconds\n", timelimit);
3456         while (timeval_elapsed(&tv) < timelimit) {
3457                 for (i=0;i<torture_nprocs;i++) {
3458                         status = smb2_create(trees[i], mem_ctx, &(io.smb2));
3459                         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
3460                         count++;
3461                 }
3462
3463                 if (torture_setting_bool(tctx, "progress", true)) {
3464                         torture_comment(tctx, "%.2f ops/second\r",
3465                                         count/timeval_elapsed(&tv));
3466                 }
3467         }
3468
3469         torture_comment(tctx, "%.2f ops/second\n", count/timeval_elapsed(&tv));
3470         smb2_util_close(trees[0], io.smb2.out.file.handle);
3471         smb2_util_unlink(trees[0], BASEDIR "\\test.dat");
3472         smb2_deltree(trees[0], BASEDIR);
3473         talloc_free(mem_ctx);
3474         return ret;
3475 }
3476
3477 static struct hold_oplock_info {
3478         const char *fname;
3479         bool close_on_break;
3480         uint32_t share_access;
3481         struct smb2_handle handle;
3482 } hold_info[] = {
3483         { BASEDIR "\\notshared_close", true,
3484           NTCREATEX_SHARE_ACCESS_NONE, },
3485         { BASEDIR "\\notshared_noclose", false,
3486           NTCREATEX_SHARE_ACCESS_NONE, },
3487         { BASEDIR "\\shared_close", true,
3488           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3489         { BASEDIR "\\shared_noclose", false,
3490           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3491 };
3492
3493 static bool torture_oplock_handler_hold(struct smb2_transport *transport,
3494                                         const struct smb2_handle *handle,
3495                                         uint8_t level, void *private_data)
3496 {
3497         struct hold_oplock_info *info;
3498         int i;
3499
3500         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3501                 if (smb2_util_handle_equal(hold_info[i].handle, *handle))
3502                         break;
3503         }
3504
3505         if (i == ARRAY_SIZE(hold_info)) {
3506                 printf("oplock break for unknown handle 0x%llx%llx\n",
3507                        (unsigned long long) handle->data[0],
3508                        (unsigned long long) handle->data[1]);
3509                 return false;
3510         }
3511
3512         info = &hold_info[i];
3513
3514         if (info->close_on_break) {
3515                 printf("oplock break on %s - closing\n", info->fname);
3516                 torture_oplock_handler_close(transport, handle,
3517                                              level, private_data);
3518                 return true;
3519         }
3520
3521         printf("oplock break on %s - acking break\n", info->fname);
3522         printf("Acking to none in oplock handler\n");
3523
3524         torture_oplock_handler_ack_to_none(transport, handle,
3525                                            level, private_data);
3526         return true;
3527 }
3528
3529 /*
3530    used for manual testing of oplocks - especially interaction with
3531    other filesystems (such as NFS and local access)
3532 */
3533 bool test_smb2_hold_oplock(struct torture_context *tctx,
3534                            struct smb2_tree *tree)
3535 {
3536         struct torture_context *mem_ctx = talloc_new(tctx);
3537         struct tevent_context *ev =
3538                 (struct tevent_context *)tree->session->transport->socket->event.ctx;
3539         int i;
3540         struct smb2_handle h;
3541         NTSTATUS status;
3542
3543         torture_comment(tctx, "Setting up open files with oplocks in %s\n",
3544                         BASEDIR);
3545
3546         status = torture_smb2_testdir(tree, BASEDIR, &h);
3547         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
3548
3549         tree->session->transport->oplock.handler = torture_oplock_handler_hold;
3550         tree->session->transport->oplock.private_data = tree;
3551
3552         /* setup the files */
3553         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3554                 union smb_open io;
3555                 char c = 1;
3556
3557                 ZERO_STRUCT(io.smb2);
3558                 io.generic.level = RAW_OPEN_SMB2;
3559                 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
3560                 io.smb2.in.alloc_size = 0;
3561                 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3562                 io.smb2.in.share_access = hold_info[i].share_access;
3563                 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3564                 io.smb2.in.create_options = 0;
3565                 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3566                 io.smb2.in.security_flags = 0;
3567                 io.smb2.in.fname = hold_info[i].fname;
3568                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
3569                 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
3570
3571                 torture_comment(tctx, "opening %s\n", hold_info[i].fname);
3572
3573                 status = smb2_create(tree, mem_ctx, &(io.smb2));
3574                 if (!NT_STATUS_IS_OK(status)) {
3575                         torture_comment(tctx, "Failed to open %s - %s\n",
3576                                hold_info[i].fname, nt_errstr(status));
3577                         return false;
3578                 }
3579
3580                 if (io.smb2.out.oplock_level != SMB2_OPLOCK_LEVEL_BATCH) {
3581                         torture_comment(tctx, "Oplock not granted for %s - "
3582                                         "expected %d but got %d\n",
3583                                         hold_info[i].fname,
3584                                         SMB2_OPLOCK_LEVEL_BATCH,
3585                                         io.smb2.out.oplock_level);
3586                         return false;
3587                 }
3588                 hold_info[i].handle = io.smb2.out.file.handle;
3589
3590                 /* make the file non-zero size */
3591                 status = smb2_util_write(tree, hold_info[i].handle, &c, 0, 1);
3592                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
3593                         torture_comment(tctx, "Failed to write to file\n");
3594                         return false;
3595                 }
3596         }
3597
3598         torture_comment(tctx, "Waiting for oplock events\n");
3599         event_loop_wait(ev);
3600         smb2_deltree(tree, BASEDIR);
3601         talloc_free(mem_ctx);
3602         return true;
3603 }