1d5fd4f8de59750c8f2fa7c2ac8c7a7e5cc5983e
[samba.git] / source4 / torture / raw / oplock.c
1 /* 
2    Unix SMB/CIFS implementation.
3    basic raw test suite for oplocks
4    Copyright (C) Andrew Tridgell 2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "libcli/raw/libcliraw.h"
22 #include "libcli/raw/raw_proto.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
25 #include "lib/events/events.h"
26 #include "param/param.h"
27 #include "lib/cmdline/popt_common.h"
28 #include "libcli/resolve/resolve.h"
29 #include "torture/raw/proto.h"
30
31 #define CHECK_VAL(v, correct) do { \
32         if ((v) != (correct)) { \
33                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
34                                 __location__, #v, (int)v, (int)correct); \
35                 ret = false; \
36         }} while (0)
37
38 #define CHECK_RANGE(v, min, max) do {                                   \
39         if ((v) < (min) || (v) > (max)) {                               \
40                 torture_warning(tctx, "(%s): wrong value for %s got "   \
41                     "%d - should be between %d and %d\n",               \
42                     __location__, #v, (int)v, (int)min, (int)max);      \
43         }} while (0)
44
45 #define CHECK_STRMATCH(v, correct) do { \
46         if (!v || strstr((v),(correct)) == NULL) { \
47                 torture_result(tctx, TORTURE_FAIL,  "(%s): wrong value for %s got '%s' - should be '%s'\n", \
48                                 __location__, #v, v?v:"NULL", correct); \
49                 ret = false; \
50         } \
51 } while (0)
52
53 #define CHECK_STATUS(tctx, status, correct) do { \
54         if (!NT_STATUS_EQUAL(status, correct)) { \
55                 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
56                        nt_errstr(status), nt_errstr(correct)); \
57                 ret = false; \
58                 goto done; \
59         }} while (0)
60
61
62 static struct {
63         int fnum;
64         uint8_t level;
65         int count;
66         int failures;
67 } break_info;
68
69 #define BASEDIR "\\test_oplock"
70
71 /*
72   a handler function for oplock break requests. Ack it as a break to level II if possible
73 */
74 static bool oplock_handler_ack_to_given(struct smbcli_transport *transport,
75                                         uint16_t tid, uint16_t fnum,
76                                         uint8_t level, void *private_data)
77 {
78         struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
79         const char *name;
80
81         break_info.fnum = fnum;
82         break_info.level = level;
83         break_info.count++;
84
85         switch (level) {
86         case OPLOCK_BREAK_TO_LEVEL_II:
87                 name = "level II";
88                 break;
89         case OPLOCK_BREAK_TO_NONE:
90                 name = "none";
91                 break;
92         default:
93                 name = "unknown";
94                 break_info.failures++;
95         }
96         printf("Acking to %s [0x%02X] in oplock handler\n",
97                 name, level);
98
99         return smbcli_oplock_ack(tree, fnum, level);
100 }
101
102 /*
103   a handler function for oplock break requests. Ack it as a break to none
104 */
105 static bool oplock_handler_ack_to_none(struct smbcli_transport *transport, 
106                                        uint16_t tid, uint16_t fnum, 
107                                        uint8_t level, void *private_data)
108 {
109         struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
110         break_info.fnum = fnum;
111         break_info.level = level;
112         break_info.count++;
113
114         printf("Acking to none in oplock handler\n");
115
116         return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
117 }
118
119 /*
120   a handler function for oplock break requests. Let it timeout
121 */
122 static bool oplock_handler_timeout(struct smbcli_transport *transport,
123                                    uint16_t tid, uint16_t fnum,
124                                    uint8_t level, void *private_data)
125 {
126         break_info.fnum = fnum;
127         break_info.level = level;
128         break_info.count++;
129
130         printf("Let oplock break timeout\n");
131         return true;
132 }
133
134 static void oplock_handler_close_recv(struct smbcli_request *req)
135 {
136         NTSTATUS status;
137         status = smbcli_request_simple_recv(req);
138         if (!NT_STATUS_IS_OK(status)) {
139                 printf("close failed in oplock_handler_close\n");
140                 break_info.failures++;
141         }
142 }
143
144 /*
145   a handler function for oplock break requests - close the file
146 */
147 static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t tid, 
148                                  uint16_t fnum, uint8_t level, void *private_data)
149 {
150         union smb_close io;
151         struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
152         struct smbcli_request *req;
153
154         break_info.fnum = fnum;
155         break_info.level = level;
156         break_info.count++;
157
158         io.close.level = RAW_CLOSE_CLOSE;
159         io.close.in.file.fnum = fnum;
160         io.close.in.write_time = 0;
161         req = smb_raw_close_send(tree, &io);
162         if (req == NULL) {
163                 printf("failed to send close in oplock_handler_close\n");
164                 return false;
165         }
166
167         req->async.fn = oplock_handler_close_recv;
168         req->async.private_data = NULL;
169
170         return true;
171 }
172
173 static bool open_connection_no_level2_oplocks(struct torture_context *tctx,
174                                               struct smbcli_state **c)
175 {
176         NTSTATUS status;
177         struct smbcli_options options;
178         struct smbcli_session_options session_options;
179
180         lpcfg_smbcli_options(tctx->lp_ctx, &options);
181         lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);
182
183         options.use_level2_oplocks = false;
184
185         status = smbcli_full_connection(tctx, c,
186                                         torture_setting_string(tctx, "host", NULL),
187                                         lpcfg_smb_ports(tctx->lp_ctx),
188                                         torture_setting_string(tctx, "share", NULL),
189                                         NULL, lpcfg_socket_options(tctx->lp_ctx),
190                                         popt_get_cmdline_credentials(),
191                                         lpcfg_resolve_context(tctx->lp_ctx),
192                                         tctx->ev, &options, &session_options,
193                                         lpcfg_gensec_settings(tctx, tctx->lp_ctx));
194         if (!NT_STATUS_IS_OK(status)) {
195                 torture_comment(tctx, "Failed to open connection - %s\n",
196                                 nt_errstr(status));
197                 return false;
198         }
199
200         return true;
201 }
202
203 /*
204    Timer handler function notifies the registering function that time is up
205 */
206 static void timeout_cb(struct tevent_context *ev,
207                        struct tevent_timer *te,
208                        struct timeval current_time,
209                        void *private_data)
210 {
211         bool *timesup = (bool *)private_data;
212         *timesup = true;
213         return;
214 }
215
216 /*
217    Wait a short period of time to receive a single oplock break request
218 */
219 static void torture_wait_for_oplock_break(struct torture_context *tctx)
220 {
221         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
222         struct tevent_timer *te = NULL;
223         struct timeval ne;
224         bool timesup = false;
225         int old_count = break_info.count;
226
227         /* Wait .1 seconds for an oplock break */
228         ne = tevent_timeval_current_ofs(0, 100000);
229
230         if ((te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup))
231             == NULL)
232         {
233                 torture_comment(tctx, "Failed to wait for an oplock break. "
234                                       "test results may not be accurate.");
235                 goto done;
236         }
237
238         while (!timesup && break_info.count < old_count + 1) {
239                 if (tevent_loop_once(tctx->ev) != 0) {
240                         torture_comment(tctx, "Failed to wait for an oplock "
241                                               "break. test results may not be "
242                                               "accurate.");
243                         goto done;
244                 }
245         }
246
247 done:
248         /* We don't know if the timed event fired and was freed, we received
249          * our oplock break, or some other event triggered the loop.  Thus,
250          * we create a tmp_ctx to be able to safely free/remove the timed
251          * event in all 3 cases. */
252         talloc_free(tmp_ctx);
253
254         return;
255 }
256
257 static uint8_t get_break_level1_to_none_count(struct torture_context *tctx)
258 {
259         return torture_setting_bool(tctx, "2_step_break_to_none", false) ?
260             2 : 1;
261 }
262
263 static uint8_t get_setinfo_break_count(struct torture_context *tctx)
264 {
265         if (TARGET_IS_W2K12(tctx)) {
266                 return 2;
267         }
268         if (TARGET_IS_SAMBA3(tctx)) {
269                 return 2;
270         }
271         return 1;
272 }
273
274 static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
275 {
276         const char *fname = BASEDIR "\\test_exclusive1.dat";
277         NTSTATUS status;
278         bool ret = true;
279         union smb_open io;
280         union smb_unlink unl;
281         uint16_t fnum=0;
282
283         if (!torture_setup_dir(cli1, BASEDIR)) {
284                 return false;
285         }
286
287         /* cleanup */
288         smbcli_unlink(cli1->tree, fname);
289
290         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
291
292         /*
293           base ntcreatex parms
294         */
295         io.generic.level = RAW_OPEN_NTCREATEX;
296         io.ntcreatex.in.root_fid.fnum = 0;
297         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
298         io.ntcreatex.in.alloc_size = 0;
299         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
300         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
301         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
302         io.ntcreatex.in.create_options = 0;
303         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
304         io.ntcreatex.in.security_flags = 0;
305         io.ntcreatex.in.fname = fname;
306
307         torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
308         ZERO_STRUCT(break_info);
309         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
310
311         status = smb_raw_open(cli1->tree, tctx, &io);
312         CHECK_STATUS(tctx, status, NT_STATUS_OK);
313         fnum = io.ntcreatex.out.file.fnum;
314         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
315
316         torture_comment(tctx, "a 2nd open should not cause a break\n");
317         status = smb_raw_open(cli2->tree, tctx, &io);
318         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
319         torture_wait_for_oplock_break(tctx);
320         CHECK_VAL(break_info.count, 0);
321         CHECK_VAL(break_info.failures, 0);
322
323         torture_comment(tctx, "unlink it - should also be no break\n");
324         unl.unlink.in.pattern = fname;
325         unl.unlink.in.attrib = 0;
326         status = smb_raw_unlink(cli2->tree, &unl);
327         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
328         torture_wait_for_oplock_break(tctx);
329         CHECK_VAL(break_info.count, 0);
330         CHECK_VAL(break_info.failures, 0);
331
332         smbcli_close(cli1->tree, fnum);
333
334 done:
335         smb_raw_exit(cli1->session);
336         smb_raw_exit(cli2->session);
337         smbcli_deltree(cli1->tree, BASEDIR);
338         return ret;
339 }
340
341 static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
342 {
343         const char *fname = BASEDIR "\\test_exclusive2.dat";
344         NTSTATUS status;
345         bool ret = true;
346         union smb_open io;
347         union smb_unlink unl;
348         uint16_t fnum=0, fnum2=0;
349
350         if (!torture_setup_dir(cli1, BASEDIR)) {
351                 return false;
352         }
353
354         /* cleanup */
355         smbcli_unlink(cli1->tree, fname);
356
357         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
358
359         /*
360           base ntcreatex parms
361         */
362         io.generic.level = RAW_OPEN_NTCREATEX;
363         io.ntcreatex.in.root_fid.fnum = 0;
364         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
365         io.ntcreatex.in.alloc_size = 0;
366         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
367         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
368         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
369         io.ntcreatex.in.create_options = 0;
370         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
371         io.ntcreatex.in.security_flags = 0;
372         io.ntcreatex.in.fname = fname;
373
374         torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
375         ZERO_STRUCT(break_info);
376         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
377         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
378                 NTCREATEX_SHARE_ACCESS_WRITE|
379                 NTCREATEX_SHARE_ACCESS_DELETE;
380
381         status = smb_raw_open(cli1->tree, tctx, &io);
382         CHECK_STATUS(tctx, status, NT_STATUS_OK);
383         fnum = io.ntcreatex.out.file.fnum;
384         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
385
386         torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
387         status = smb_raw_open(cli2->tree, tctx, &io);
388         CHECK_STATUS(tctx, status, NT_STATUS_OK);
389         fnum2 = io.ntcreatex.out.file.fnum;
390         torture_wait_for_oplock_break(tctx);
391         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
392         CHECK_VAL(break_info.count, 1);
393         CHECK_VAL(break_info.fnum, fnum);
394         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
395         CHECK_VAL(break_info.failures, 0);
396         ZERO_STRUCT(break_info);
397
398         /* now we have 2 level II oplocks... */
399         torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
400         unl.unlink.in.pattern = fname;
401         unl.unlink.in.attrib = 0;
402         status = smb_raw_unlink(cli2->tree, &unl);
403         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
404         torture_wait_for_oplock_break(tctx);
405         CHECK_VAL(break_info.count, 0);
406         CHECK_VAL(break_info.failures, 0);
407
408         torture_comment(tctx, "close 1st handle\n");
409         smbcli_close(cli1->tree, fnum);
410
411         torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
412         unl.unlink.in.pattern = fname;
413         unl.unlink.in.attrib = 0;
414         status = smb_raw_unlink(cli2->tree, &unl);
415         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
416         torture_wait_for_oplock_break(tctx);
417         CHECK_VAL(break_info.count, 0);
418         CHECK_VAL(break_info.failures, 0);
419
420         torture_comment(tctx, "close 2nd handle\n");
421         smbcli_close(cli2->tree, fnum2);
422
423         torture_comment(tctx, "unlink it\n");
424         unl.unlink.in.pattern = fname;
425         unl.unlink.in.attrib = 0;
426         status = smb_raw_unlink(cli2->tree, &unl);
427         CHECK_STATUS(tctx, status, NT_STATUS_OK);
428         torture_wait_for_oplock_break(tctx);
429         CHECK_VAL(break_info.count, 0);
430         CHECK_VAL(break_info.failures, 0);
431
432 done:
433         smb_raw_exit(cli1->session);
434         smb_raw_exit(cli2->session);
435         smbcli_deltree(cli1->tree, BASEDIR);
436         return ret;
437 }
438
439 static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
440 {
441         const char *fname = BASEDIR "\\test_exclusive3.dat";
442         NTSTATUS status;
443         bool ret = true;
444         union smb_open io;
445         union smb_setfileinfo sfi;
446         uint16_t fnum=0;
447
448         if (!torture_setup_dir(cli1, BASEDIR)) {
449                 return false;
450         }
451
452         /* cleanup */
453         smbcli_unlink(cli1->tree, fname);
454
455         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
456
457         /*
458           base ntcreatex parms
459         */
460         io.generic.level = RAW_OPEN_NTCREATEX;
461         io.ntcreatex.in.root_fid.fnum = 0;
462         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
463         io.ntcreatex.in.alloc_size = 0;
464         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
465         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
466         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
467         io.ntcreatex.in.create_options = 0;
468         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
469         io.ntcreatex.in.security_flags = 0;
470         io.ntcreatex.in.fname = fname;
471
472         torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
473
474         ZERO_STRUCT(break_info);
475         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
476
477         status = smb_raw_open(cli1->tree, tctx, &io);
478         CHECK_STATUS(tctx, status, NT_STATUS_OK);
479         fnum = io.ntcreatex.out.file.fnum;
480         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
481
482         torture_comment(tctx, "setpathinfo EOF should trigger a break to none\n");
483         ZERO_STRUCT(sfi);
484         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
485         sfi.generic.in.file.path = fname;
486         sfi.end_of_file_info.in.size = 100;
487
488         status = smb_raw_setpathinfo(cli2->tree, &sfi);
489
490         CHECK_STATUS(tctx, status, NT_STATUS_OK);
491         torture_wait_for_oplock_break(tctx);
492         CHECK_VAL(break_info.count, get_setinfo_break_count(tctx));
493         CHECK_VAL(break_info.failures, 0);
494         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
495
496         smbcli_close(cli1->tree, fnum);
497
498 done:
499         smb_raw_exit(cli1->session);
500         smb_raw_exit(cli2->session);
501         smbcli_deltree(cli1->tree, BASEDIR);
502         return ret;
503 }
504
505 static bool test_raw_oplock_exclusive4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
506 {
507         const char *fname = BASEDIR "\\test_exclusive4.dat";
508         NTSTATUS status;
509         bool ret = true;
510         union smb_open io;
511         uint16_t fnum=0, fnum2=0;
512
513         if (!torture_setup_dir(cli1, BASEDIR)) {
514                 return false;
515         }
516
517         /* cleanup */
518         smbcli_unlink(cli1->tree, fname);
519
520         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
521
522         /*
523           base ntcreatex parms
524         */
525         io.generic.level = RAW_OPEN_NTCREATEX;
526         io.ntcreatex.in.root_fid.fnum = 0;
527         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
528         io.ntcreatex.in.alloc_size = 0;
529         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
530         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
531         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
532         io.ntcreatex.in.create_options = 0;
533         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
534         io.ntcreatex.in.security_flags = 0;
535         io.ntcreatex.in.fname = fname;
536
537         torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
538         ZERO_STRUCT(break_info);
539         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
540
541         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
542         status = smb_raw_open(cli1->tree, tctx, &io);
543         CHECK_STATUS(tctx, status, NT_STATUS_OK);
544         fnum = io.ntcreatex.out.file.fnum;
545         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
546
547         ZERO_STRUCT(break_info);
548         torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
549
550         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
551         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
552         status = smb_raw_open(cli2->tree, tctx, &io);
553         CHECK_STATUS(tctx, status, NT_STATUS_OK);
554         fnum2 = io.ntcreatex.out.file.fnum;
555         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
556         torture_wait_for_oplock_break(tctx);
557         CHECK_VAL(break_info.count, 0);
558         CHECK_VAL(break_info.failures, 0);
559
560         /*
561          * Open another non-stat open. This reproduces bug 10216. Make sure it
562          * won't happen again...
563          */
564         io.ntcreatex.in.flags = 0;
565         io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
566         status = smb_raw_open(cli2->tree, tctx, &io);
567         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
568         torture_wait_for_oplock_break(tctx);
569         CHECK_VAL(break_info.count, 0);
570         CHECK_VAL(break_info.failures, 0);
571
572         smbcli_close(cli1->tree, fnum);
573         smbcli_close(cli2->tree, fnum2);
574
575 done:
576         smb_raw_exit(cli1->session);
577         smb_raw_exit(cli2->session);
578         smbcli_deltree(cli1->tree, BASEDIR);
579         return ret;
580 }
581
582 static bool test_raw_oplock_exclusive5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
583 {
584         const char *fname = BASEDIR "\\test_exclusive5.dat";
585         NTSTATUS status;
586         bool ret = true;
587         union smb_open io;
588         uint16_t fnum=0, fnum2=0;
589
590         if (!torture_setup_dir(cli1, BASEDIR)) {
591                 return false;
592         }
593
594         /* cleanup */
595         smbcli_unlink(cli1->tree, fname);
596
597         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
598         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
599
600         /*
601           base ntcreatex parms
602         */
603         io.generic.level = RAW_OPEN_NTCREATEX;
604         io.ntcreatex.in.root_fid.fnum = 0;
605         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
606         io.ntcreatex.in.alloc_size = 0;
607         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
608         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
609         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
610         io.ntcreatex.in.create_options = 0;
611         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
612         io.ntcreatex.in.security_flags = 0;
613         io.ntcreatex.in.fname = fname;
614
615         torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
616         ZERO_STRUCT(break_info);
617         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
618
619
620         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
621         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
622                 NTCREATEX_SHARE_ACCESS_WRITE|
623                 NTCREATEX_SHARE_ACCESS_DELETE;
624         status = smb_raw_open(cli1->tree, tctx, &io);
625         CHECK_STATUS(tctx, status, NT_STATUS_OK);
626         fnum = io.ntcreatex.out.file.fnum;
627         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
628
629         ZERO_STRUCT(break_info);
630
631         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
632
633         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
634         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
635         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
636         status = smb_raw_open(cli2->tree, tctx, &io);
637         CHECK_STATUS(tctx, status, NT_STATUS_OK);
638         fnum2 = io.ntcreatex.out.file.fnum;
639         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
640         torture_wait_for_oplock_break(tctx);
641         CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
642         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
643         CHECK_VAL(break_info.failures, 0);
644
645         smbcli_close(cli1->tree, fnum);
646         smbcli_close(cli2->tree, fnum2);
647
648 done:
649         smb_raw_exit(cli1->session);
650         smb_raw_exit(cli2->session);
651         smbcli_deltree(cli1->tree, BASEDIR);
652         return ret;
653 }
654
655 static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
656 {
657         const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
658         const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
659         NTSTATUS status;
660         bool ret = true;
661         union smb_open io;
662         union smb_rename rn;
663         uint16_t fnum=0;
664
665         if (!torture_setup_dir(cli1, BASEDIR)) {
666                 return false;
667         }
668
669         /* cleanup */
670         smbcli_unlink(cli1->tree, fname1);
671         smbcli_unlink(cli1->tree, fname2);
672
673         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
674
675         /*
676           base ntcreatex parms
677         */
678         io.generic.level = RAW_OPEN_NTCREATEX;
679         io.ntcreatex.in.root_fid.fnum = 0;
680         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
681         io.ntcreatex.in.alloc_size = 0;
682         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
683         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
684         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
685         io.ntcreatex.in.create_options = 0;
686         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
687         io.ntcreatex.in.security_flags = 0;
688         io.ntcreatex.in.fname = fname1;
689
690         torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
691                         "oplock (share mode: none)\n");
692         ZERO_STRUCT(break_info);
693         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
694
695         status = smb_raw_open(cli1->tree, tctx, &io);
696         CHECK_STATUS(tctx, status, NT_STATUS_OK);
697         fnum = io.ntcreatex.out.file.fnum;
698         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
699
700         torture_comment(tctx, "rename should not generate a break but get a "
701                         "sharing violation\n");
702         ZERO_STRUCT(rn);
703         rn.generic.level = RAW_RENAME_RENAME;
704         rn.rename.in.pattern1 = fname1;
705         rn.rename.in.pattern2 = fname2;
706         rn.rename.in.attrib = 0;
707
708         torture_comment(tctx, "trying rename while first file open\n");
709         status = smb_raw_rename(cli2->tree, &rn);
710
711         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
712         torture_wait_for_oplock_break(tctx);
713         CHECK_VAL(break_info.count, 0);
714         CHECK_VAL(break_info.failures, 0);
715
716         smbcli_close(cli1->tree, fnum);
717
718 done:
719         smb_raw_exit(cli1->session);
720         smb_raw_exit(cli2->session);
721         smbcli_deltree(cli1->tree, BASEDIR);
722         return ret;
723 }
724
725 /**
726  * Exclusive version of batch19
727  */
728 static bool test_raw_oplock_exclusive7(struct torture_context *tctx,
729     struct smbcli_state *cli1, struct smbcli_state *cli2)
730 {
731         const char *fname1 = BASEDIR "\\test_exclusiv6_1.dat";
732         const char *fname2 = BASEDIR "\\test_exclusiv6_2.dat";
733         const char *fname3 = BASEDIR "\\test_exclusiv6_3.dat";
734         NTSTATUS status;
735         bool ret = true;
736         union smb_open io;
737         union smb_fileinfo qfi;
738         union smb_setfileinfo sfi;
739         uint16_t fnum=0;
740         uint16_t fnum2 = 0;
741
742         if (!torture_setup_dir(cli1, BASEDIR)) {
743                 return false;
744         }
745
746         /* cleanup */
747         smbcli_unlink(cli1->tree, fname1);
748         smbcli_unlink(cli1->tree, fname2);
749         smbcli_unlink(cli1->tree, fname3);
750
751         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
752             cli1->tree);
753
754         /*
755           base ntcreatex parms
756         */
757         io.generic.level = RAW_OPEN_NTCREATEX;
758         io.ntcreatex.in.root_fid.fnum = 0;
759         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
760         io.ntcreatex.in.alloc_size = 0;
761         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
762         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
763             NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
764         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
765         io.ntcreatex.in.create_options = 0;
766         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
767         io.ntcreatex.in.security_flags = 0;
768         io.ntcreatex.in.fname = fname1;
769
770         torture_comment(tctx, "open a file with an exclusive oplock (share "
771             "mode: none)\n");
772         ZERO_STRUCT(break_info);
773         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
774                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
775         status = smb_raw_open(cli1->tree, tctx, &io);
776         CHECK_STATUS(tctx, status, NT_STATUS_OK);
777         fnum = io.ntcreatex.out.file.fnum;
778         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
779
780         torture_comment(tctx, "setpathinfo rename info should trigger a break "
781             "to none\n");
782         ZERO_STRUCT(sfi);
783         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
784         sfi.generic.in.file.path = fname1;
785         sfi.rename_information.in.overwrite     = 0;
786         sfi.rename_information.in.root_fid      = 0;
787         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
788
789         status = smb_raw_setpathinfo(cli2->tree, &sfi);
790         CHECK_STATUS(tctx, status, NT_STATUS_OK);
791
792         torture_wait_for_oplock_break(tctx);
793         CHECK_VAL(break_info.failures, 0);
794
795         if (TARGET_IS_WINXP(tctx) || TARGET_IS_W2K12(tctx)) {
796                 /* XP incorrectly breaks to level2. */
797                 CHECK_VAL(break_info.count, 1);
798                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
799         } else {
800                 /* Exclusive oplocks should not be broken on rename. */
801                 CHECK_VAL(break_info.failures, 0);
802                 CHECK_VAL(break_info.count, 0);
803         }
804
805         ZERO_STRUCT(qfi);
806         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
807         qfi.generic.in.file.fnum = fnum;
808
809         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
810         CHECK_STATUS(tctx, status, NT_STATUS_OK);
811         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
812
813         /* Try breaking to level2 and then see if rename breaks the level2.*/
814         ZERO_STRUCT(break_info);
815         io.ntcreatex.in.fname = fname2;
816         status = smb_raw_open(cli2->tree, tctx, &io);
817         CHECK_STATUS(tctx, status, NT_STATUS_OK);
818         fnum2 = io.ntcreatex.out.file.fnum;
819         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
820
821         torture_wait_for_oplock_break(tctx);
822         CHECK_VAL(break_info.failures, 0);
823
824         if (TARGET_IS_WINXP(tctx)) {
825                 /* XP already broke to level2. */
826                 CHECK_VAL(break_info.failures, 0);
827                 CHECK_VAL(break_info.count, 0);
828         } else if (TARGET_IS_W2K12(tctx)) {
829                 /* no break */
830                 CHECK_VAL(break_info.count, 0);
831                 CHECK_VAL(break_info.level, 0);
832         } else {
833                 /* Break to level 2 expected. */
834                 CHECK_VAL(break_info.count, 1);
835                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
836         }
837
838         ZERO_STRUCT(break_info);
839         sfi.generic.in.file.path = fname2;
840         sfi.rename_information.in.overwrite     = 0;
841         sfi.rename_information.in.root_fid      = 0;
842         sfi.rename_information.in.new_name      = fname1+strlen(BASEDIR)+1;
843
844         status = smb_raw_setpathinfo(cli2->tree, &sfi);
845         CHECK_STATUS(tctx, status, NT_STATUS_OK);
846
847         /* Level2 oplocks are not broken on rename. */
848         torture_wait_for_oplock_break(tctx);
849         CHECK_VAL(break_info.failures, 0);
850         CHECK_VAL(break_info.count, 0);
851
852         /* Close and re-open file with oplock. */
853         smbcli_close(cli1->tree, fnum);
854         status = smb_raw_open(cli1->tree, tctx, &io);
855         CHECK_STATUS(tctx, status, NT_STATUS_OK);
856         fnum = io.ntcreatex.out.file.fnum;
857         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
858
859         torture_comment(tctx, "setfileinfo rename info on a client's own fid "
860             "should not trigger a break nor a violation\n");
861         ZERO_STRUCT(break_info);
862         ZERO_STRUCT(sfi);
863         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
864         sfi.generic.in.file.fnum = fnum;
865         sfi.rename_information.in.overwrite     = 0;
866         sfi.rename_information.in.root_fid      = 0;
867         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
868
869         status = smb_raw_setfileinfo(cli1->tree, &sfi);
870         CHECK_STATUS(tctx, status, NT_STATUS_OK);
871
872         torture_wait_for_oplock_break(tctx);
873         if (TARGET_IS_WINXP(tctx)) {
874                 /* XP incorrectly breaks to level2. */
875                 CHECK_VAL(break_info.count, 1);
876                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
877         } else {
878                 CHECK_VAL(break_info.count, 0);
879         }
880
881         ZERO_STRUCT(qfi);
882         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
883         qfi.generic.in.file.fnum = fnum;
884
885         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
886         CHECK_STATUS(tctx, status, NT_STATUS_OK);
887         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
888
889 done:
890         smbcli_close(cli1->tree, fnum);
891         smbcli_close(cli2->tree, fnum2);
892
893         smb_raw_exit(cli1->session);
894         smb_raw_exit(cli2->session);
895         smbcli_deltree(cli1->tree, BASEDIR);
896         return ret;
897 }
898
899 static bool test_raw_oplock_exclusive8(struct torture_context *tctx,
900                                        struct smbcli_state *cli1,
901                                        struct smbcli_state *cli2)
902 {
903         const char *fname = BASEDIR "\\test_exclusive8.dat";
904         NTSTATUS status;
905         bool ret = true;
906         union smb_open io;
907         uint16_t fnum1 = 0;
908         uint16_t fnum2 = 0;
909         uint16_t fnum3 = 0;
910
911         if (!torture_setup_dir(cli1, BASEDIR)) {
912                 return false;
913         }
914
915         /* cleanup */
916         smbcli_unlink(cli1->tree, fname);
917
918         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
919                               cli1->tree);
920
921         /*
922           base ntcreatex parms
923         */
924         io.generic.level = RAW_OPEN_NTCREATEX;
925         io.ntcreatex.in.root_fid.fnum = 0;
926         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
927         io.ntcreatex.in.alloc_size = 0;
928         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
929         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
930                 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
931         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
932         io.ntcreatex.in.create_options = 0;
933         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
934         io.ntcreatex.in.security_flags = 0;
935         io.ntcreatex.in.fname = fname;
936
937         torture_comment(tctx, "open a file with an exclusive oplock (share "
938                         "mode: all)\n");
939         ZERO_STRUCT(break_info);
940         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
941                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
942         status = smb_raw_open(cli1->tree, tctx, &io);
943         CHECK_STATUS(tctx, status, NT_STATUS_OK);
944         fnum1 = io.ntcreatex.out.file.fnum;
945         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
946
947         torture_comment(tctx, "second open with delete should trigger a "
948                         "break\n");
949
950         io.ntcreatex.in.access_mask = SEC_STD_DELETE;
951         io.ntcreatex.in.flags = 0;
952         status = smb_raw_open(cli2->tree, tctx, &io);
953         CHECK_STATUS(tctx, status, NT_STATUS_OK);
954         fnum2 = io.ntcreatex.out.file.fnum;
955         CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
956         CHECK_VAL(break_info.failures, 0);
957         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
958
959         /* Trigger a little panic in "old" samba code.. */
960         status = smb_raw_open(cli2->tree, tctx, &io);
961         CHECK_STATUS(tctx, status, NT_STATUS_OK);
962         fnum3 = io.ntcreatex.out.file.fnum;
963
964         smbcli_close(cli2->tree, fnum3);
965         smbcli_close(cli2->tree, fnum2);
966         smbcli_close(cli1->tree, fnum1);
967
968 done:
969         smbcli_deltree(cli1->tree, BASEDIR);
970         smb_raw_exit(cli1->session);
971         smb_raw_exit(cli2->session);
972         return ret;
973 }
974
975 static bool test_raw_oplock_exclusive9(struct torture_context *tctx,
976                                        struct smbcli_state *cli1,
977                                        struct smbcli_state *cli2)
978 {
979         const char *fname = BASEDIR "\\test_exclusive9.dat";
980         NTSTATUS status;
981         bool ret = true;
982         union smb_open io;
983         uint16_t fnum=0, fnum2=0;
984         int i;
985
986         struct {
987                 uint32_t create_disposition;
988                 uint32_t break_level;
989         } levels[] = {
990                 { NTCREATEX_DISP_SUPERSEDE, OPLOCK_BREAK_TO_NONE },
991                 { NTCREATEX_DISP_OPEN, OPLOCK_BREAK_TO_LEVEL_II },
992                 { NTCREATEX_DISP_OVERWRITE_IF, OPLOCK_BREAK_TO_NONE },
993                 { NTCREATEX_DISP_OPEN_IF, OPLOCK_BREAK_TO_LEVEL_II },
994         };
995
996         if (!torture_setup_dir(cli1, BASEDIR)) {
997                 return false;
998         }
999
1000         /* cleanup */
1001         smbcli_unlink(cli1->tree, fname);
1002
1003         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
1004                               cli1->tree);
1005         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given,
1006                               cli1->tree);
1007
1008         /*
1009           base ntcreatex parms
1010         */
1011         io.generic.level = RAW_OPEN_NTCREATEX;
1012         io.ntcreatex.in.root_fid.fnum = 0;
1013         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1014         io.ntcreatex.in.alloc_size = 0;
1015         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1016         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1017         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1018         io.ntcreatex.in.create_options = 0;
1019         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1020         io.ntcreatex.in.security_flags = 0;
1021         io.ntcreatex.in.fname = fname;
1022
1023         ZERO_STRUCT(break_info);
1024         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
1025                               cli1->tree);
1026
1027         for (i=0; i<ARRAY_SIZE(levels); i++) {
1028
1029                 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1030                         NTCREATEX_FLAGS_REQUEST_OPLOCK;
1031                 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1032                         NTCREATEX_SHARE_ACCESS_WRITE|
1033                         NTCREATEX_SHARE_ACCESS_DELETE;
1034                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1035                 status = smb_raw_open(cli1->tree, tctx, &io);
1036                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1037                 fnum = io.ntcreatex.out.file.fnum;
1038                 CHECK_VAL(io.ntcreatex.out.oplock_level,
1039                           EXCLUSIVE_OPLOCK_RETURN);
1040
1041                 ZERO_STRUCT(break_info);
1042
1043                 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1044                         NTCREATEX_FLAGS_REQUEST_OPLOCK;
1045                 io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
1046                 io.ntcreatex.in.open_disposition =
1047                         levels[i].create_disposition;
1048                 status = smb_raw_open(cli2->tree, tctx, &io);
1049                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1050                 fnum2 = io.ntcreatex.out.file.fnum;
1051                 CHECK_VAL(io.ntcreatex.out.oplock_level,
1052                           LEVEL_II_OPLOCK_RETURN);
1053                 torture_wait_for_oplock_break(tctx);
1054                 CHECK_VAL(break_info.count, 1);
1055                 CHECK_VAL(break_info.level, levels[i].break_level);
1056                 CHECK_VAL(break_info.failures, 0);
1057
1058                 smbcli_close(cli1->tree, fnum);
1059                 smbcli_close(cli2->tree, fnum2);
1060         }
1061
1062 done:
1063         smb_raw_exit(cli1->session);
1064         smb_raw_exit(cli2->session);
1065         smbcli_deltree(cli1->tree, BASEDIR);
1066         return ret;
1067 }
1068
1069 static bool test_raw_oplock_level_ii_1(struct torture_context *tctx,
1070                                        struct smbcli_state *cli1,
1071                                        struct smbcli_state *cli2)
1072 {
1073         const char *fname = BASEDIR "\\test_level_ii_1.dat";
1074         NTSTATUS status;
1075         bool ret = true;
1076         union smb_open io;
1077         uint16_t fnum=0, fnum2=0;
1078         char c = 0;
1079         ssize_t written;
1080
1081         if (!torture_setup_dir(cli1, BASEDIR)) {
1082                 return false;
1083         }
1084
1085         /* cleanup */
1086         smbcli_unlink(cli1->tree, fname);
1087
1088         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
1089                               cli1->tree);
1090         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given,
1091                               cli1->tree);
1092
1093         /*
1094           base ntcreatex parms
1095         */
1096         io.generic.level = RAW_OPEN_NTCREATEX;
1097         io.ntcreatex.in.root_fid.fnum = 0;
1098         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1099         io.ntcreatex.in.alloc_size = 0;
1100         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1101         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1102         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1103         io.ntcreatex.in.create_options = 0;
1104         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1105         io.ntcreatex.in.security_flags = 0;
1106         io.ntcreatex.in.fname = fname;
1107
1108         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1109                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
1110         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1111                 NTCREATEX_SHARE_ACCESS_WRITE|
1112                 NTCREATEX_SHARE_ACCESS_DELETE;
1113         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1114         status = smb_raw_open(cli1->tree, tctx, &io);
1115         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1116         fnum = io.ntcreatex.out.file.fnum;
1117         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
1118
1119         ZERO_STRUCT(break_info);
1120
1121         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1122                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
1123         io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA;
1124         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1125         status = smb_raw_open(cli2->tree, tctx, &io);
1126         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1127         fnum2 = io.ntcreatex.out.file.fnum;
1128         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1129         torture_wait_for_oplock_break(tctx);
1130         CHECK_VAL(break_info.count, 1);
1131         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1132         CHECK_VAL(break_info.failures, 0);
1133
1134         status = smbcli_close(cli2->tree, fnum2);
1135         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1136
1137         /*
1138          * fnum1 has a level2 oplock now
1139          */
1140
1141         ZERO_STRUCT(break_info);
1142
1143         /*
1144          * Don't answer the break to none that will come in
1145          */
1146
1147         smbcli_oplock_handler(cli1->transport, oplock_handler_timeout,
1148                               cli1->tree);
1149
1150         io.ntcreatex.in.flags = 0;
1151         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1152
1153         status = smb_raw_open(cli2->tree, tctx, &io);
1154         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1155         fnum2 = io.ntcreatex.out.file.fnum;
1156         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1157         torture_wait_for_oplock_break(tctx);
1158         CHECK_VAL(break_info.count, 1);
1159         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
1160         CHECK_VAL(break_info.failures, 0);
1161
1162         /*
1163          * Check that a write does not cause another break. This used to be a
1164          * bug in smbd.
1165          */
1166
1167         ZERO_STRUCT(break_info);
1168         written = smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
1169         CHECK_VAL(written, 1);
1170         torture_wait_for_oplock_break(tctx);
1171         CHECK_VAL(break_info.count, 0);
1172         CHECK_VAL(break_info.failures, 0);
1173
1174         status = smbcli_close(cli2->tree, fnum2);
1175         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1176         status = smbcli_close(cli1->tree, fnum);
1177         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1178
1179 done:
1180         smb_raw_exit(cli1->session);
1181         smb_raw_exit(cli2->session);
1182         smbcli_deltree(cli1->tree, BASEDIR);
1183         return ret;
1184 }
1185
1186 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1187 {
1188         const char *fname = BASEDIR "\\test_batch1.dat";
1189         NTSTATUS status;
1190         bool ret = true;
1191         union smb_open io;
1192         union smb_unlink unl;
1193         uint16_t fnum=0;
1194         char c = 0;
1195
1196         if (!torture_setup_dir(cli1, BASEDIR)) {
1197                 return false;
1198         }
1199
1200         /* cleanup */
1201         smbcli_unlink(cli1->tree, fname);
1202
1203         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1204
1205         /*
1206           base ntcreatex parms
1207         */
1208         io.generic.level = RAW_OPEN_NTCREATEX;
1209         io.ntcreatex.in.root_fid.fnum = 0;
1210         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1211         io.ntcreatex.in.alloc_size = 0;
1212         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1213         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1214         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1215         io.ntcreatex.in.create_options = 0;
1216         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1217         io.ntcreatex.in.security_flags = 0;
1218         io.ntcreatex.in.fname = fname;
1219
1220         /*
1221           with a batch oplock we get a break
1222         */
1223         torture_comment(tctx, "BATCH1: open with batch oplock\n");
1224         ZERO_STRUCT(break_info);
1225         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1226                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1227                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1228         status = smb_raw_open(cli1->tree, tctx, &io);
1229         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1230         fnum = io.ntcreatex.out.file.fnum;
1231         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1232
1233         torture_comment(tctx, "unlink should generate a break\n");
1234         unl.unlink.in.pattern = fname;
1235         unl.unlink.in.attrib = 0;
1236         status = smb_raw_unlink(cli2->tree, &unl);
1237         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1238
1239         torture_wait_for_oplock_break(tctx);
1240         CHECK_VAL(break_info.count, 1);
1241         CHECK_VAL(break_info.fnum, fnum);
1242         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1243         CHECK_VAL(break_info.failures, 0);
1244
1245         torture_comment(tctx, "2nd unlink should not generate a break\n");
1246         ZERO_STRUCT(break_info);
1247         status = smb_raw_unlink(cli2->tree, &unl);
1248         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1249
1250         torture_wait_for_oplock_break(tctx);
1251         CHECK_VAL(break_info.count, 0);
1252
1253         torture_comment(tctx, "writing should generate a self break to none\n");
1254         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1255
1256         torture_wait_for_oplock_break(tctx);
1257         torture_wait_for_oplock_break(tctx);
1258         CHECK_VAL(break_info.count, 1);
1259         CHECK_VAL(break_info.fnum, fnum);
1260         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
1261         CHECK_VAL(break_info.failures, 0);
1262
1263         smbcli_close(cli1->tree, fnum);
1264
1265 done:
1266         smb_raw_exit(cli1->session);
1267         smb_raw_exit(cli2->session);
1268         smbcli_deltree(cli1->tree, BASEDIR);
1269         return ret;
1270 }
1271
1272 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1273 {
1274         const char *fname = BASEDIR "\\test_batch2.dat";
1275         NTSTATUS status;
1276         bool ret = true;
1277         union smb_open io;
1278         union smb_unlink unl;
1279         uint16_t fnum=0;
1280         char c = 0;
1281
1282         if (!torture_setup_dir(cli1, BASEDIR)) {
1283                 return false;
1284         }
1285
1286         /* cleanup */
1287         smbcli_unlink(cli1->tree, fname);
1288
1289         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1290
1291         /*
1292           base ntcreatex parms
1293         */
1294         io.generic.level = RAW_OPEN_NTCREATEX;
1295         io.ntcreatex.in.root_fid.fnum = 0;
1296         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1297         io.ntcreatex.in.alloc_size = 0;
1298         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1299         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1300         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1301         io.ntcreatex.in.create_options = 0;
1302         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1303         io.ntcreatex.in.security_flags = 0;
1304         io.ntcreatex.in.fname = fname;
1305
1306         torture_comment(tctx, "BATCH2: open with batch oplock\n");
1307         ZERO_STRUCT(break_info);
1308         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1309                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1310                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1311         status = smb_raw_open(cli1->tree, tctx, &io);
1312         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1313         fnum = io.ntcreatex.out.file.fnum;
1314         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1315
1316         torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
1317         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
1318         unl.unlink.in.pattern = fname;
1319         unl.unlink.in.attrib = 0;
1320         status = smb_raw_unlink(cli2->tree, &unl);
1321         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1322
1323         torture_wait_for_oplock_break(tctx);
1324         CHECK_VAL(break_info.count, 1);
1325         CHECK_VAL(break_info.fnum, fnum);
1326         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1327         CHECK_VAL(break_info.failures, 0);
1328
1329         torture_comment(tctx, "2nd unlink should not generate a break\n");
1330         ZERO_STRUCT(break_info);
1331         status = smb_raw_unlink(cli2->tree, &unl);
1332         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1333
1334         torture_wait_for_oplock_break(tctx);
1335         CHECK_VAL(break_info.count, 0);
1336
1337         torture_comment(tctx, "writing should not generate a break\n");
1338         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1339
1340         torture_wait_for_oplock_break(tctx);
1341         CHECK_VAL(break_info.count, 0);
1342
1343         smbcli_close(cli1->tree, fnum);
1344
1345 done:
1346         smb_raw_exit(cli1->session);
1347         smb_raw_exit(cli2->session);
1348         smbcli_deltree(cli1->tree, BASEDIR);
1349         return ret;
1350 }
1351
1352 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1353 {
1354         const char *fname = BASEDIR "\\test_batch3.dat";
1355         NTSTATUS status;
1356         bool ret = true;
1357         union smb_open io;
1358         union smb_unlink unl;
1359         uint16_t fnum=0;
1360
1361         if (!torture_setup_dir(cli1, BASEDIR)) {
1362                 return false;
1363         }
1364
1365         /* cleanup */
1366         smbcli_unlink(cli1->tree, fname);
1367
1368         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1369
1370         /*
1371           base ntcreatex parms
1372         */
1373         io.generic.level = RAW_OPEN_NTCREATEX;
1374         io.ntcreatex.in.root_fid.fnum = 0;
1375         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1376         io.ntcreatex.in.alloc_size = 0;
1377         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1378         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1379         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1380         io.ntcreatex.in.create_options = 0;
1381         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1382         io.ntcreatex.in.security_flags = 0;
1383         io.ntcreatex.in.fname = fname;
1384
1385         torture_comment(tctx, "BATCH3: if we close on break then the unlink can succeed\n");
1386         ZERO_STRUCT(break_info);
1387         smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1388         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1389                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1390                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1391         status = smb_raw_open(cli1->tree, tctx, &io);
1392         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1393         fnum = io.ntcreatex.out.file.fnum;
1394         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1395
1396         unl.unlink.in.pattern = fname;
1397         unl.unlink.in.attrib = 0;
1398         ZERO_STRUCT(break_info);
1399         status = smb_raw_unlink(cli2->tree, &unl);
1400         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1401
1402         torture_wait_for_oplock_break(tctx);
1403         CHECK_VAL(break_info.count, 1);
1404         CHECK_VAL(break_info.fnum, fnum);
1405         CHECK_VAL(break_info.level, 1);
1406         CHECK_VAL(break_info.failures, 0);
1407
1408         smbcli_close(cli1->tree, fnum);
1409
1410 done:
1411         smb_raw_exit(cli1->session);
1412         smb_raw_exit(cli2->session);
1413         smbcli_deltree(cli1->tree, BASEDIR);
1414         return ret;
1415 }
1416
1417 static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1418 {
1419         const char *fname = BASEDIR "\\test_batch4.dat";
1420         NTSTATUS status;
1421         bool ret = true;
1422         union smb_open io;
1423         union smb_read rd;
1424         uint16_t fnum=0;
1425
1426         if (!torture_setup_dir(cli1, BASEDIR)) {
1427                 return false;
1428         }
1429
1430         /* cleanup */
1431         smbcli_unlink(cli1->tree, fname);
1432
1433         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1434
1435         /*
1436           base ntcreatex parms
1437         */
1438         io.generic.level = RAW_OPEN_NTCREATEX;
1439         io.ntcreatex.in.root_fid.fnum = 0;
1440         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1441         io.ntcreatex.in.alloc_size = 0;
1442         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1443         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1444         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1445         io.ntcreatex.in.create_options = 0;
1446         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1447         io.ntcreatex.in.security_flags = 0;
1448         io.ntcreatex.in.fname = fname;
1449
1450         torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
1451         ZERO_STRUCT(break_info);
1452         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1453
1454         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1455                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1456                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1457         status = smb_raw_open(cli1->tree, tctx, &io);
1458         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1459         fnum = io.ntcreatex.out.file.fnum;
1460         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1461
1462         rd.readx.level = RAW_READ_READX;
1463         rd.readx.in.file.fnum = fnum;
1464         rd.readx.in.mincnt = 1;
1465         rd.readx.in.maxcnt = 1;
1466         rd.readx.in.offset = 0;
1467         rd.readx.in.remaining = 0;
1468         rd.readx.in.read_for_execute = false;
1469         status = smb_raw_read(cli1->tree, &rd);
1470         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1471         torture_wait_for_oplock_break(tctx);
1472         CHECK_VAL(break_info.count, 0);
1473         CHECK_VAL(break_info.failures, 0);
1474
1475         smbcli_close(cli1->tree, fnum);
1476
1477 done:
1478         smb_raw_exit(cli1->session);
1479         smb_raw_exit(cli2->session);
1480         smbcli_deltree(cli1->tree, BASEDIR);
1481         return ret;
1482 }
1483
1484 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1485 {
1486         const char *fname = BASEDIR "\\test_batch5.dat";
1487         NTSTATUS status;
1488         bool ret = true;
1489         union smb_open io;
1490         uint16_t fnum=0;
1491
1492         if (!torture_setup_dir(cli1, BASEDIR)) {
1493                 return false;
1494         }
1495
1496         /* cleanup */
1497         smbcli_unlink(cli1->tree, fname);
1498
1499         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1500
1501         /*
1502           base ntcreatex parms
1503         */
1504         io.generic.level = RAW_OPEN_NTCREATEX;
1505         io.ntcreatex.in.root_fid.fnum = 0;
1506         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1507         io.ntcreatex.in.alloc_size = 0;
1508         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1509         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1510         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1511         io.ntcreatex.in.create_options = 0;
1512         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1513         io.ntcreatex.in.security_flags = 0;
1514         io.ntcreatex.in.fname = fname;
1515
1516         torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1517         ZERO_STRUCT(break_info);
1518         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1519
1520         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1521                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1522                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1523         status = smb_raw_open(cli1->tree, tctx, &io);
1524         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1525         fnum = io.ntcreatex.out.file.fnum;
1526         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1527
1528         ZERO_STRUCT(break_info);
1529
1530         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1531         status = smb_raw_open(cli2->tree, tctx, &io);
1532         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1533
1534         torture_wait_for_oplock_break(tctx);
1535         CHECK_VAL(break_info.count, 1);
1536         CHECK_VAL(break_info.fnum, fnum);
1537         CHECK_VAL(break_info.level, 1);
1538         CHECK_VAL(break_info.failures, 0);
1539
1540         smbcli_close(cli1->tree, fnum);
1541
1542 done:
1543         smb_raw_exit(cli1->session);
1544         smb_raw_exit(cli2->session);
1545         smbcli_deltree(cli1->tree, BASEDIR);
1546         return ret;
1547 }
1548
1549 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1550 {
1551         const char *fname = BASEDIR "\\test_batch6.dat";
1552         NTSTATUS status;
1553         bool ret = true;
1554         union smb_open io;
1555         uint16_t fnum=0, fnum2=0;
1556         char c = 0;
1557
1558         if (!torture_setup_dir(cli1, BASEDIR)) {
1559                 return false;
1560         }
1561
1562         /* cleanup */
1563         smbcli_unlink(cli1->tree, fname);
1564
1565         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1566         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1567
1568         /*
1569           base ntcreatex parms
1570         */
1571         io.generic.level = RAW_OPEN_NTCREATEX;
1572         io.ntcreatex.in.root_fid.fnum = 0;
1573         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1574         io.ntcreatex.in.alloc_size = 0;
1575         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1576         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1577         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1578         io.ntcreatex.in.create_options = 0;
1579         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1580         io.ntcreatex.in.security_flags = 0;
1581         io.ntcreatex.in.fname = fname;
1582
1583         torture_comment(tctx, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1584         ZERO_STRUCT(break_info);
1585
1586         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
1587         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1588         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1589                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1590                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1591         status = smb_raw_open(cli1->tree, tctx, &io);
1592         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1593         fnum = io.ntcreatex.out.file.fnum;
1594         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1595
1596         ZERO_STRUCT(break_info);
1597
1598         status = smb_raw_open(cli2->tree, tctx, &io);
1599         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1600         fnum2 = io.ntcreatex.out.file.fnum;
1601         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1602
1603         //torture_wait_for_oplock_break(tctx);
1604         CHECK_VAL(break_info.count, 1);
1605         CHECK_VAL(break_info.fnum, fnum);
1606         CHECK_VAL(break_info.level, 1);
1607         CHECK_VAL(break_info.failures, 0);
1608         ZERO_STRUCT(break_info);
1609
1610         torture_comment(tctx, "write should trigger a break to none on both\n");
1611         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1612
1613         /* We expect two breaks */
1614         torture_wait_for_oplock_break(tctx);
1615         torture_wait_for_oplock_break(tctx);
1616
1617         CHECK_VAL(break_info.count, 2);
1618         CHECK_VAL(break_info.level, 0);
1619         CHECK_VAL(break_info.failures, 0);
1620
1621         smbcli_close(cli1->tree, fnum);
1622         smbcli_close(cli2->tree, fnum2);
1623
1624 done:
1625         smb_raw_exit(cli1->session);
1626         smb_raw_exit(cli2->session);
1627         smbcli_deltree(cli1->tree, BASEDIR);
1628         return ret;
1629 }
1630
1631 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1632 {
1633         const char *fname = BASEDIR "\\test_batch7.dat";
1634         NTSTATUS status;
1635         bool ret = true;
1636         union smb_open io;
1637         uint16_t fnum=0, fnum2=0;
1638
1639         if (!torture_setup_dir(cli1, BASEDIR)) {
1640                 return false;
1641         }
1642
1643         /* cleanup */
1644         smbcli_unlink(cli1->tree, fname);
1645
1646         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1647
1648         /*
1649           base ntcreatex parms
1650         */
1651         io.generic.level = RAW_OPEN_NTCREATEX;
1652         io.ntcreatex.in.root_fid.fnum = 0;
1653         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1654         io.ntcreatex.in.alloc_size = 0;
1655         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1656         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1657         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1658         io.ntcreatex.in.create_options = 0;
1659         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1660         io.ntcreatex.in.security_flags = 0;
1661         io.ntcreatex.in.fname = fname;
1662
1663         torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1664         ZERO_STRUCT(break_info);
1665         smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1666
1667         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1668         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1669         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1670                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1671                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1672         status = smb_raw_open(cli1->tree, tctx, &io);
1673         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1674         fnum2 = io.ntcreatex.out.file.fnum;
1675         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1676
1677         ZERO_STRUCT(break_info);
1678
1679         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1680                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1681                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1682         status = smb_raw_open(cli2->tree, tctx, &io);
1683         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1684         fnum = io.ntcreatex.out.file.fnum;
1685         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1686
1687         torture_wait_for_oplock_break(tctx);
1688         CHECK_VAL(break_info.count, 1);
1689         CHECK_VAL(break_info.fnum, fnum2);
1690         CHECK_VAL(break_info.level, 1);
1691         CHECK_VAL(break_info.failures, 0);
1692
1693         smbcli_close(cli2->tree, fnum);
1694
1695 done:
1696         smb_raw_exit(cli1->session);
1697         smb_raw_exit(cli2->session);
1698         smbcli_deltree(cli1->tree, BASEDIR);
1699         return ret;
1700 }
1701
1702 static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1703 {
1704         const char *fname = BASEDIR "\\test_batch8.dat";
1705         NTSTATUS status;
1706         bool ret = true;
1707         union smb_open io;
1708         uint16_t fnum=0, fnum2=0;
1709
1710         if (!torture_setup_dir(cli1, BASEDIR)) {
1711                 return false;
1712         }
1713
1714         /* cleanup */
1715         smbcli_unlink(cli1->tree, fname);
1716
1717         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1718
1719         /*
1720           base ntcreatex parms
1721         */
1722         io.generic.level = RAW_OPEN_NTCREATEX;
1723         io.ntcreatex.in.root_fid.fnum = 0;
1724         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1725         io.ntcreatex.in.alloc_size = 0;
1726         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1727         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1728         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1729         io.ntcreatex.in.create_options = 0;
1730         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1731         io.ntcreatex.in.security_flags = 0;
1732         io.ntcreatex.in.fname = fname;
1733
1734         torture_comment(tctx, "BATCH8: open with batch oplock\n");
1735         ZERO_STRUCT(break_info);
1736         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1737
1738         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1739                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1740                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1741         status = smb_raw_open(cli1->tree, tctx, &io);
1742         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1743         fnum = io.ntcreatex.out.file.fnum;
1744         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1745
1746         ZERO_STRUCT(break_info);
1747         torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
1748
1749         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1750                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1751                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1752         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1753         status = smb_raw_open(cli2->tree, tctx, &io);
1754         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1755         fnum2 = io.ntcreatex.out.file.fnum;
1756         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1757         torture_wait_for_oplock_break(tctx);
1758         CHECK_VAL(break_info.count, 0);
1759         CHECK_VAL(break_info.failures, 0);
1760
1761         smbcli_close(cli1->tree, fnum);
1762         smbcli_close(cli2->tree, fnum2);
1763
1764 done:
1765         smb_raw_exit(cli1->session);
1766         smb_raw_exit(cli2->session);
1767         smbcli_deltree(cli1->tree, BASEDIR);
1768         return ret;
1769 }
1770
1771 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1772 {
1773         const char *fname = BASEDIR "\\test_batch9.dat";
1774         NTSTATUS status;
1775         bool ret = true;
1776         union smb_open io;
1777         uint16_t fnum=0, fnum2=0;
1778         char c = 0;
1779
1780         if (!torture_setup_dir(cli1, BASEDIR)) {
1781                 return false;
1782         }
1783
1784         /* cleanup */
1785         smbcli_unlink(cli1->tree, fname);
1786
1787         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1788
1789         /*
1790           base ntcreatex parms
1791         */
1792         io.generic.level = RAW_OPEN_NTCREATEX;
1793         io.ntcreatex.in.root_fid.fnum = 0;
1794         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1795         io.ntcreatex.in.alloc_size = 0;
1796         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1797         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1798         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1799         io.ntcreatex.in.create_options = 0;
1800         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1801         io.ntcreatex.in.security_flags = 0;
1802         io.ntcreatex.in.fname = fname;
1803
1804         torture_comment(tctx, "BATCH9: open with attributes only can create file\n");
1805
1806         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1807                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1808                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1809         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1810         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1811         status = smb_raw_open(cli1->tree, tctx, &io);
1812         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1813         fnum = io.ntcreatex.out.file.fnum;
1814         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1815
1816         torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
1817
1818         ZERO_STRUCT(break_info);
1819         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1820
1821         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1822                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1823                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1824         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1825         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1826         status = smb_raw_open(cli2->tree, tctx, &io);
1827         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1828         fnum2 = io.ntcreatex.out.file.fnum;
1829         torture_wait_for_oplock_break(tctx);
1830         CHECK_VAL(break_info.count, 1);
1831         CHECK_VAL(break_info.fnum, fnum);
1832         CHECK_VAL(break_info.failures, 0);
1833         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1834         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1835         smbcli_close(cli2->tree, fnum2);
1836
1837         torture_comment(tctx, "third oplocked open should grant level2 without break\n");
1838         ZERO_STRUCT(break_info);
1839         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1840         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1841         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1842                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1843                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1844         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1845         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1846         status = smb_raw_open(cli2->tree, tctx, &io);
1847         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1848         fnum2 = io.ntcreatex.out.file.fnum;
1849         torture_wait_for_oplock_break(tctx);
1850         CHECK_VAL(break_info.count, 0);
1851         CHECK_VAL(break_info.failures, 0);
1852         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1853
1854         ZERO_STRUCT(break_info);
1855
1856         torture_comment(tctx, "write should trigger a break to none on both\n");
1857         smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
1858
1859         /* We expect two breaks */
1860         torture_wait_for_oplock_break(tctx);
1861         torture_wait_for_oplock_break(tctx);
1862
1863         CHECK_VAL(break_info.count, 2);
1864         CHECK_VAL(break_info.level, 0);
1865         CHECK_VAL(break_info.failures, 0);
1866
1867         smbcli_close(cli1->tree, fnum);
1868         smbcli_close(cli2->tree, fnum2);
1869
1870 done:
1871         smb_raw_exit(cli1->session);
1872         smb_raw_exit(cli2->session);
1873         smbcli_deltree(cli1->tree, BASEDIR);
1874         return ret;
1875 }
1876
1877 static bool test_raw_oplock_batch9a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1878 {
1879         const char *fname = BASEDIR "\\test_batch9a.dat";
1880         NTSTATUS status;
1881         bool ret = true;
1882         union smb_open io;
1883         uint16_t fnum=0, fnum2=0;
1884         char c = 0;
1885
1886         if (!torture_setup_dir(cli1, BASEDIR)) {
1887                 return false;
1888         }
1889
1890         /* cleanup */
1891         smbcli_unlink(cli1->tree, fname);
1892
1893         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1894
1895         /*
1896           base ntcreatex parms
1897         */
1898         io.generic.level = RAW_OPEN_NTCREATEX;
1899         io.ntcreatex.in.root_fid.fnum = 0;
1900         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1901         io.ntcreatex.in.alloc_size = 0;
1902         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1903         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1904         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1905         io.ntcreatex.in.create_options = 0;
1906         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1907         io.ntcreatex.in.security_flags = 0;
1908         io.ntcreatex.in.fname = fname;
1909
1910         torture_comment(tctx, "BATCH9: open with attributes only can create file\n");
1911
1912         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1913                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1914                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1915         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1916         status = smb_raw_open(cli1->tree, tctx, &io);
1917         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1918         fnum = io.ntcreatex.out.file.fnum;
1919         CHECK_VAL(io.ntcreatex.out.create_action, FILE_WAS_CREATED);
1920         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1921
1922         torture_comment(tctx, "Subsequent attributes open should not break\n");
1923
1924         ZERO_STRUCT(break_info);
1925         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1926
1927         status = smb_raw_open(cli2->tree, tctx, &io);
1928         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1929         fnum2 = io.ntcreatex.out.file.fnum;
1930         torture_wait_for_oplock_break(tctx);
1931         CHECK_VAL(break_info.count, 0);
1932         CHECK_VAL(io.ntcreatex.out.create_action, FILE_WAS_OPENED);
1933         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1934         smbcli_close(cli2->tree, fnum2);
1935
1936         torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
1937
1938         ZERO_STRUCT(break_info);
1939         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1940
1941         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1942                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1943                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1944         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1945         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1946         status = smb_raw_open(cli2->tree, tctx, &io);
1947         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1948         fnum2 = io.ntcreatex.out.file.fnum;
1949         torture_wait_for_oplock_break(tctx);
1950         CHECK_VAL(break_info.count, 1);
1951         CHECK_VAL(break_info.fnum, fnum);
1952         CHECK_VAL(break_info.failures, 0);
1953         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1954         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1955         smbcli_close(cli2->tree, fnum2);
1956
1957         torture_comment(tctx, "third oplocked open should grant level2 without break\n");
1958         ZERO_STRUCT(break_info);
1959         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1960         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1961         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1962                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1963                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1964         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1965         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1966         status = smb_raw_open(cli2->tree, tctx, &io);
1967         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1968         fnum2 = io.ntcreatex.out.file.fnum;
1969         torture_wait_for_oplock_break(tctx);
1970         CHECK_VAL(break_info.count, 0);
1971         CHECK_VAL(break_info.failures, 0);
1972         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1973
1974         ZERO_STRUCT(break_info);
1975
1976         torture_comment(tctx, "write should trigger a break to none on both\n");
1977         smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
1978
1979         /* We expect two breaks */
1980         torture_wait_for_oplock_break(tctx);
1981         torture_wait_for_oplock_break(tctx);
1982
1983         CHECK_VAL(break_info.count, 2);
1984         CHECK_VAL(break_info.level, 0);
1985         CHECK_VAL(break_info.failures, 0);
1986
1987         smbcli_close(cli1->tree, fnum);
1988         smbcli_close(cli2->tree, fnum2);
1989
1990 done:
1991         smb_raw_exit(cli1->session);
1992         smb_raw_exit(cli2->session);
1993         smbcli_deltree(cli1->tree, BASEDIR);
1994         return ret;
1995 }
1996
1997 static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1998 {
1999         const char *fname = BASEDIR "\\test_batch10.dat";
2000         NTSTATUS status;
2001         bool ret = true;
2002         union smb_open io;
2003         uint16_t fnum=0, fnum2=0;
2004
2005         if (!torture_setup_dir(cli1, BASEDIR)) {
2006                 return false;
2007         }
2008
2009         /* cleanup */
2010         smbcli_unlink(cli1->tree, fname);
2011
2012         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2013
2014         /*
2015           base ntcreatex parms
2016         */
2017         io.generic.level = RAW_OPEN_NTCREATEX;
2018         io.ntcreatex.in.root_fid.fnum = 0;
2019         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2020         io.ntcreatex.in.alloc_size = 0;
2021         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2022         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2023         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2024         io.ntcreatex.in.create_options = 0;
2025         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2026         io.ntcreatex.in.security_flags = 0;
2027         io.ntcreatex.in.fname = fname;
2028
2029         torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
2030         ZERO_STRUCT(break_info);
2031         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
2032         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2033         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2034                 NTCREATEX_SHARE_ACCESS_WRITE|
2035                 NTCREATEX_SHARE_ACCESS_DELETE;
2036         status = smb_raw_open(cli1->tree, tctx, &io);
2037         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2038         fnum = io.ntcreatex.out.file.fnum;
2039         torture_wait_for_oplock_break(tctx);
2040         CHECK_VAL(break_info.count, 0);
2041         CHECK_VAL(break_info.failures, 0);
2042         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
2043
2044         {
2045                 union smb_write wr;
2046                 wr.write.level = RAW_WRITE_WRITE;
2047                 wr.write.in.file.fnum = fnum;
2048                 wr.write.in.count = 1;
2049                 wr.write.in.offset = 0;
2050                 wr.write.in.remaining = 0;
2051                 wr.write.in.data = (const uint8_t *)"x";
2052                 status = smb_raw_write(cli1->tree, &wr);
2053                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2054         }
2055
2056         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2057
2058         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2059                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
2060                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2061         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2062         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2063                 NTCREATEX_SHARE_ACCESS_WRITE|
2064                 NTCREATEX_SHARE_ACCESS_DELETE;
2065         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2066         status = smb_raw_open(cli2->tree, tctx, &io);
2067         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2068         fnum2 = io.ntcreatex.out.file.fnum;
2069         torture_wait_for_oplock_break(tctx);
2070         CHECK_VAL(break_info.count, 0);
2071         CHECK_VAL(break_info.failures, 0);
2072         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2073
2074         torture_comment(tctx, "write should trigger a break to none\n");
2075         {
2076                 union smb_write wr;
2077                 wr.write.level = RAW_WRITE_WRITE;
2078                 wr.write.in.file.fnum = fnum;
2079                 wr.write.in.count = 1;
2080                 wr.write.in.offset = 0;
2081                 wr.write.in.remaining = 0;
2082                 wr.write.in.data = (const uint8_t *)"x";
2083                 status = smb_raw_write(cli1->tree, &wr);
2084                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2085         }
2086
2087         torture_wait_for_oplock_break(tctx);
2088
2089         CHECK_VAL(break_info.count, 1);
2090         CHECK_VAL(break_info.fnum, fnum2);
2091         CHECK_VAL(break_info.level, 0);
2092         CHECK_VAL(break_info.failures, 0);
2093
2094         smbcli_close(cli1->tree, fnum);
2095         smbcli_close(cli2->tree, fnum2);
2096
2097 done:
2098         smb_raw_exit(cli1->session);
2099         smb_raw_exit(cli2->session);
2100         smbcli_deltree(cli1->tree, BASEDIR);
2101         return ret;
2102 }
2103
2104 static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2105 {
2106         const char *fname = BASEDIR "\\test_batch11.dat";
2107         NTSTATUS status;
2108         bool ret = true;
2109         union smb_open io;
2110         union smb_setfileinfo sfi;
2111         uint16_t fnum=0;
2112
2113         if (!torture_setup_dir(cli1, BASEDIR)) {
2114                 return false;
2115         }
2116
2117         /* cleanup */
2118         smbcli_unlink(cli1->tree, fname);
2119
2120         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2121
2122         /*
2123           base ntcreatex parms
2124         */
2125         io.generic.level = RAW_OPEN_NTCREATEX;
2126         io.ntcreatex.in.root_fid.fnum = 0;
2127         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2128         io.ntcreatex.in.alloc_size = 0;
2129         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2130         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
2131         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2132         io.ntcreatex.in.create_options = 0;
2133         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2134         io.ntcreatex.in.security_flags = 0;
2135         io.ntcreatex.in.fname = fname;
2136
2137         /* Test if a set-eof on pathname breaks an exclusive oplock. */
2138         torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
2139
2140         ZERO_STRUCT(break_info);
2141
2142         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2143                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2144                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2145         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2146         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2147                 NTCREATEX_SHARE_ACCESS_WRITE|
2148                 NTCREATEX_SHARE_ACCESS_DELETE;
2149         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2150         status = smb_raw_open(cli1->tree, tctx, &io);
2151         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2152         fnum = io.ntcreatex.out.file.fnum;
2153         torture_wait_for_oplock_break(tctx);
2154         CHECK_VAL(break_info.count, 0);
2155         CHECK_VAL(break_info.failures, 0);
2156         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2157
2158         ZERO_STRUCT(sfi);
2159         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
2160         sfi.generic.in.file.path = fname;
2161         sfi.end_of_file_info.in.size = 100;
2162
2163         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2164         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2165
2166         torture_wait_for_oplock_break(tctx);
2167         CHECK_VAL(break_info.count, get_setinfo_break_count(tctx));
2168         CHECK_VAL(break_info.failures, 0);
2169         CHECK_VAL(break_info.level, 0);
2170
2171         smbcli_close(cli1->tree, fnum);
2172
2173 done:
2174         smb_raw_exit(cli1->session);
2175         smb_raw_exit(cli2->session);
2176         smbcli_deltree(cli1->tree, BASEDIR);
2177         return ret;
2178 }
2179
2180 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2181 {
2182         const char *fname = BASEDIR "\\test_batch12.dat";
2183         NTSTATUS status;
2184         bool ret = true;
2185         union smb_open io;
2186         union smb_setfileinfo sfi;
2187         uint16_t fnum=0;
2188
2189         if (!torture_setup_dir(cli1, BASEDIR)) {
2190                 return false;
2191         }
2192
2193         /* cleanup */
2194         smbcli_unlink(cli1->tree, fname);
2195
2196         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2197
2198         /*
2199           base ntcreatex parms
2200         */
2201         io.generic.level = RAW_OPEN_NTCREATEX;
2202         io.ntcreatex.in.root_fid.fnum = 0;
2203         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2204         io.ntcreatex.in.alloc_size = 0;
2205         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2206         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2207         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2208         io.ntcreatex.in.create_options = 0;
2209         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2210         io.ntcreatex.in.security_flags = 0;
2211         io.ntcreatex.in.fname = fname;
2212
2213         /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
2214         torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
2215
2216         ZERO_STRUCT(break_info);
2217         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2218
2219         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2220                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2221                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2222         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2223         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2224                 NTCREATEX_SHARE_ACCESS_WRITE|
2225                 NTCREATEX_SHARE_ACCESS_DELETE;
2226         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2227         status = smb_raw_open(cli1->tree, tctx, &io);
2228         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2229         fnum = io.ntcreatex.out.file.fnum;
2230         torture_wait_for_oplock_break(tctx);
2231         CHECK_VAL(break_info.count, 0);
2232         CHECK_VAL(break_info.failures, 0);
2233         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2234
2235         ZERO_STRUCT(sfi);
2236         sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
2237         sfi.generic.in.file.path = fname;
2238         sfi.allocation_info.in.alloc_size = 65536 * 8;
2239
2240         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2241         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2242
2243         torture_wait_for_oplock_break(tctx);
2244         CHECK_VAL(break_info.count, get_setinfo_break_count(tctx));
2245         CHECK_VAL(break_info.failures, 0);
2246         CHECK_VAL(break_info.level, 0);
2247
2248         smbcli_close(cli1->tree, fnum);
2249
2250 done:
2251         smb_raw_exit(cli1->session);
2252         smb_raw_exit(cli2->session);
2253         smbcli_deltree(cli1->tree, BASEDIR);
2254         return ret;
2255 }
2256
2257 static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2258 {
2259         const char *fname = BASEDIR "\\test_batch13.dat";
2260         NTSTATUS status;
2261         bool ret = true;
2262         union smb_open io;
2263         uint16_t fnum=0, fnum2=0;
2264
2265         if (!torture_setup_dir(cli1, BASEDIR)) {
2266                 return false;
2267         }
2268
2269         /* cleanup */
2270         smbcli_unlink(cli1->tree, fname);
2271
2272         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2273         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
2274
2275         /*
2276           base ntcreatex parms
2277         */
2278         io.generic.level = RAW_OPEN_NTCREATEX;
2279         io.ntcreatex.in.root_fid.fnum = 0;
2280         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2281         io.ntcreatex.in.alloc_size = 0;
2282         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2283         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2284         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2285         io.ntcreatex.in.create_options = 0;
2286         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2287         io.ntcreatex.in.security_flags = 0;
2288         io.ntcreatex.in.fname = fname;
2289
2290         torture_comment(tctx, "BATCH13: open with batch oplock\n");
2291         ZERO_STRUCT(break_info);
2292
2293         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
2294                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
2295                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2296         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2297                 NTCREATEX_SHARE_ACCESS_WRITE|
2298                 NTCREATEX_SHARE_ACCESS_DELETE;
2299         status = smb_raw_open(cli1->tree, tctx, &io);
2300         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2301         fnum = io.ntcreatex.out.file.fnum;
2302         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2303
2304         ZERO_STRUCT(break_info);
2305
2306         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
2307
2308         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
2309                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
2310                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2311         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
2312         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2313                 NTCREATEX_SHARE_ACCESS_WRITE|
2314                 NTCREATEX_SHARE_ACCESS_DELETE;
2315         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
2316         status = smb_raw_open(cli2->tree, tctx, &io);
2317         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2318         fnum2 = io.ntcreatex.out.file.fnum;
2319         torture_wait_for_oplock_break(tctx);
2320         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2321         CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
2322         CHECK_VAL(break_info.failures, 0);
2323
2324         smbcli_close(cli1->tree, fnum);
2325         smbcli_close(cli2->tree, fnum2);
2326
2327 done:
2328         smb_raw_exit(cli1->session);
2329         smb_raw_exit(cli2->session);
2330         smbcli_deltree(cli1->tree, BASEDIR);
2331         return ret;
2332 }
2333
2334 static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2335 {
2336         const char *fname = BASEDIR "\\test_batch14.dat";
2337         NTSTATUS status;
2338         bool ret = true;
2339         union smb_open io;
2340         uint16_t fnum=0, fnum2=0;
2341
2342         if (!torture_setup_dir(cli1, BASEDIR)) {
2343                 return false;
2344         }
2345
2346         /* cleanup */
2347         smbcli_unlink(cli1->tree, fname);
2348
2349         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2350
2351         /*
2352           base ntcreatex parms
2353         */
2354         io.generic.level = RAW_OPEN_NTCREATEX;
2355         io.ntcreatex.in.root_fid.fnum = 0;
2356         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2357         io.ntcreatex.in.alloc_size = 0;
2358         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2359         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2360         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2361         io.ntcreatex.in.create_options = 0;
2362         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2363         io.ntcreatex.in.security_flags = 0;
2364         io.ntcreatex.in.fname = fname;
2365
2366         torture_comment(tctx, "BATCH14: open with batch oplock\n");
2367         ZERO_STRUCT(break_info);
2368
2369         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
2370                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
2371                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2372         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2373                 NTCREATEX_SHARE_ACCESS_WRITE|
2374                 NTCREATEX_SHARE_ACCESS_DELETE;
2375         status = smb_raw_open(cli1->tree, tctx, &io);
2376         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2377         fnum = io.ntcreatex.out.file.fnum;
2378         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2379
2380         ZERO_STRUCT(break_info);
2381
2382         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
2383
2384         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
2385                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
2386                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2387         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
2388         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2389                 NTCREATEX_SHARE_ACCESS_WRITE|
2390                 NTCREATEX_SHARE_ACCESS_DELETE;
2391         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
2392         status = smb_raw_open(cli2->tree, tctx, &io);
2393         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2394         fnum2 = io.ntcreatex.out.file.fnum;
2395         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2396
2397         torture_wait_for_oplock_break(tctx);
2398         CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
2399         CHECK_VAL(break_info.failures, 0);
2400
2401         smbcli_close(cli1->tree, fnum);
2402         smbcli_close(cli2->tree, fnum2);
2403 done:
2404         smb_raw_exit(cli1->session);
2405         smb_raw_exit(cli2->session);
2406         smbcli_deltree(cli1->tree, BASEDIR);
2407         return ret;
2408 }
2409
2410 static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2411 {
2412         const char *fname = BASEDIR "\\test_batch15.dat";
2413         NTSTATUS status;
2414         bool ret = true;
2415         union smb_open io;
2416         union smb_fileinfo qfi;
2417         uint16_t fnum=0;
2418
2419         if (!torture_setup_dir(cli1, BASEDIR)) {
2420                 return false;
2421         }
2422
2423         /* cleanup */
2424         smbcli_unlink(cli1->tree, fname);
2425
2426         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2427
2428         /*
2429           base ntcreatex parms
2430         */
2431         io.generic.level = RAW_OPEN_NTCREATEX;
2432         io.ntcreatex.in.root_fid.fnum = 0;
2433         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2434         io.ntcreatex.in.alloc_size = 0;
2435         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2436         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2437         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2438         io.ntcreatex.in.create_options = 0;
2439         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2440         io.ntcreatex.in.security_flags = 0;
2441         io.ntcreatex.in.fname = fname;
2442
2443         /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
2444         torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
2445
2446         ZERO_STRUCT(break_info);
2447
2448         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2449                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2450                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2451         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2452         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2453                 NTCREATEX_SHARE_ACCESS_WRITE|
2454                 NTCREATEX_SHARE_ACCESS_DELETE;
2455         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2456         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2457         status = smb_raw_open(cli1->tree, tctx, &io);
2458         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2459         fnum = io.ntcreatex.out.file.fnum;
2460
2461         torture_wait_for_oplock_break(tctx);
2462         CHECK_VAL(break_info.count, 0);
2463         CHECK_VAL(break_info.failures, 0);
2464         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2465
2466         ZERO_STRUCT(qfi);
2467         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2468         qfi.generic.in.file.path = fname;
2469
2470         status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
2471         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2472
2473         torture_wait_for_oplock_break(tctx);
2474         CHECK_VAL(break_info.count, 0);
2475
2476         smbcli_close(cli1->tree, fnum);
2477
2478 done:
2479         smb_raw_exit(cli1->session);
2480         smb_raw_exit(cli2->session);
2481         smbcli_deltree(cli1->tree, BASEDIR);
2482         return ret;
2483 }
2484
2485 static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2486 {
2487         const char *fname = BASEDIR "\\test_batch16.dat";
2488         NTSTATUS status;
2489         bool ret = true;
2490         union smb_open io;
2491         uint16_t fnum=0, fnum2=0;
2492
2493         if (!torture_setup_dir(cli1, BASEDIR)) {
2494                 return false;
2495         }
2496
2497         /* cleanup */
2498         smbcli_unlink(cli1->tree, fname);
2499
2500         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2501         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
2502
2503         /*
2504           base ntcreatex parms
2505         */
2506         io.generic.level = RAW_OPEN_NTCREATEX;
2507         io.ntcreatex.in.root_fid.fnum = 0;
2508         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2509         io.ntcreatex.in.alloc_size = 0;
2510         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2511         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2512         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2513         io.ntcreatex.in.create_options = 0;
2514         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2515         io.ntcreatex.in.security_flags = 0;
2516         io.ntcreatex.in.fname = fname;
2517
2518         torture_comment(tctx, "BATCH16: open with batch oplock\n");
2519         ZERO_STRUCT(break_info);
2520
2521         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2522                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2523                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2524         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2525                 NTCREATEX_SHARE_ACCESS_WRITE|
2526                 NTCREATEX_SHARE_ACCESS_DELETE;
2527         status = smb_raw_open(cli1->tree, tctx, &io);
2528         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2529         fnum = io.ntcreatex.out.file.fnum;
2530         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2531
2532         ZERO_STRUCT(break_info);
2533
2534         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
2535
2536         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2537                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2538                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2539         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
2540         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2541                 NTCREATEX_SHARE_ACCESS_WRITE|
2542                 NTCREATEX_SHARE_ACCESS_DELETE;
2543         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2544         status = smb_raw_open(cli2->tree, tctx, &io);
2545         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2546         fnum2 = io.ntcreatex.out.file.fnum;
2547         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2548
2549         torture_wait_for_oplock_break(tctx);
2550         CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
2551         CHECK_VAL(break_info.failures, 0);
2552
2553         smbcli_close(cli1->tree, fnum);
2554         smbcli_close(cli2->tree, fnum2);
2555
2556 done:
2557         smb_raw_exit(cli1->session);
2558         smb_raw_exit(cli2->session);
2559         smbcli_deltree(cli1->tree, BASEDIR);
2560         return ret;
2561 }
2562
2563 static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2564 {
2565         const char *fname1 = BASEDIR "\\test_batch17_1.dat";
2566         const char *fname2 = BASEDIR "\\test_batch17_2.dat";
2567         NTSTATUS status;
2568         bool ret = true;
2569         union smb_open io;
2570         union smb_rename rn;
2571         uint16_t fnum=0;
2572
2573         if (!torture_setup_dir(cli1, BASEDIR)) {
2574                 return false;
2575         }
2576
2577         /* cleanup */
2578         smbcli_unlink(cli1->tree, fname1);
2579         smbcli_unlink(cli1->tree, fname2);
2580
2581         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2582
2583         /*
2584           base ntcreatex parms
2585         */
2586         io.generic.level = RAW_OPEN_NTCREATEX;
2587         io.ntcreatex.in.root_fid.fnum = 0;
2588         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2589         io.ntcreatex.in.alloc_size = 0;
2590         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2591         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2592         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2593         io.ntcreatex.in.create_options = 0;
2594         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2595         io.ntcreatex.in.security_flags = 0;
2596         io.ntcreatex.in.fname = fname1;
2597
2598         torture_comment(tctx, "BATCH17: open a file with an batch oplock (share mode: none)\n");
2599
2600         ZERO_STRUCT(break_info);
2601         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2602                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2603                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2604
2605         status = smb_raw_open(cli1->tree, tctx, &io);
2606         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2607         fnum = io.ntcreatex.out.file.fnum;
2608         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2609
2610         torture_comment(tctx, "rename should trigger a break\n");
2611         ZERO_STRUCT(rn);
2612         rn.generic.level = RAW_RENAME_RENAME;
2613         rn.rename.in.pattern1 = fname1;
2614         rn.rename.in.pattern2 = fname2;
2615         rn.rename.in.attrib = 0;
2616
2617         torture_comment(tctx, "trying rename while first file open\n");
2618         status = smb_raw_rename(cli2->tree, &rn);
2619         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2620
2621         torture_wait_for_oplock_break(tctx);
2622         CHECK_VAL(break_info.count, 1);
2623         CHECK_VAL(break_info.failures, 0);
2624         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2625
2626         smbcli_close(cli1->tree, fnum);
2627
2628 done:
2629         smb_raw_exit(cli1->session);
2630         smb_raw_exit(cli2->session);
2631         smbcli_deltree(cli1->tree, BASEDIR);
2632         return ret;
2633 }
2634
2635 static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2636 {
2637         const char *fname1 = BASEDIR "\\test_batch18_1.dat";
2638         const char *fname2 = BASEDIR "\\test_batch18_2.dat";
2639         NTSTATUS status;
2640         bool ret = true;
2641         union smb_open io;
2642         union smb_rename rn;
2643         uint16_t fnum=0;
2644
2645         if (!torture_setup_dir(cli1, BASEDIR)) {
2646                 return false;
2647         }
2648
2649         /* cleanup */
2650         smbcli_unlink(cli1->tree, fname1);
2651         smbcli_unlink(cli1->tree, fname2);
2652
2653         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2654
2655         /*
2656           base ntcreatex parms
2657         */
2658         io.generic.level = RAW_OPEN_NTCREATEX;
2659         io.ntcreatex.in.root_fid.fnum = 0;
2660         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2661         io.ntcreatex.in.alloc_size = 0;
2662         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2663         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2664         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2665         io.ntcreatex.in.create_options = 0;
2666         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2667         io.ntcreatex.in.security_flags = 0;
2668         io.ntcreatex.in.fname = fname1;
2669
2670         torture_comment(tctx, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2671
2672         ZERO_STRUCT(break_info);
2673         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2674                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2675                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2676
2677         status = smb_raw_open(cli1->tree, tctx, &io);
2678         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2679         fnum = io.ntcreatex.out.file.fnum;
2680         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2681
2682         torture_comment(tctx, "ntrename should trigger a break\n");
2683         ZERO_STRUCT(rn);
2684         rn.generic.level = RAW_RENAME_NTRENAME;
2685         rn.ntrename.in.attrib   = 0;
2686         rn.ntrename.in.flags    = RENAME_FLAG_RENAME;
2687         rn.ntrename.in.old_name = fname1;
2688         rn.ntrename.in.new_name = fname2;
2689         torture_comment(tctx, "trying rename while first file open\n");
2690         status = smb_raw_rename(cli2->tree, &rn);
2691         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2692
2693         torture_wait_for_oplock_break(tctx);
2694         CHECK_VAL(break_info.count, 1);
2695         CHECK_VAL(break_info.failures, 0);
2696         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2697
2698         smbcli_close(cli1->tree, fnum);
2699
2700 done:
2701         smb_raw_exit(cli1->session);
2702         smb_raw_exit(cli2->session);
2703         smbcli_deltree(cli1->tree, BASEDIR);
2704         return ret;
2705 }
2706
2707 static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2708 {
2709         const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2710         const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2711         const char *fname3 = BASEDIR "\\test_batch19_3.dat";
2712         NTSTATUS status;
2713         bool ret = true;
2714         union smb_open io;
2715         union smb_fileinfo qfi;
2716         union smb_setfileinfo sfi;
2717         uint16_t fnum=0;
2718
2719         if (!torture_setup_dir(cli1, BASEDIR)) {
2720                 return false;
2721         }
2722
2723         /* cleanup */
2724         smbcli_unlink(cli1->tree, fname1);
2725         smbcli_unlink(cli1->tree, fname2);
2726         smbcli_unlink(cli1->tree, fname3);
2727
2728         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2729
2730         /*
2731           base ntcreatex parms
2732         */
2733         io.generic.level = RAW_OPEN_NTCREATEX;
2734         io.ntcreatex.in.root_fid.fnum = 0;
2735         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2736         io.ntcreatex.in.alloc_size = 0;
2737         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2738         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2739             NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
2740         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2741         io.ntcreatex.in.create_options = 0;
2742         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2743         io.ntcreatex.in.security_flags = 0;
2744         io.ntcreatex.in.fname = fname1;
2745
2746         torture_comment(tctx, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2747         ZERO_STRUCT(break_info);
2748         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2749                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2750                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2751         status = smb_raw_open(cli1->tree, tctx, &io);
2752         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2753         fnum = io.ntcreatex.out.file.fnum;
2754         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2755
2756         torture_comment(tctx, "setpathinfo rename info should trigger a break "
2757             "to none\n");
2758         ZERO_STRUCT(sfi);
2759         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2760         sfi.generic.in.file.path = fname1;
2761         sfi.rename_information.in.overwrite     = 0;
2762         sfi.rename_information.in.root_fid      = 0;
2763         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2764
2765         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2766         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2767
2768         torture_wait_for_oplock_break(tctx);
2769
2770         CHECK_VAL(break_info.failures, 0);
2771
2772         if (TARGET_IS_WINXP(tctx) || TARGET_IS_W2K12(tctx)) {
2773                 /* Win XP breaks to level2. */
2774                 CHECK_VAL(break_info.count, 1);
2775                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2776         } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
2777             TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
2778                 /* Win2K3/2k8 incorrectly doesn't break at all. */
2779                 CHECK_VAL(break_info.count, 0);
2780         } else {
2781                 /* win7/2k8r2 break to none. */
2782                 CHECK_VAL(break_info.count, 1);
2783                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2784         }
2785
2786         ZERO_STRUCT(qfi);
2787         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2788         qfi.generic.in.file.fnum = fnum;
2789
2790         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2791         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2792         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2793
2794         /* Close and re-open file with oplock. */
2795         smbcli_close(cli1->tree, fnum);
2796         status = smb_raw_open(cli1->tree, tctx, &io);
2797         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2798         fnum = io.ntcreatex.out.file.fnum;
2799         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2800
2801         torture_comment(tctx, "setfileinfo rename info on a client's own fid "
2802             "should not trigger a break nor a violation\n");
2803         ZERO_STRUCT(break_info);
2804         ZERO_STRUCT(sfi);
2805         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2806         sfi.generic.in.file.fnum = fnum;
2807         sfi.rename_information.in.overwrite     = 0;
2808         sfi.rename_information.in.root_fid      = 0;
2809         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2810
2811         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2812         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2813
2814         torture_wait_for_oplock_break(tctx);
2815         if (TARGET_IS_WINXP(tctx)) {
2816                 /* XP incorrectly breaks to level2. */
2817                 CHECK_VAL(break_info.count, 1);
2818                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2819         } else {
2820                 CHECK_VAL(break_info.count, 0);
2821         }
2822
2823         ZERO_STRUCT(qfi);
2824         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2825         qfi.generic.in.file.fnum = fnum;
2826
2827         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2828         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2829         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2830
2831 done:
2832         smbcli_close(cli1->tree, fnum);
2833         smb_raw_exit(cli1->session);
2834         smb_raw_exit(cli2->session);
2835         smbcli_deltree(cli1->tree, BASEDIR);
2836         return ret;
2837 }
2838
2839 /****************************************************
2840  Called from raw-rename - we need oplock handling for
2841  this test so this is why it's in oplock.c, not rename.c
2842 ****************************************************/
2843
2844 bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2845 {
2846         const char *fname1 = BASEDIR "\\test_trans2rename_1.dat";
2847         const char *fname2 = BASEDIR "\\test_trans2rename_2.dat";
2848         const char *fname3 = BASEDIR "\\test_trans2rename_3.dat";
2849         NTSTATUS status;
2850         bool ret = true;
2851         union smb_open io;
2852         union smb_fileinfo qfi;
2853         union smb_setfileinfo sfi;
2854         uint16_t fnum=0;
2855
2856         if (!torture_setup_dir(cli1, BASEDIR)) {
2857                 return false;
2858         }
2859
2860         /* cleanup */
2861         smbcli_unlink(cli1->tree, fname1);
2862         smbcli_unlink(cli1->tree, fname2);
2863         smbcli_unlink(cli1->tree, fname3);
2864
2865         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2866
2867         /*
2868           base ntcreatex parms
2869         */
2870         io.generic.level = RAW_OPEN_NTCREATEX;
2871         io.ntcreatex.in.root_fid.fnum = 0;
2872         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2873         io.ntcreatex.in.alloc_size = 0;
2874         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2875         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2876             NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
2877         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2878         io.ntcreatex.in.create_options = 0;
2879         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2880         io.ntcreatex.in.security_flags = 0;
2881         io.ntcreatex.in.fname = fname1;
2882
2883         torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n");
2884         ZERO_STRUCT(break_info);
2885         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2886                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2887         status = smb_raw_open(cli1->tree, tctx, &io);
2888         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2889         fnum = io.ntcreatex.out.file.fnum;
2890         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2891
2892         torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2893         ZERO_STRUCT(sfi);
2894         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2895         sfi.generic.in.file.path = fname1;
2896         sfi.rename_information.in.overwrite     = 0;
2897         sfi.rename_information.in.root_fid      = 0;
2898         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2899
2900         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2901
2902         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2903
2904         torture_wait_for_oplock_break(tctx);
2905         CHECK_VAL(break_info.count, 0);
2906
2907         ZERO_STRUCT(qfi);
2908         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2909         qfi.generic.in.file.fnum = fnum;
2910
2911         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2912         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2913         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2914
2915         torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2916         ZERO_STRUCT(sfi);
2917         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2918         sfi.generic.in.file.fnum = fnum;
2919         sfi.rename_information.in.overwrite     = 0;
2920         sfi.rename_information.in.root_fid      = 0;
2921         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2922
2923         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2924         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2925
2926         torture_wait_for_oplock_break(tctx);
2927         CHECK_VAL(break_info.count, 0);
2928
2929         ZERO_STRUCT(qfi);
2930         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2931         qfi.generic.in.file.fnum = fnum;
2932
2933         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2934         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2935         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2936
2937 done:
2938         smbcli_close(cli1->tree, fnum);
2939         smb_raw_exit(cli1->session);
2940         smb_raw_exit(cli2->session);
2941         smbcli_deltree(cli1->tree, BASEDIR);
2942         return ret;
2943 }
2944
2945 /****************************************************
2946  Called from raw-rename - we need oplock handling for
2947  this test so this is why it's in oplock.c, not rename.c
2948 ****************************************************/
2949
2950 bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1)
2951 {
2952         const char *fname1 = BASEDIR "\\test_nttransrename_1.dat";
2953         const char *fname2 = BASEDIR "\\test_nttransrename_2.dat";
2954         NTSTATUS status;
2955         bool ret = true;
2956         union smb_open io;
2957         union smb_fileinfo qfi, qpi;
2958         union smb_rename rn;
2959         uint16_t fnum=0;
2960
2961         if (!torture_setup_dir(cli1, BASEDIR)) {
2962                 return false;
2963         }
2964
2965         /* cleanup */
2966         smbcli_unlink(cli1->tree, fname1);
2967         smbcli_unlink(cli1->tree, fname2);
2968
2969         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2970
2971         /*
2972           base ntcreatex parms
2973         */
2974         io.generic.level = RAW_OPEN_NTCREATEX;
2975         io.ntcreatex.in.root_fid.fnum = 0;
2976         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2977         io.ntcreatex.in.alloc_size = 0;
2978         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2979         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2980         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2981         io.ntcreatex.in.create_options = 0;
2982         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2983         io.ntcreatex.in.security_flags = 0;
2984         io.ntcreatex.in.fname = fname1;
2985
2986         torture_comment(tctx, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2987         ZERO_STRUCT(break_info);
2988         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2989                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2990         status = smb_raw_open(cli1->tree, tctx, &io);
2991         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2992         fnum = io.ntcreatex.out.file.fnum;
2993         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2994
2995         torture_comment(tctx, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2996         ZERO_STRUCT(rn);
2997         rn.generic.level = RAW_RENAME_NTTRANS;
2998         rn.nttrans.in.file.fnum = fnum;
2999         rn.nttrans.in.flags     = 0;
3000         rn.nttrans.in.new_name  = fname2+strlen(BASEDIR)+1;
3001
3002         status = smb_raw_rename(cli1->tree, &rn);
3003         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3004
3005         torture_wait_for_oplock_break(tctx);
3006         CHECK_VAL(break_info.count, 0);
3007
3008         /* w2k3 does nothing, it doesn't rename the file */
3009         torture_comment(tctx, "nttrans_rename: the server should have done nothing\n");
3010         ZERO_STRUCT(qfi);
3011         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
3012         qfi.generic.in.file.fnum = fnum;
3013
3014         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
3015         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3016         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname1);
3017
3018         ZERO_STRUCT(qpi);
3019         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
3020         qpi.generic.in.file.path = fname1;
3021
3022         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
3023         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3024         CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
3025
3026         ZERO_STRUCT(qpi);
3027         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
3028         qpi.generic.in.file.path = fname2;
3029
3030         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
3031         CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
3032
3033         torture_comment(tctx, "nttrans_rename: after closing the file the file is still not renamed\n");
3034         status = smbcli_close(cli1->tree, fnum);
3035         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3036
3037         ZERO_STRUCT(qpi);
3038         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
3039         qpi.generic.in.file.path = fname1;
3040
3041         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
3042         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3043         CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
3044
3045         ZERO_STRUCT(qpi);
3046         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
3047         qpi.generic.in.file.path = fname2;
3048
3049         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
3050         CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
3051
3052         torture_comment(tctx, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
3053         ZERO_STRUCT(rn);
3054         rn.generic.level = RAW_RENAME_NTTRANS;
3055         rn.nttrans.in.file.fnum = fnum+1;
3056         rn.nttrans.in.flags     = 0;
3057         rn.nttrans.in.new_name  = fname2+strlen(BASEDIR)+1;
3058
3059         status = smb_raw_rename(cli1->tree, &rn);
3060
3061         CHECK_STATUS(tctx, status, NT_STATUS_INVALID_HANDLE);
3062
3063 done:
3064         smb_raw_exit(cli1->session);
3065         smbcli_deltree(cli1->tree, BASEDIR);
3066         return ret;
3067 }
3068
3069
3070 static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3071 {
3072         const char *fname1 = BASEDIR "\\test_batch20_1.dat";
3073         const char *fname2 = BASEDIR "\\test_batch20_2.dat";
3074         const char *fname3 = BASEDIR "\\test_batch20_3.dat";
3075         NTSTATUS status;
3076         bool ret = true;
3077         union smb_open io;
3078         union smb_fileinfo qfi;
3079         union smb_setfileinfo sfi;
3080         uint16_t fnum=0,fnum2=0;
3081
3082         if (!torture_setup_dir(cli1, BASEDIR)) {
3083                 return false;
3084         }
3085
3086         /* cleanup */
3087         smbcli_unlink(cli1->tree, fname1);
3088         smbcli_unlink(cli1->tree, fname2);
3089         smbcli_unlink(cli1->tree, fname3);
3090
3091         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3092
3093         /*
3094           base ntcreatex parms
3095         */
3096         io.generic.level = RAW_OPEN_NTCREATEX;
3097         io.ntcreatex.in.root_fid.fnum = 0;
3098         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3099         io.ntcreatex.in.alloc_size = 0;
3100         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3101         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3102         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3103         io.ntcreatex.in.create_options = 0;
3104         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3105         io.ntcreatex.in.security_flags = 0;
3106         io.ntcreatex.in.fname = fname1;
3107
3108         torture_comment(tctx, "BATCH20: open a file with an batch oplock (share mode: all)\n");
3109         ZERO_STRUCT(break_info);
3110         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3111                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3112                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3113         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
3114                 NTCREATEX_SHARE_ACCESS_WRITE|
3115                 NTCREATEX_SHARE_ACCESS_DELETE;
3116         status = smb_raw_open(cli1->tree, tctx, &io);
3117         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3118         fnum = io.ntcreatex.out.file.fnum;
3119         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3120
3121         ZERO_STRUCT(sfi);
3122         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
3123         sfi.generic.in.file.path = fname1;
3124         sfi.rename_information.in.overwrite     = 0;
3125         sfi.rename_information.in.root_fid      = 0;
3126         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
3127
3128         status = smb_raw_setpathinfo(cli2->tree, &sfi);
3129         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3130
3131         torture_wait_for_oplock_break(tctx);
3132         CHECK_VAL(break_info.failures, 0);
3133
3134         if (TARGET_IS_WINXP(tctx) || TARGET_IS_W2K12(tctx)) {
3135                 /* Win XP breaks to level2. */
3136                 CHECK_VAL(break_info.count, 1);
3137                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3138         } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
3139             TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
3140                 /* Win2K3/2k8 incorrectly doesn't break at all. */
3141                 CHECK_VAL(break_info.count, 0);
3142         } else {
3143                 /* win7/2k8r2 break to none. */
3144                 CHECK_VAL(break_info.count, 1);
3145                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3146         }
3147
3148         ZERO_STRUCT(qfi);
3149         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
3150         qfi.generic.in.file.fnum = fnum;
3151
3152         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
3153         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3154         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
3155
3156         torture_comment(tctx, "open a file with the new name an batch oplock (share mode: all)\n");
3157         ZERO_STRUCT(break_info);
3158         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3159                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3160                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3161         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
3162                 NTCREATEX_SHARE_ACCESS_WRITE|
3163                 NTCREATEX_SHARE_ACCESS_DELETE;
3164         io.ntcreatex.in.fname = fname2;
3165         status = smb_raw_open(cli2->tree, tctx, &io);
3166         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3167         fnum2 = io.ntcreatex.out.file.fnum;
3168         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
3169
3170         torture_wait_for_oplock_break(tctx);
3171
3172         if (TARGET_IS_WINXP(tctx)) {
3173                 /* XP broke to level2, and doesn't break again. */
3174                 CHECK_VAL(break_info.count, 0);
3175         } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
3176             TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
3177                 /* Win2K3 incorrectly didn't break before so break now. */
3178                 CHECK_VAL(break_info.count, 1);
3179                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3180         } else {
3181                 /* win7/2k8r2 broke to none, and doesn't break again. */
3182                 CHECK_VAL(break_info.count, 0);
3183         }
3184
3185         ZERO_STRUCT(break_info);
3186
3187         ZERO_STRUCT(sfi);
3188         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
3189         sfi.generic.in.file.fnum = fnum;
3190         sfi.rename_information.in.overwrite     = 0;
3191         sfi.rename_information.in.root_fid      = 0;
3192         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
3193
3194         status = smb_raw_setfileinfo(cli1->tree, &sfi);
3195         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3196
3197         torture_wait_for_oplock_break(tctx);
3198         CHECK_VAL(break_info.count, 0);
3199
3200         ZERO_STRUCT(qfi);
3201         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
3202         qfi.generic.in.file.fnum = fnum;
3203
3204         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
3205         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3206         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
3207
3208         ZERO_STRUCT(qfi);
3209         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
3210         qfi.generic.in.file.fnum = fnum2;
3211
3212         status = smb_raw_fileinfo(cli2->tree, tctx, &qfi);
3213         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3214         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
3215
3216
3217 done:
3218         smbcli_close(cli1->tree, fnum);
3219         smbcli_close(cli2->tree, fnum2);
3220         smb_raw_exit(cli1->session);
3221         smb_raw_exit(cli2->session);
3222         smbcli_deltree(cli1->tree, BASEDIR);
3223         return ret;
3224 }
3225
3226 static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3227 {
3228         const char *fname = BASEDIR "\\test_batch21.dat";
3229         NTSTATUS status;
3230         bool ret = true;
3231         union smb_open io;
3232         struct smb_echo e;
3233         uint16_t fnum=0;
3234         char c = 0;
3235         ssize_t wr;
3236
3237         if (!torture_setup_dir(cli1, BASEDIR)) {
3238                 return false;
3239         }
3240
3241         /* cleanup */
3242         smbcli_unlink(cli1->tree, fname);
3243
3244         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3245
3246         /*
3247           base ntcreatex parms
3248         */
3249         io.generic.level = RAW_OPEN_NTCREATEX;
3250         io.ntcreatex.in.root_fid.fnum = 0;
3251         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3252         io.ntcreatex.in.alloc_size = 0;
3253         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3254         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3255         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3256         io.ntcreatex.in.create_options = 0;
3257         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3258         io.ntcreatex.in.security_flags = 0;
3259         io.ntcreatex.in.fname = fname;
3260
3261         /*
3262           with a batch oplock we get a break
3263         */
3264         torture_comment(tctx, "BATCH21: open with batch oplock\n");
3265         ZERO_STRUCT(break_info);
3266         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3267                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3268                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3269         status = smb_raw_open(cli1->tree, tctx, &io);
3270         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3271         fnum = io.ntcreatex.out.file.fnum;
3272         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3273
3274         torture_comment(tctx, "writing should not generate a break\n");
3275         wr = smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
3276         CHECK_VAL(wr, 1);
3277         CHECK_STATUS(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_OK);
3278
3279         ZERO_STRUCT(e);
3280         e.in.repeat_count = 1;
3281         status = smb_raw_echo(cli1->transport, &e);
3282         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3283
3284         torture_wait_for_oplock_break(tctx);
3285         CHECK_VAL(break_info.count, 0);
3286
3287         smbcli_close(cli1->tree, fnum);
3288
3289 done:
3290         smb_raw_exit(cli1->session);
3291         smb_raw_exit(cli2->session);
3292         smbcli_deltree(cli1->tree, BASEDIR);
3293         return ret;
3294 }
3295
3296 static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3297 {
3298         const char *fname = BASEDIR "\\test_batch22.dat";
3299         NTSTATUS status;
3300         bool ret = true;
3301         union smb_open io;
3302         uint16_t fnum = 0, fnum2 = 0, fnum3 = 0;
3303         struct timeval tv;
3304         int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
3305         int te;
3306
3307         if (!torture_setup_dir(cli1, BASEDIR)) {
3308                 return false;
3309         }
3310
3311         /* cleanup */
3312         smbcli_unlink(cli1->tree, fname);
3313
3314         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3315         /*
3316           base ntcreatex parms
3317         */
3318         io.generic.level = RAW_OPEN_NTCREATEX;
3319         io.ntcreatex.in.root_fid.fnum = 0;
3320         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3321         io.ntcreatex.in.alloc_size = 0;
3322         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3323         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3324         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3325         io.ntcreatex.in.create_options = 0;
3326         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3327         io.ntcreatex.in.security_flags = 0;
3328         io.ntcreatex.in.fname = fname;
3329
3330         /*
3331           with a batch oplock we get a break
3332         */
3333         torture_comment(tctx, "BATCH22: open with batch oplock\n");
3334         ZERO_STRUCT(break_info);
3335         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3336                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3337                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3338         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
3339                 NTCREATEX_SHARE_ACCESS_WRITE|
3340                 NTCREATEX_SHARE_ACCESS_DELETE;
3341         status = smb_raw_open(cli1->tree, tctx, &io);
3342         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3343         fnum = io.ntcreatex.out.file.fnum;
3344         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3345
3346         torture_comment(tctx, "a 2nd open should not succeed after the oplock "
3347                         "break timeout\n");
3348         tv = timeval_current();
3349         smbcli_oplock_handler(cli1->transport, oplock_handler_timeout, cli1->tree);
3350         status = smb_raw_open(cli1->tree, tctx, &io);
3351
3352         if (TARGET_IS_W2K3(tctx)) {
3353                 /* 2k3 has an issue here. xp/win7 are ok. */
3354                 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
3355         } else {
3356                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3357         }
3358
3359         fnum2 = io.ntcreatex.out.file.fnum;
3360
3361         torture_wait_for_oplock_break(tctx);
3362         te = (int)timeval_elapsed(&tv);
3363
3364         /*
3365          * Some servers detect clients that let oplocks timeout, so this check
3366          * only shows a warning message instead failing the test to eliminate
3367          * failures from repeated runs of the test.  This isn't ideal, but
3368          * it's better than not running the test at all.
3369          */
3370         CHECK_RANGE(te, timeout - 1, timeout + 15);
3371
3372         CHECK_VAL(break_info.count, 1);
3373         CHECK_VAL(break_info.fnum, fnum);
3374         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3375         CHECK_VAL(break_info.failures, 0);
3376         ZERO_STRUCT(break_info);
3377
3378         torture_comment(tctx, "a 2nd open should succeed after the oplock "
3379                         "release without break\n");
3380         tv = timeval_current();
3381         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3382         status = smb_raw_open(cli1->tree, tctx, &io);
3383         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3384 #if 0
3385         /* Samba 3.6.0 and above behave as Windows. */
3386         if (TARGET_IS_SAMBA3(tctx)) {
3387                 /* samba3 doesn't grant additional oplocks to bad clients. */
3388                 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
3389         } else {
3390                 CHECK_VAL(io.ntcreatex.out.oplock_level,
3391                         LEVEL_II_OPLOCK_RETURN);
3392         }
3393 #else
3394         CHECK_VAL(io.ntcreatex.out.oplock_level,
3395                   LEVEL_II_OPLOCK_RETURN);
3396 #endif
3397         torture_wait_for_oplock_break(tctx);
3398         te = (int)timeval_elapsed(&tv);
3399         /* it should come in without delay */
3400         CHECK_RANGE(te+1, 0, timeout);
3401         fnum3 = io.ntcreatex.out.file.fnum;
3402
3403         CHECK_VAL(break_info.count, 0);
3404
3405         smbcli_close(cli1->tree, fnum);
3406         smbcli_close(cli1->tree, fnum2);
3407         smbcli_close(cli1->tree, fnum3);
3408
3409 done:
3410         smb_raw_exit(cli1->session);
3411         smb_raw_exit(cli2->session);
3412         smbcli_deltree(cli1->tree, BASEDIR);
3413         return ret;
3414 }
3415
3416 static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3417 {
3418         const char *fname = BASEDIR "\\test_batch23.dat";
3419         NTSTATUS status;
3420         bool ret = true;
3421         union smb_open io;
3422         uint16_t fnum=0, fnum2=0,fnum3=0;
3423         struct smbcli_state *cli3 = NULL;
3424
3425         if (!torture_setup_dir(cli1, BASEDIR)) {
3426                 return false;
3427         }
3428
3429         /* cleanup */
3430         smbcli_unlink(cli1->tree, fname);
3431
3432         ret = open_connection_no_level2_oplocks(tctx, &cli3);
3433         CHECK_VAL(ret, true);
3434
3435         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3436         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3437         smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
3438
3439         /*
3440           base ntcreatex parms
3441         */
3442         io.generic.level = RAW_OPEN_NTCREATEX;
3443         io.ntcreatex.in.root_fid.fnum = 0;
3444         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3445         io.ntcreatex.in.alloc_size = 0;
3446         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3447         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3448         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3449         io.ntcreatex.in.create_options = 0;
3450         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3451         io.ntcreatex.in.security_flags = 0;
3452         io.ntcreatex.in.fname = fname;
3453
3454         torture_comment(tctx, "BATCH23: a open and ask for a batch oplock\n");
3455         ZERO_STRUCT(break_info);
3456
3457         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
3458         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
3459         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3460                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3461                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3462         status = smb_raw_open(cli1->tree, tctx, &io);
3463         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3464         fnum = io.ntcreatex.out.file.fnum;
3465         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3466
3467         ZERO_STRUCT(break_info);
3468
3469         torture_comment(tctx, "a 2nd open without level2 oplock support should generate a break to level2\n");
3470         status = smb_raw_open(cli3->tree, tctx, &io);
3471         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3472         fnum3 = io.ntcreatex.out.file.fnum;
3473         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
3474
3475         torture_wait_for_oplock_break(tctx);
3476         CHECK_VAL(break_info.count, 1);
3477         CHECK_VAL(break_info.fnum, fnum);
3478         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3479         CHECK_VAL(break_info.failures, 0);
3480
3481         ZERO_STRUCT(break_info);
3482
3483         torture_comment(tctx, "a 3rd open with level2 oplock support should not generate a break\n");
3484         status = smb_raw_open(cli2->tree, tctx, &io);
3485         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3486         fnum2 = io.ntcreatex.out.file.fnum;
3487         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
3488
3489         torture_wait_for_oplock_break(tctx);
3490         CHECK_VAL(break_info.count, 0);
3491
3492         smbcli_close(cli1->tree, fnum);
3493         smbcli_close(cli2->tree, fnum2);
3494         smbcli_close(cli3->tree, fnum3);
3495
3496 done:
3497         smb_raw_exit(cli1->session);
3498         smb_raw_exit(cli2->session);
3499         smb_raw_exit(cli3->session);
3500         smbcli_deltree(cli1->tree, BASEDIR);
3501         return ret;
3502 }
3503
3504 static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3505 {
3506         const char *fname = BASEDIR "\\test_batch24.dat";
3507         NTSTATUS status;
3508         bool ret = true;
3509         union smb_open io;
3510         uint16_t fnum2=0,fnum3=0;
3511         struct smbcli_state *cli3 = NULL;
3512
3513         if (!torture_setup_dir(cli1, BASEDIR)) {
3514                 return false;
3515         }
3516
3517         /* cleanup */
3518         smbcli_unlink(cli1->tree, fname);
3519
3520         ret = open_connection_no_level2_oplocks(tctx, &cli3);
3521         CHECK_VAL(ret, true);
3522
3523         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3524         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3525         smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
3526
3527         /*
3528           base ntcreatex parms
3529         */
3530         io.generic.level = RAW_OPEN_NTCREATEX;
3531         io.ntcreatex.in.root_fid.fnum = 0;
3532         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3533         io.ntcreatex.in.alloc_size = 0;
3534         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3535         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3536         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3537         io.ntcreatex.in.create_options = 0;
3538         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3539         io.ntcreatex.in.security_flags = 0;
3540         io.ntcreatex.in.fname = fname;
3541
3542         torture_comment(tctx, "BATCH24: a open without level support and ask for a batch oplock\n");
3543         ZERO_STRUCT(break_info);
3544
3545         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
3546         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
3547         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3548                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3549                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3550         status = smb_raw_open(cli3->tree, tctx, &io);
3551         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3552         fnum3 = io.ntcreatex.out.file.fnum;
3553         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3554
3555         ZERO_STRUCT(break_info);
3556
3557         torture_comment(tctx, "a 2nd open with level2 oplock support should generate a break to none\n");
3558         status = smb_raw_open(cli2->tree, tctx, &io);
3559         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3560         fnum2 = io.ntcreatex.out.file.fnum;
3561         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
3562
3563         torture_wait_for_oplock_break(tctx);
3564         CHECK_VAL(break_info.count, 1);
3565         CHECK_VAL(break_info.fnum, fnum3);
3566         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3567         CHECK_VAL(break_info.failures, 0);
3568
3569         smbcli_close(cli3->tree, fnum3);
3570         smbcli_close(cli2->tree, fnum2);
3571
3572 done:
3573         smb_raw_exit(cli1->session);
3574         smb_raw_exit(cli2->session);
3575         smb_raw_exit(cli3->session);
3576         smbcli_deltree(cli1->tree, BASEDIR);
3577         return ret;
3578 }
3579
3580 static bool test_raw_oplock_batch25(struct torture_context *tctx,
3581                                     struct smbcli_state *cli1,
3582                                     struct smbcli_state *cli2)
3583 {
3584         const char *fname = BASEDIR "\\test_batch25.dat";
3585         NTSTATUS status;
3586         bool ret = true;
3587         union smb_open io;
3588         union smb_setfileinfo sfi;
3589         uint16_t fnum=0;
3590
3591         if (!torture_setup_dir(cli1, BASEDIR)) {
3592                 return false;
3593         }
3594
3595         /* cleanup */
3596         smbcli_unlink(cli1->tree, fname);
3597
3598         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3599
3600         /*
3601           base ntcreatex parms
3602         */
3603         io.generic.level = RAW_OPEN_NTCREATEX;
3604         io.ntcreatex.in.root_fid.fnum = 0;
3605         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3606         io.ntcreatex.in.alloc_size = 0;
3607         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3608         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3609         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3610         io.ntcreatex.in.create_options = 0;
3611         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3612         io.ntcreatex.in.security_flags = 0;
3613         io.ntcreatex.in.fname = fname;
3614
3615         torture_comment(tctx, "BATCH25: open a file with an batch oplock "
3616                         "(share mode: none)\n");
3617
3618         ZERO_STRUCT(break_info);
3619         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3620                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3621                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3622         status = smb_raw_open(cli1->tree, tctx, &io);
3623         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3624         fnum = io.ntcreatex.out.file.fnum;
3625         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3626
3627         torture_comment(tctx, "setpathinfo attribute info should not trigger "
3628                         "a break nor a violation\n");
3629         ZERO_STRUCT(sfi);
3630         sfi.generic.level = RAW_SFILEINFO_SETATTR;
3631         sfi.generic.in.file.path        = fname;
3632         sfi.setattr.in.attrib           = FILE_ATTRIBUTE_HIDDEN;
3633         sfi.setattr.in.write_time       = 0;
3634
3635         status = smb_raw_setpathinfo(cli2->tree, &sfi);
3636         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3637
3638         torture_wait_for_oplock_break(tctx);
3639         CHECK_VAL(break_info.count, 0);
3640
3641         smbcli_close(cli1->tree, fnum);
3642
3643 done:
3644         smb_raw_exit(cli1->session);
3645         smb_raw_exit(cli2->session);
3646         smbcli_deltree(cli1->tree, BASEDIR);
3647         return ret;
3648 }
3649
3650 /**
3651  * Similar to batch17/18, but test with open share mode rather than
3652  * share_none.
3653  */
3654 static bool test_raw_oplock_batch26(struct torture_context *tctx,
3655     struct smbcli_state *cli1, struct smbcli_state *cli2)
3656 {
3657         const char *fname1 = BASEDIR "\\test_batch26_1.dat";
3658         const char *fname2 = BASEDIR "\\test_batch26_2.dat";
3659         NTSTATUS status;
3660         bool ret = true;
3661         union smb_open io;
3662         union smb_rename rn;
3663         uint16_t fnum=0;
3664
3665         if (!torture_setup_dir(cli1, BASEDIR)) {
3666                 return false;
3667         }
3668
3669         /* cleanup */
3670         smbcli_unlink(cli1->tree, fname1);
3671         smbcli_unlink(cli1->tree, fname2);
3672
3673         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3674             cli1->tree);
3675
3676         /*
3677           base ntcreatex parms
3678         */
3679         io.generic.level = RAW_OPEN_NTCREATEX;
3680         io.ntcreatex.in.root_fid.fnum = 0;
3681         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3682         io.ntcreatex.in.alloc_size = 0;
3683         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3684         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3685             NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
3686         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3687         io.ntcreatex.in.create_options = 0;
3688         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3689         io.ntcreatex.in.security_flags = 0;
3690         io.ntcreatex.in.fname = fname1;
3691
3692         torture_comment(tctx,
3693                         "BATCH26: open a file with an batch oplock "
3694                         "(share mode: all)\n");
3695
3696         ZERO_STRUCT(break_info);
3697         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3698                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3699                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3700
3701
3702         status = smb_raw_open(cli1->tree, tctx, &io);
3703         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3704         fnum = io.ntcreatex.out.file.fnum;
3705         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3706
3707         torture_comment(tctx, "rename should trigger a break\n");
3708         ZERO_STRUCT(rn);
3709         rn.generic.level = RAW_RENAME_RENAME;
3710         rn.rename.in.pattern1 = fname1;
3711         rn.rename.in.pattern2 = fname2;
3712         rn.rename.in.attrib = 0;
3713
3714         torture_comment(tctx, "trying rename while first file open\n");
3715         status = smb_raw_rename(cli2->tree, &rn);
3716         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
3717
3718         torture_wait_for_oplock_break(tctx);
3719         CHECK_VAL(break_info.count, 1);
3720         CHECK_VAL(break_info.failures, 0);
3721         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3722
3723         /* Close and reopen with batch again. */
3724         smbcli_close(cli1->tree, fnum);
3725         ZERO_STRUCT(break_info);
3726
3727         status = smb_raw_open(cli1->tree, tctx, &io);
3728         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3729         fnum = io.ntcreatex.out.file.fnum;
3730         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3731
3732         /* Now try ntrename. */
3733         torture_comment(tctx, "ntrename should trigger a break\n");
3734         ZERO_STRUCT(rn);
3735         rn.generic.level = RAW_RENAME_NTRENAME;
3736         rn.ntrename.in.attrib   = 0;
3737         rn.ntrename.in.flags    = RENAME_FLAG_RENAME;
3738         rn.ntrename.in.old_name = fname1;
3739         rn.ntrename.in.new_name = fname2;
3740         torture_comment(tctx, "trying rename while first file open\n");
3741         status = smb_raw_rename(cli2->tree, &rn);
3742         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
3743
3744         torture_wait_for_oplock_break(tctx);
3745         CHECK_VAL(break_info.count, 1);
3746         CHECK_VAL(break_info.failures, 0);
3747         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3748
3749         smbcli_close(cli1->tree, fnum);
3750
3751 done:
3752         smb_raw_exit(cli1->session);
3753         smb_raw_exit(cli2->session);
3754         smbcli_deltree(cli1->tree, BASEDIR);
3755         return ret;
3756 }
3757
3758 /* Test how oplocks work on streams. */
3759 static bool test_raw_oplock_stream1(struct torture_context *tctx,
3760                                     struct smbcli_state *cli1,
3761                                     struct smbcli_state *cli2)
3762 {
3763         NTSTATUS status;
3764         union smb_open io;
3765         const char *fname_base = BASEDIR "\\test_stream1.txt";
3766         const char *stream = "Stream One:$DATA";
3767         const char *fname_stream, *fname_default_stream;
3768         const char *default_stream = "::$DATA";
3769         bool ret = true;
3770         int fnum = -1;
3771         int i;
3772         int stream_fnum = -1;
3773         uint32_t batch_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
3774             NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK | NTCREATEX_FLAGS_EXTENDED;
3775         uint32_t exclusive_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
3776             NTCREATEX_FLAGS_EXTENDED;
3777
3778 #define NSTREAM_OPLOCK_RESULTS 8
3779         struct {
3780                 const char **fname;
3781                 bool open_base_file;
3782                 uint32_t oplock_req;
3783                 uint32_t oplock_granted;
3784         } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
3785                 /* Request oplock on stream without the base file open. */
3786                 {&fname_stream, false, batch_req, NO_OPLOCK_RETURN},
3787                 {&fname_default_stream, false, batch_req, NO_OPLOCK_RETURN},
3788                 {&fname_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3789                 {&fname_default_stream, false,  exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3790
3791                 /* Request oplock on stream with the base file open. */
3792                 {&fname_stream, true, batch_req, NO_OPLOCK_RETURN},
3793                 {&fname_default_stream, true, batch_req, NO_OPLOCK_RETURN},
3794                 {&fname_stream, true, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3795                 {&fname_default_stream, true,  exclusive_req, LEVEL_II_OPLOCK_RETURN},
3796
3797         };
3798
3799
3800         /* Only passes against windows at the moment. */
3801         if (torture_setting_bool(tctx, "samba3", false) ||
3802             torture_setting_bool(tctx, "samba4", false)) {
3803                 torture_skip(tctx, "STREAM1 disabled against samba3+4\n");
3804         }
3805
3806         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
3807         fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
3808                                                default_stream);
3809
3810         if (!torture_setup_dir(cli1, BASEDIR)) {
3811                 return false;
3812         }
3813         smbcli_unlink(cli1->tree, fname_base);
3814
3815         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3816         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3817
3818         /* Setup generic open parameters. */
3819         io.generic.level = RAW_OPEN_NTCREATEX;
3820         io.ntcreatex.in.root_fid.fnum = 0;
3821         io.ntcreatex.in.access_mask = (SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|
3822             SEC_FILE_APPEND_DATA|SEC_STD_READ_CONTROL);
3823         io.ntcreatex.in.create_options = 0;
3824         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3825         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3826             NTCREATEX_SHARE_ACCESS_WRITE;
3827         io.ntcreatex.in.alloc_size = 0;
3828         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3829         io.ntcreatex.in.security_flags = 0;
3830
3831         /* Create the file with a stream */
3832         io.ntcreatex.in.fname = fname_stream;
3833         io.ntcreatex.in.flags = 0;
3834         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
3835         status = smb_raw_open(cli1->tree, tctx, &io);
3836         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3837         smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3838
3839         /* Change the disposition to open now that the file has been created. */
3840         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
3841
3842         /* Try some permutations of taking oplocks on streams. */
3843         for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
3844                 const char *fname = *stream_oplock_results[i].fname;
3845                 bool open_base_file = stream_oplock_results[i].open_base_file;
3846                 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
3847                 uint32_t oplock_granted =
3848                     stream_oplock_results[i].oplock_granted;
3849                 int base_fnum = -1;
3850
3851                 if (open_base_file) {
3852                         torture_comment(tctx, "Opening base file: %s with "
3853                             "%d\n", fname_base, batch_req);
3854                         io.ntcreatex.in.fname = fname_base;
3855                         io.ntcreatex.in.flags = batch_req;
3856                         status = smb_raw_open(cli2->tree, tctx, &io);
3857                         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3858                         CHECK_VAL(io.ntcreatex.out.oplock_level,
3859                             BATCH_OPLOCK_RETURN);
3860                         base_fnum = io.ntcreatex.out.file.fnum;
3861                 }
3862
3863                 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
3864                     fname, oplock_req);
3865                 io.ntcreatex.in.fname = fname;
3866                 io.ntcreatex.in.flags = oplock_req;
3867
3868                 /* Do the open with the desired oplock on the stream. */
3869                 status = smb_raw_open(cli1->tree, tctx, &io);
3870                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3871                 CHECK_VAL(io.ntcreatex.out.oplock_level, oplock_granted);
3872                 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3873
3874                 /* Cleanup the base file if it was opened. */
3875                 if (base_fnum != -1) {
3876                         smbcli_close(cli2->tree, base_fnum);
3877                 }
3878         }
3879
3880         /* Open the stream with an exclusive oplock. */
3881         torture_comment(tctx, "Opening stream: %s with %d\n",
3882             fname_stream, exclusive_req);
3883         io.ntcreatex.in.fname = fname_stream;
3884         io.ntcreatex.in.flags = exclusive_req;
3885         status = smb_raw_open(cli1->tree, tctx, &io);
3886         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3887         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
3888         stream_fnum = io.ntcreatex.out.file.fnum;
3889
3890         /* Open the base file and see if it contends. */
3891         ZERO_STRUCT(break_info);
3892         torture_comment(tctx, "Opening base file: %s with "
3893             "%d\n", fname_base, batch_req);
3894         io.ntcreatex.in.fname = fname_base;
3895         io.ntcreatex.in.flags = batch_req;
3896         status = smb_raw_open(cli2->tree, tctx, &io);
3897         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3898         CHECK_VAL(io.ntcreatex.out.oplock_level,
3899             BATCH_OPLOCK_RETURN);
3900         smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3901
3902         torture_wait_for_oplock_break(tctx);
3903         CHECK_VAL(break_info.count, 0);
3904         CHECK_VAL(break_info.failures, 0);
3905
3906         /* Open the stream again to see if it contends. */
3907         ZERO_STRUCT(break_info);
3908         torture_comment(tctx, "Opening stream again: %s with "
3909             "%d\n", fname_base, batch_req);
3910         io.ntcreatex.in.fname = fname_stream;
3911         io.ntcreatex.in.flags = exclusive_req;
3912         status = smb_raw_open(cli2->tree, tctx, &io);
3913         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3914         CHECK_VAL(io.ntcreatex.out.oplock_level,
3915             LEVEL_II_OPLOCK_RETURN);
3916         smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3917
3918         torture_wait_for_oplock_break(tctx);
3919         CHECK_VAL(break_info.count, 1);
3920         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3921         CHECK_VAL(break_info.failures, 0);
3922
3923         /* Close the stream. */
3924         if (stream_fnum != -1) {
3925                 smbcli_close(cli1->tree, stream_fnum);
3926         }
3927
3928  done:
3929         smbcli_close(cli1->tree, fnum);
3930         smb_raw_exit(cli1->session);
3931         smb_raw_exit(cli2->session);
3932         smbcli_deltree(cli1->tree, BASEDIR);
3933         return ret;
3934 }
3935
3936 static bool test_raw_oplock_doc(struct torture_context *tctx,
3937                                 struct smbcli_state *cli,
3938                                 struct smbcli_state *cli2)
3939 {
3940         const char *fname = BASEDIR "\\test_oplock_doc.dat";
3941         NTSTATUS status;
3942         bool ret = true;
3943         union smb_open io;
3944         uint16_t fnum=0;
3945
3946         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
3947
3948         /* cleanup */
3949         smbcli_unlink(cli->tree, fname);
3950
3951         smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_given,
3952                               cli->tree);
3953
3954         /*
3955           base ntcreatex parms
3956         */
3957         io.generic.level = RAW_OPEN_NTCREATEX;
3958         io.ntcreatex.in.root_fid.fnum = 0;
3959         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3960         io.ntcreatex.in.alloc_size = 0;
3961         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3962         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
3963                 NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
3964         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3965         io.ntcreatex.in.create_options = 0;
3966         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3967         io.ntcreatex.in.security_flags = 0;
3968         io.ntcreatex.in.fname = fname;
3969
3970         torture_comment(tctx, "open a file with a batch oplock\n");
3971         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3972             NTCREATEX_FLAGS_REQUEST_OPLOCK |
3973             NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3974
3975         status = smb_raw_open(cli->tree, tctx, &io);
3976         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3977         fnum = io.ntcreatex.out.file.fnum;
3978         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3979
3980         torture_comment(tctx, "Set delete-on-close\n");
3981         status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
3982         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3983
3984         torture_comment(tctx, "2nd open should not break and get "
3985                         "DELETE_PENDING\n");
3986         ZERO_STRUCT(break_info);
3987         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
3988         io.ntcreatex.in.create_options = 0;
3989         io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
3990         status = smb_raw_open(cli2->tree, tctx, &io);
3991         CHECK_STATUS(tctx, status, NT_STATUS_DELETE_PENDING);
3992         CHECK_VAL(break_info.count, 0);
3993
3994         smbcli_close(cli->tree, fnum);
3995
3996 done:
3997         smb_raw_exit(cli->session);
3998         smbcli_deltree(cli->tree, BASEDIR);
3999         return ret;
4000 }
4001
4002 /* Open a file with a batch oplock, then open it again from a second client
4003  * requesting no oplock. Having two open file handles should break our own
4004  * oplock during BRL acquisition.
4005  */
4006 static bool test_raw_oplock_brl1(struct torture_context *tctx,
4007                                  struct smbcli_state *cli1,
4008                                  struct smbcli_state *cli2)
4009 {
4010         const char *fname = BASEDIR "\\test_batch_brl.dat";
4011         /*int fname, f;*/
4012         bool ret = true;
4013         uint8_t buf[1000];
4014         union smb_open io;
4015         NTSTATUS status;
4016         uint16_t fnum=0;
4017         uint16_t fnum2=0;
4018
4019         if (!torture_setup_dir(cli1, BASEDIR)) {
4020                 return false;
4021         }
4022
4023         /* cleanup */
4024         smbcli_unlink(cli1->tree, fname);
4025
4026         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
4027                               cli1->tree);
4028
4029         /*
4030           base ntcreatex parms
4031         */
4032         io.generic.level = RAW_OPEN_NTCREATEX;
4033         io.ntcreatex.in.root_fid.fnum = 0;
4034         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
4035                                       SEC_RIGHTS_FILE_WRITE;
4036         io.ntcreatex.in.alloc_size = 0;
4037         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4038         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
4039                                        NTCREATEX_SHARE_ACCESS_WRITE;
4040         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4041         io.ntcreatex.in.create_options = 0;
4042         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4043         io.ntcreatex.in.security_flags = 0;
4044         io.ntcreatex.in.fname = fname;
4045
4046         /*
4047           with a batch oplock we get a break
4048         */
4049         torture_comment(tctx, "open with batch oplock\n");
4050         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4051                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
4052                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4053
4054         status = smb_raw_open(cli1->tree, tctx, &io);
4055         CHECK_STATUS(tctx, status, NT_STATUS_OK);
4056         fnum = io.ntcreatex.out.file.fnum;
4057         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
4058         /* create a file with bogus data */
4059         memset(buf, 0, sizeof(buf));
4060
4061         if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
4062                          sizeof(buf))
4063         {
4064                 torture_comment(tctx, "Failed to create file\n");
4065                 goto done;
4066         }
4067
4068         torture_comment(tctx, "a 2nd open should give a break\n");
4069         ZERO_STRUCT(break_info);
4070
4071         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
4072         status = smb_raw_open(cli2->tree, tctx, &io);
4073         fnum2 = io.ntcreatex.out.file.fnum;
4074         CHECK_STATUS(tctx, status, NT_STATUS_OK);
4075         CHECK_VAL(break_info.count, 1);
4076         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
4077         CHECK_VAL(break_info.failures, 0);
4078         CHECK_VAL(break_info.fnum, fnum);
4079
4080         ZERO_STRUCT(break_info);
4081
4082         torture_comment(tctx, "a self BRL acquisition should break to none\n");
4083
4084         status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
4085         CHECK_STATUS(tctx, status, NT_STATUS_OK);
4086
4087         torture_wait_for_oplock_break(tctx);
4088         CHECK_VAL(break_info.count, 1);
4089         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
4090         CHECK_VAL(break_info.fnum, fnum);
4091         CHECK_VAL(break_info.failures, 0);
4092
4093         /* expect no oplock break */
4094         ZERO_STRUCT(break_info);
4095         status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
4096         CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
4097
4098         torture_wait_for_oplock_break(tctx);
4099         CHECK_VAL(break_info.count, 0);
4100         CHECK_VAL(break_info.level, 0);
4101         CHECK_VAL(break_info.fnum, 0);
4102         CHECK_VAL(break_info.failures, 0);
4103
4104         smbcli_close(cli1->tree, fnum);
4105         smbcli_close(cli2->tree, fnum2);
4106
4107 done:
4108         smb_raw_exit(cli1->session);
4109         smb_raw_exit(cli2->session);
4110         smbcli_deltree(cli1->tree, BASEDIR);
4111         return ret;
4112
4113 }
4114
4115 /* Open a file with a batch oplock on one client and then acquire a brl.
4116  * We should not contend our own oplock.
4117  */
4118 static bool test_raw_oplock_brl2(struct torture_context *tctx, struct smbcli_state *cli1)
4119 {
4120         const char *fname = BASEDIR "\\test_batch_brl.dat";
4121         /*int fname, f;*/
4122         bool ret = true;
4123         uint8_t buf[1000];
4124         union smb_open io;
4125         NTSTATUS status;
4126         uint16_t fnum=0;
4127
4128         if (!torture_setup_dir(cli1, BASEDIR)) {
4129                 return false;
4130         }
4131
4132         /* cleanup */
4133         smbcli_unlink(cli1->tree, fname);
4134
4135         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
4136                               cli1->tree);
4137
4138         /*
4139           base ntcreatex parms
4140         */
4141         io.generic.level = RAW_OPEN_NTCREATEX;
4142         io.ntcreatex.in.root_fid.fnum = 0;
4143         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
4144                                       SEC_RIGHTS_FILE_WRITE;
4145         io.ntcreatex.in.alloc_size = 0;
4146         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4147         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
4148                                        NTCREATEX_SHARE_ACCESS_WRITE;
4149         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4150         io.ntcreatex.in.create_options = 0;
4151         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4152         io.ntcreatex.in.security_flags = 0;
4153         io.ntcreatex.in.fname = fname;
4154
4155         /*
4156           with a batch oplock we get a break
4157         */
4158         torture_comment(tctx, "open with batch oplock\n");
4159         ZERO_STRUCT(break_info);
4160         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4161                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
4162                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4163
4164         status = smb_raw_open(cli1->tree, tctx, &io);
4165         CHECK_STATUS(tctx, status, NT_STATUS_OK);
4166         fnum = io.ntcreatex.out.file.fnum;
4167         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
4168
4169         /* create a file with bogus data */
4170         memset(buf, 0, sizeof(buf));
4171
4172         if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
4173                          sizeof(buf))
4174         {
4175                 torture_comment(tctx, "Failed to create file\n");
4176                 goto done;
4177         }
4178
4179         torture_comment(tctx, "a self BRL acquisition should not break to "
4180                         "none\n");
4181
4182         status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
4183         CHECK_STATUS(tctx, status, NT_STATUS_OK);
4184
4185         status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
4186         CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
4187
4188         /* With one file handle open a BRL should not contend our oplock.
4189          * Thus, no oplock break will be received and the entire break_info
4190          * struct will be 0 */
4191         torture_wait_for_oplock_break(tctx);
4192         CHECK_VAL(break_info.fnum, 0);
4193         CHECK_VAL(break_info.count, 0);
4194         CHECK_VAL(break_info.level, 0);
4195         CHECK_VAL(break_info.failures, 0);
4196
4197         smbcli_close(cli1->tree, fnum);
4198
4199 done:
4200         smb_raw_exit(cli1->session);
4201         smbcli_deltree(cli1->tree, BASEDIR);
4202         return ret;
4203 }
4204
4205 /* Open a file with a batch oplock twice from one client and then acquire a
4206  * brl. BRL acquisition should break our own oplock.
4207  */
4208 static bool test_raw_oplock_brl3(struct torture_context *tctx,
4209                                  struct smbcli_state *cli1)
4210 {
4211         const char *fname = BASEDIR "\\test_batch_brl.dat";
4212         bool ret = true;
4213         uint8_t buf[1000];
4214         union smb_open io;
4215         NTSTATUS status;
4216         uint16_t fnum=0;
4217         uint16_t fnum2=0;
4218
4219         if (!torture_setup_dir(cli1, BASEDIR)) {
4220                 return false;
4221         }
4222
4223         /* cleanup */
4224         smbcli_unlink(cli1->tree, fname);
4225
4226         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
4227                               cli1->tree);
4228
4229         /*
4230           base ntcreatex parms
4231         */
4232         io.generic.level = RAW_OPEN_NTCREATEX;
4233         io.ntcreatex.in.root_fid.fnum = 0;
4234         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
4235                                       SEC_RIGHTS_FILE_WRITE;
4236         io.ntcreatex.in.alloc_size = 0;
4237         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4238         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
4239                                        NTCREATEX_SHARE_ACCESS_WRITE;
4240         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4241         io.ntcreatex.in.create_options = 0;
4242         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4243         io.ntcreatex.in.security_flags = 0;
4244         io.ntcreatex.in.fname = fname;
4245
4246         /*
4247           with a batch oplock we get a break
4248         */
4249         torture_comment(tctx, "open with batch oplock\n");
4250         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4251                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
4252                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4253
4254         status = smb_raw_open(cli1->tree, tctx, &io);
4255         CHECK_STATUS(tctx, status, NT_STATUS_OK);
4256         fnum = io.ntcreatex.out.file.fnum;
4257         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
4258
4259         /* create a file with bogus data */
4260         memset(buf, 0, sizeof(buf));
4261
4262         if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
4263                          sizeof(buf))
4264         {
4265                 torture_comment(tctx, "Failed to create file\n");
4266                 ret = false;
4267                 goto done;
4268         }
4269
4270         torture_comment(tctx, "a 2nd open should give a break\n");
4271         ZERO_STRUCT(break_info);
4272
4273         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
4274         status = smb_raw_open(cli1->tree, tctx, &io);
4275         fnum2 = io.ntcreatex.out.file.fnum;
4276         CHECK_STATUS(tctx, status, NT_STATUS_OK);
4277         CHECK_VAL(break_info.count, 1);
4278         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
4279         CHECK_VAL(break_info.failures, 0);
4280         CHECK_VAL(break_info.fnum, fnum);
4281
4282         ZERO_STRUCT(break_info);
4283
4284         torture_comment(tctx, "a self BRL acquisition should break to none\n");
4285
4286         status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
4287         CHECK_STATUS(tctx, status, NT_STATUS_OK);
4288
4289         torture_wait_for_oplock_break(tctx);
4290         CHECK_VAL(break_info.count, 1);
4291         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
4292         CHECK_VAL(break_info.fnum, fnum);
4293         CHECK_VAL(break_info.failures, 0);
4294
4295         /* expect no oplock break */
4296         ZERO_STRUCT(break_info);
4297         status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
4298         CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
4299
4300         torture_wait_for_oplock_break(tctx);
4301         CHECK_VAL(break_info.count, 0);
4302         CHECK_VAL(break_info.level, 0);
4303         CHECK_VAL(break_info.fnum, 0);
4304         CHECK_VAL(break_info.failures, 0);
4305
4306         smbcli_close(cli1->tree, fnum);
4307         smbcli_close(cli1->tree, fnum2);
4308
4309 done:
4310         smb_raw_exit(cli1->session);
4311         smbcli_deltree(cli1->tree, BASEDIR);
4312         return ret;
4313 }
4314
4315 /*
4316  * Open a file with an exclusive oplock from the 1st client and acquire a
4317  * brl. Then open the same file from the 2nd client that should give oplock
4318  * break with level2 to the 1st and return no oplock to the 2nd.
4319  */
4320 static bool test_raw_oplock_brl4(struct torture_context *tctx,
4321                                  struct smbcli_state *cli1,
4322                                  struct smbcli_state *cli2)
4323 {
4324         const char *fname = BASEDIR "\\test_batch_brl.dat";
4325         bool ret = true;
4326         uint8_t buf[1000];
4327         union smb_open io;
4328         NTSTATUS status;
4329         uint16_t fnum = 0;
4330         uint16_t fnum2 = 0;
4331
4332         if (!torture_setup_dir(cli1, BASEDIR)) {
4333                 return false;
4334         }
4335
4336         /* cleanup */
4337         smbcli_unlink(cli1->tree, fname);
4338
4339         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
4340                               cli1->tree);
4341
4342         /*
4343           base ntcreatex parms
4344         */
4345         io.generic.level = RAW_OPEN_NTCREATEX;
4346         io.ntcreatex.in.root_fid.fnum = 0;
4347         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
4348                                       SEC_RIGHTS_FILE_WRITE;
4349         io.ntcreatex.in.alloc_size = 0;
4350         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4351         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
4352                                        NTCREATEX_SHARE_ACCESS_WRITE;
4353         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4354         io.ntcreatex.in.create_options = 0;
4355         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4356         io.ntcreatex.in.security_flags = 0;
4357         io.ntcreatex.in.fname = fname;
4358
4359         torture_comment(tctx, "open with exclusive oplock\n");
4360         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4361                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
4362
4363         status = smb_raw_open(cli1->tree, tctx, &io);
4364
4365         CHECK_STATUS(tctx, status, NT_STATUS_OK);
4366         fnum = io.ntcreatex.out.file.fnum;
4367         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
4368
4369         /* create a file with bogus data */
4370         memset(buf, 0, sizeof(buf));
4371
4372         if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
4373                          sizeof(buf))
4374         {
4375                 torture_comment(tctx, "Failed to create file\n");
4376                 goto done;
4377         }
4378
4379         status = smbcli_lock(cli1->tree, fnum, 0, 1, 0, WRITE_LOCK);
4380         CHECK_STATUS(tctx, status, NT_STATUS_OK);
4381
4382         torture_comment(tctx, "a 2nd open should give a break to the 1st\n");
4383         ZERO_STRUCT(break_info);
4384
4385         status = smb_raw_open(cli2->tree, tctx, &io);
4386
4387         CHECK_STATUS(tctx, status, NT_STATUS_OK);
4388         CHECK_VAL(break_info.count, 1);
4389         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
4390         CHECK_VAL(break_info.failures, 0);
4391         CHECK_VAL(break_info.fnum, fnum);
4392
4393         torture_comment(tctx, "and return no oplock to the 2nd\n");
4394         fnum2 = io.ntcreatex.out.file.fnum;
4395         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
4396
4397         smbcli_close(cli1->tree, fnum);
4398         smbcli_close(cli2->tree, fnum2);
4399
4400 done:
4401         smb_raw_exit(cli1->session);
4402         smb_raw_exit(cli2->session);
4403         smbcli_deltree(cli1->tree, BASEDIR);
4404         return ret;
4405 }
4406
4407 /*
4408    basic testing of oplocks
4409 */
4410 struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
4411 {
4412         struct torture_suite *suite = torture_suite_create(mem_ctx, "oplock");
4413
4414         torture_suite_add_2smb_test(suite, "exclusive1", test_raw_oplock_exclusive1);
4415         torture_suite_add_2smb_test(suite, "exclusive2", test_raw_oplock_exclusive2);
4416         torture_suite_add_2smb_test(suite, "exclusive3", test_raw_oplock_exclusive3);
4417         torture_suite_add_2smb_test(suite, "exclusive4", test_raw_oplock_exclusive4);
4418         torture_suite_add_2smb_test(suite, "exclusive5", test_raw_oplock_exclusive5);
4419         torture_suite_add_2smb_test(suite, "exclusive6", test_raw_oplock_exclusive6);
4420         torture_suite_add_2smb_test(suite, "exclusive7", test_raw_oplock_exclusive7);
4421         torture_suite_add_2smb_test(suite, "exclusive8",
4422                                     test_raw_oplock_exclusive8);
4423         torture_suite_add_2smb_test(suite, "exclusive9",
4424                                     test_raw_oplock_exclusive9);
4425         torture_suite_add_2smb_test(suite, "level_ii_1",
4426                                     test_raw_oplock_level_ii_1);
4427         torture_suite_add_2smb_test(suite, "batch1", test_raw_oplock_batch1);
4428         torture_suite_add_2smb_test(suite, "batch2", test_raw_oplock_batch2);
4429         torture_suite_add_2smb_test(suite, "batch3", test_raw_oplock_batch3);
4430         torture_suite_add_2smb_test(suite, "batch4", test_raw_oplock_batch4);
4431         torture_suite_add_2smb_test(suite, "batch5", test_raw_oplock_batch5);
4432         torture_suite_add_2smb_test(suite, "batch6", test_raw_oplock_batch6);
4433         torture_suite_add_2smb_test(suite, "batch7", test_raw_oplock_batch7);
4434         torture_suite_add_2smb_test(suite, "batch8", test_raw_oplock_batch8);
4435         torture_suite_add_2smb_test(suite, "batch9", test_raw_oplock_batch9);
4436         torture_suite_add_2smb_test(suite, "batch9a", test_raw_oplock_batch9a);
4437         torture_suite_add_2smb_test(suite, "batch10", test_raw_oplock_batch10);
4438         torture_suite_add_2smb_test(suite, "batch11", test_raw_oplock_batch11);
4439         torture_suite_add_2smb_test(suite, "batch12", test_raw_oplock_batch12);
4440         torture_suite_add_2smb_test(suite, "batch13", test_raw_oplock_batch13);
4441         torture_suite_add_2smb_test(suite, "batch14", test_raw_oplock_batch14);
4442         torture_suite_add_2smb_test(suite, "batch15", test_raw_oplock_batch15);
4443         torture_suite_add_2smb_test(suite, "batch16", test_raw_oplock_batch16);
4444         torture_suite_add_2smb_test(suite, "batch17", test_raw_oplock_batch17);
4445         torture_suite_add_2smb_test(suite, "batch18", test_raw_oplock_batch18);
4446         torture_suite_add_2smb_test(suite, "batch19", test_raw_oplock_batch19);
4447         torture_suite_add_2smb_test(suite, "batch20", test_raw_oplock_batch20);
4448         torture_suite_add_2smb_test(suite, "batch21", test_raw_oplock_batch21);
4449         torture_suite_add_2smb_test(suite, "batch22", test_raw_oplock_batch22);
4450         torture_suite_add_2smb_test(suite, "batch23", test_raw_oplock_batch23);
4451         torture_suite_add_2smb_test(suite, "batch24", test_raw_oplock_batch24);
4452         torture_suite_add_2smb_test(suite, "batch25", test_raw_oplock_batch25);
4453         torture_suite_add_2smb_test(suite, "batch26", test_raw_oplock_batch26);
4454         torture_suite_add_2smb_test(suite, "stream1", test_raw_oplock_stream1);
4455         torture_suite_add_2smb_test(suite, "doc1", test_raw_oplock_doc);
4456         torture_suite_add_2smb_test(suite, "brl1", test_raw_oplock_brl1);
4457         torture_suite_add_1smb_test(suite, "brl2", test_raw_oplock_brl2);
4458         torture_suite_add_1smb_test(suite, "brl3", test_raw_oplock_brl3);
4459         torture_suite_add_2smb_test(suite, "brl4", test_raw_oplock_brl4);
4460
4461         return suite;
4462 }
4463
4464 /*
4465    stress testing of oplocks
4466 */
4467 bool torture_bench_oplock(struct torture_context *torture)
4468 {
4469         struct smbcli_state **cli;
4470         bool ret = true;
4471         TALLOC_CTX *mem_ctx = talloc_new(torture);
4472         int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
4473         int i, count=0;
4474         int timelimit = torture_setting_int(torture, "timelimit", 10);
4475         union smb_open io;
4476         struct timeval tv;
4477
4478         cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
4479
4480         torture_comment(torture, "Opening %d connections\n", torture_nprocs);
4481         for (i=0;i<torture_nprocs;i++) {
4482                 if (!torture_open_connection_ev(&cli[i], i, torture, torture->ev)) {
4483                         return false;
4484                 }
4485                 talloc_steal(mem_ctx, cli[i]);
4486                 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close, 
4487                                       cli[i]->tree);
4488         }
4489
4490         if (!torture_setup_dir(cli[0], BASEDIR)) {
4491                 ret = false;
4492                 goto done;
4493         }
4494
4495         io.ntcreatex.level = RAW_OPEN_NTCREATEX;
4496         io.ntcreatex.in.root_fid.fnum = 0;
4497         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
4498         io.ntcreatex.in.alloc_size = 0;
4499         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4500         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
4501         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4502         io.ntcreatex.in.create_options = 0;
4503         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4504         io.ntcreatex.in.security_flags = 0;
4505         io.ntcreatex.in.fname = BASEDIR "\\test.dat";
4506         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
4507                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
4508                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4509
4510         tv = timeval_current(); 
4511
4512         /*
4513           we open the same file with SHARE_ACCESS_NONE from all the
4514           connections in a round robin fashion. Each open causes an
4515           oplock break on the previous connection, which is answered
4516           by the oplock_handler_close() to close the file.
4517
4518           This measures how fast we can pass on oplocks, and stresses
4519           the oplock handling code
4520         */
4521         torture_comment(torture, "Running for %d seconds\n", timelimit);
4522         while (timeval_elapsed(&tv) < timelimit) {
4523                 for (i=0;i<torture_nprocs;i++) {
4524                         NTSTATUS status;
4525
4526                         status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
4527                         CHECK_STATUS(torture, status, NT_STATUS_OK);
4528                         count++;
4529                 }
4530
4531                 if (torture_setting_bool(torture, "progress", true)) {
4532                         torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
4533                 }
4534         }
4535
4536         torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
4537
4538         smb_raw_exit(cli[torture_nprocs-1]->session);
4539         
4540 done:
4541         smb_raw_exit(cli[0]->session);
4542         smbcli_deltree(cli[0]->tree, BASEDIR);
4543         talloc_free(mem_ctx);
4544         return ret;
4545 }
4546
4547
4548 static struct hold_oplock_info {
4549         const char *fname;
4550         bool close_on_break;
4551         uint32_t share_access;
4552         uint16_t fnum;
4553 } hold_info[] = {
4554         {
4555                 .fname          = BASEDIR "\\notshared_close",
4556                 .close_on_break = true,
4557                 .share_access   = NTCREATEX_SHARE_ACCESS_NONE,
4558         },
4559         {
4560                 .fname          = BASEDIR "\\notshared_noclose",
4561                 .close_on_break = false,
4562                 .share_access   = NTCREATEX_SHARE_ACCESS_NONE,
4563         },
4564         {
4565                 .fname          = BASEDIR "\\shared_close",
4566                 .close_on_break = true,
4567                 .share_access   = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
4568         },
4569         {
4570                 .fname          = BASEDIR "\\shared_noclose",
4571                 .close_on_break = false,
4572                 .share_access   = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
4573         },
4574 };
4575
4576 static bool oplock_handler_hold(struct smbcli_transport *transport, 
4577                                 uint16_t tid, uint16_t fnum, uint8_t level, 
4578                                 void *private_data)
4579 {
4580         struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
4581         struct hold_oplock_info *info;
4582         int i;
4583
4584         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4585                 if (hold_info[i].fnum == fnum) break;
4586         }
4587
4588         if (i == ARRAY_SIZE(hold_info)) {
4589                 printf("oplock break for unknown fnum %u\n", fnum);
4590                 return false;
4591         }
4592
4593         info = &hold_info[i];
4594
4595         if (info->close_on_break) {
4596                 printf("oplock break on %s - closing\n",
4597                        info->fname);
4598                 oplock_handler_close(transport, tid, fnum, level, private_data);
4599                 return true;
4600         }
4601
4602         printf("oplock break on %s - acking break\n", info->fname);
4603
4604         return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
4605 }
4606
4607
4608 /* 
4609    used for manual testing of oplocks - especially interaction with
4610    other filesystems (such as NFS and local access)
4611 */
4612 bool torture_hold_oplock(struct torture_context *torture, 
4613                          struct smbcli_state *cli)
4614 {
4615         struct tevent_context *ev = torture->ev;
4616         int i;
4617
4618         printf("Setting up open files with oplocks in %s\n", BASEDIR);
4619
4620         torture_assert(torture, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
4621
4622         smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
4623
4624         /* setup the files */
4625         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4626                 union smb_open io;
4627                 NTSTATUS status;
4628                 char c = 1;
4629
4630                 io.generic.level = RAW_OPEN_NTCREATEX;
4631                 io.ntcreatex.in.root_fid.fnum = 0;
4632                 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
4633                 io.ntcreatex.in.alloc_size = 0;
4634                 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4635                 io.ntcreatex.in.share_access = hold_info[i].share_access;
4636                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4637                 io.ntcreatex.in.create_options = 0;
4638                 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4639                 io.ntcreatex.in.security_flags = 0;
4640                 io.ntcreatex.in.fname = hold_info[i].fname;
4641                 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
4642                         NTCREATEX_FLAGS_REQUEST_OPLOCK |
4643                         NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4644                 printf("opening %s\n", hold_info[i].fname);
4645
4646                 status = smb_raw_open(cli->tree, cli, &io);
4647                 if (!NT_STATUS_IS_OK(status)) {
4648                         printf("Failed to open %s - %s\n", 
4649                                hold_info[i].fname, nt_errstr(status));
4650                         return false;
4651                 }
4652
4653                 if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
4654                         printf("Oplock not granted for %s - expected %d but got %d\n", 
4655                                hold_info[i].fname, BATCH_OPLOCK_RETURN, 
4656                                 io.ntcreatex.out.oplock_level);
4657                         return false;
4658                 }
4659                 hold_info[i].fnum = io.ntcreatex.out.file.fnum;
4660
4661                 /* make the file non-zero size */
4662                 if (smbcli_write(cli->tree, hold_info[i].fnum, 0, &c, 0, 1) != 1) {
4663                         printf("Failed to write to file\n");
4664                         return false;
4665                 }
4666         }
4667
4668         printf("Waiting for oplock events\n");
4669         tevent_loop_wait(ev);
4670
4671         return true;
4672 }