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