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