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