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