smbtorture: Test that delete requests are not special
[metze/samba/wip.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_exclusive8(struct torture_context *tctx,
871                                        struct smbcli_state *cli1,
872                                        struct smbcli_state *cli2)
873 {
874         const char *fname = BASEDIR "\\test_exclusive8.dat";
875         NTSTATUS status;
876         bool ret = true;
877         union smb_open io;
878         uint16_t fnum1 = 0;
879         uint16_t fnum2 = 0;
880         uint16_t fnum3 = 0;
881
882         if (!torture_setup_dir(cli1, BASEDIR)) {
883                 return false;
884         }
885
886         /* cleanup */
887         smbcli_unlink(cli1->tree, fname);
888
889         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
890                               cli1->tree);
891
892         /*
893           base ntcreatex parms
894         */
895         io.generic.level = RAW_OPEN_NTCREATEX;
896         io.ntcreatex.in.root_fid.fnum = 0;
897         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
898         io.ntcreatex.in.alloc_size = 0;
899         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
900         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
901                 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
902         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
903         io.ntcreatex.in.create_options = 0;
904         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
905         io.ntcreatex.in.security_flags = 0;
906         io.ntcreatex.in.fname = fname;
907
908         torture_comment(tctx, "open a file with an exclusive oplock (share "
909                         "mode: all)\n");
910         ZERO_STRUCT(break_info);
911         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
912                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
913         status = smb_raw_open(cli1->tree, tctx, &io);
914         CHECK_STATUS(tctx, status, NT_STATUS_OK);
915         fnum1 = io.ntcreatex.out.file.fnum;
916         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
917
918         torture_comment(tctx, "second open with delete should trigger a "
919                         "break\n");
920
921         io.ntcreatex.in.access_mask = SEC_STD_DELETE;
922         io.ntcreatex.in.flags = 0;
923         status = smb_raw_open(cli2->tree, tctx, &io);
924         CHECK_STATUS(tctx, status, NT_STATUS_OK);
925         fnum2 = io.ntcreatex.out.file.fnum;
926         CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
927         CHECK_VAL(break_info.failures, 0);
928         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
929
930         /* Trigger a little panic in "old" samba code.. */
931         status = smb_raw_open(cli2->tree, tctx, &io);
932         CHECK_STATUS(tctx, status, NT_STATUS_OK);
933         fnum3 = io.ntcreatex.out.file.fnum;
934
935         smbcli_close(cli2->tree, fnum3);
936         smbcli_close(cli2->tree, fnum2);
937         smbcli_close(cli1->tree, fnum1);
938
939 done:
940         smbcli_deltree(cli1->tree, BASEDIR);
941         smb_raw_exit(cli1->session);
942         smb_raw_exit(cli2->session);
943         return ret;
944 }
945
946 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
947 {
948         const char *fname = BASEDIR "\\test_batch1.dat";
949         NTSTATUS status;
950         bool ret = true;
951         union smb_open io;
952         union smb_unlink unl;
953         uint16_t fnum=0;
954         char c = 0;
955
956         if (!torture_setup_dir(cli1, BASEDIR)) {
957                 return false;
958         }
959
960         /* cleanup */
961         smbcli_unlink(cli1->tree, fname);
962
963         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
964
965         /*
966           base ntcreatex parms
967         */
968         io.generic.level = RAW_OPEN_NTCREATEX;
969         io.ntcreatex.in.root_fid.fnum = 0;
970         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
971         io.ntcreatex.in.alloc_size = 0;
972         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
973         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
974         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
975         io.ntcreatex.in.create_options = 0;
976         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
977         io.ntcreatex.in.security_flags = 0;
978         io.ntcreatex.in.fname = fname;
979
980         /*
981           with a batch oplock we get a break
982         */
983         torture_comment(tctx, "BATCH1: open with batch oplock\n");
984         ZERO_STRUCT(break_info);
985         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
986                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
987                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
988         status = smb_raw_open(cli1->tree, tctx, &io);
989         CHECK_STATUS(tctx, status, NT_STATUS_OK);
990         fnum = io.ntcreatex.out.file.fnum;
991         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
992
993         torture_comment(tctx, "unlink should generate a break\n");
994         unl.unlink.in.pattern = fname;
995         unl.unlink.in.attrib = 0;
996         status = smb_raw_unlink(cli2->tree, &unl);
997         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
998
999         torture_wait_for_oplock_break(tctx);
1000         CHECK_VAL(break_info.count, 1);
1001         CHECK_VAL(break_info.fnum, fnum);
1002         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1003         CHECK_VAL(break_info.failures, 0);
1004
1005         torture_comment(tctx, "2nd unlink should not generate a break\n");
1006         ZERO_STRUCT(break_info);
1007         status = smb_raw_unlink(cli2->tree, &unl);
1008         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1009
1010         torture_wait_for_oplock_break(tctx);
1011         CHECK_VAL(break_info.count, 0);
1012
1013         torture_comment(tctx, "writing should generate a self break to none\n");
1014         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1015
1016         torture_wait_for_oplock_break(tctx);
1017         torture_wait_for_oplock_break(tctx);
1018         CHECK_VAL(break_info.count, 1);
1019         CHECK_VAL(break_info.fnum, fnum);
1020         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
1021         CHECK_VAL(break_info.failures, 0);
1022
1023         smbcli_close(cli1->tree, fnum);
1024
1025 done:
1026         smb_raw_exit(cli1->session);
1027         smb_raw_exit(cli2->session);
1028         smbcli_deltree(cli1->tree, BASEDIR);
1029         return ret;
1030 }
1031
1032 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1033 {
1034         const char *fname = BASEDIR "\\test_batch2.dat";
1035         NTSTATUS status;
1036         bool ret = true;
1037         union smb_open io;
1038         union smb_unlink unl;
1039         uint16_t fnum=0;
1040         char c = 0;
1041
1042         if (!torture_setup_dir(cli1, BASEDIR)) {
1043                 return false;
1044         }
1045
1046         /* cleanup */
1047         smbcli_unlink(cli1->tree, fname);
1048
1049         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1050
1051         /*
1052           base ntcreatex parms
1053         */
1054         io.generic.level = RAW_OPEN_NTCREATEX;
1055         io.ntcreatex.in.root_fid.fnum = 0;
1056         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1057         io.ntcreatex.in.alloc_size = 0;
1058         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1059         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1060         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1061         io.ntcreatex.in.create_options = 0;
1062         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1063         io.ntcreatex.in.security_flags = 0;
1064         io.ntcreatex.in.fname = fname;
1065
1066         torture_comment(tctx, "BATCH2: open with batch oplock\n");
1067         ZERO_STRUCT(break_info);
1068         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1069                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1070                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1071         status = smb_raw_open(cli1->tree, tctx, &io);
1072         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1073         fnum = io.ntcreatex.out.file.fnum;
1074         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1075
1076         torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
1077         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
1078         unl.unlink.in.pattern = fname;
1079         unl.unlink.in.attrib = 0;
1080         status = smb_raw_unlink(cli2->tree, &unl);
1081         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1082
1083         torture_wait_for_oplock_break(tctx);
1084         CHECK_VAL(break_info.count, 1);
1085         CHECK_VAL(break_info.fnum, fnum);
1086         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1087         CHECK_VAL(break_info.failures, 0);
1088
1089         torture_comment(tctx, "2nd unlink should not generate a break\n");
1090         ZERO_STRUCT(break_info);
1091         status = smb_raw_unlink(cli2->tree, &unl);
1092         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1093
1094         torture_wait_for_oplock_break(tctx);
1095         CHECK_VAL(break_info.count, 0);
1096
1097         torture_comment(tctx, "writing should not generate a break\n");
1098         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1099
1100         torture_wait_for_oplock_break(tctx);
1101         CHECK_VAL(break_info.count, 0);
1102
1103         smbcli_close(cli1->tree, fnum);
1104
1105 done:
1106         smb_raw_exit(cli1->session);
1107         smb_raw_exit(cli2->session);
1108         smbcli_deltree(cli1->tree, BASEDIR);
1109         return ret;
1110 }
1111
1112 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1113 {
1114         const char *fname = BASEDIR "\\test_batch3.dat";
1115         NTSTATUS status;
1116         bool ret = true;
1117         union smb_open io;
1118         union smb_unlink unl;
1119         uint16_t fnum=0;
1120
1121         if (!torture_setup_dir(cli1, BASEDIR)) {
1122                 return false;
1123         }
1124
1125         /* cleanup */
1126         smbcli_unlink(cli1->tree, fname);
1127
1128         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1129
1130         /*
1131           base ntcreatex parms
1132         */
1133         io.generic.level = RAW_OPEN_NTCREATEX;
1134         io.ntcreatex.in.root_fid.fnum = 0;
1135         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1136         io.ntcreatex.in.alloc_size = 0;
1137         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1138         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1139         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1140         io.ntcreatex.in.create_options = 0;
1141         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1142         io.ntcreatex.in.security_flags = 0;
1143         io.ntcreatex.in.fname = fname;
1144
1145         torture_comment(tctx, "BATCH3: if we close on break then the unlink can succeed\n");
1146         ZERO_STRUCT(break_info);
1147         smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1148         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1149                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1150                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1151         status = smb_raw_open(cli1->tree, tctx, &io);
1152         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1153         fnum = io.ntcreatex.out.file.fnum;
1154         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1155
1156         unl.unlink.in.pattern = fname;
1157         unl.unlink.in.attrib = 0;
1158         ZERO_STRUCT(break_info);
1159         status = smb_raw_unlink(cli2->tree, &unl);
1160         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1161
1162         torture_wait_for_oplock_break(tctx);
1163         CHECK_VAL(break_info.count, 1);
1164         CHECK_VAL(break_info.fnum, fnum);
1165         CHECK_VAL(break_info.level, 1);
1166         CHECK_VAL(break_info.failures, 0);
1167
1168         smbcli_close(cli1->tree, fnum);
1169
1170 done:
1171         smb_raw_exit(cli1->session);
1172         smb_raw_exit(cli2->session);
1173         smbcli_deltree(cli1->tree, BASEDIR);
1174         return ret;
1175 }
1176
1177 static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1178 {
1179         const char *fname = BASEDIR "\\test_batch4.dat";
1180         NTSTATUS status;
1181         bool ret = true;
1182         union smb_open io;
1183         union smb_read rd;
1184         uint16_t fnum=0;
1185
1186         if (!torture_setup_dir(cli1, BASEDIR)) {
1187                 return false;
1188         }
1189
1190         /* cleanup */
1191         smbcli_unlink(cli1->tree, fname);
1192
1193         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1194
1195         /*
1196           base ntcreatex parms
1197         */
1198         io.generic.level = RAW_OPEN_NTCREATEX;
1199         io.ntcreatex.in.root_fid.fnum = 0;
1200         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1201         io.ntcreatex.in.alloc_size = 0;
1202         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1203         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1204         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1205         io.ntcreatex.in.create_options = 0;
1206         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1207         io.ntcreatex.in.security_flags = 0;
1208         io.ntcreatex.in.fname = fname;
1209
1210         torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
1211         ZERO_STRUCT(break_info);
1212         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1213
1214         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1215                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1216                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1217         status = smb_raw_open(cli1->tree, tctx, &io);
1218         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1219         fnum = io.ntcreatex.out.file.fnum;
1220         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1221
1222         rd.readx.level = RAW_READ_READX;
1223         rd.readx.in.file.fnum = fnum;
1224         rd.readx.in.mincnt = 1;
1225         rd.readx.in.maxcnt = 1;
1226         rd.readx.in.offset = 0;
1227         rd.readx.in.remaining = 0;
1228         rd.readx.in.read_for_execute = false;
1229         status = smb_raw_read(cli1->tree, &rd);
1230         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1231         torture_wait_for_oplock_break(tctx);
1232         CHECK_VAL(break_info.count, 0);
1233         CHECK_VAL(break_info.failures, 0);
1234
1235         smbcli_close(cli1->tree, fnum);
1236
1237 done:
1238         smb_raw_exit(cli1->session);
1239         smb_raw_exit(cli2->session);
1240         smbcli_deltree(cli1->tree, BASEDIR);
1241         return ret;
1242 }
1243
1244 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1245 {
1246         const char *fname = BASEDIR "\\test_batch5.dat";
1247         NTSTATUS status;
1248         bool ret = true;
1249         union smb_open io;
1250         uint16_t fnum=0;
1251
1252         if (!torture_setup_dir(cli1, BASEDIR)) {
1253                 return false;
1254         }
1255
1256         /* cleanup */
1257         smbcli_unlink(cli1->tree, fname);
1258
1259         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1260
1261         /*
1262           base ntcreatex parms
1263         */
1264         io.generic.level = RAW_OPEN_NTCREATEX;
1265         io.ntcreatex.in.root_fid.fnum = 0;
1266         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1267         io.ntcreatex.in.alloc_size = 0;
1268         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1269         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1270         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1271         io.ntcreatex.in.create_options = 0;
1272         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1273         io.ntcreatex.in.security_flags = 0;
1274         io.ntcreatex.in.fname = fname;
1275
1276         torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1277         ZERO_STRUCT(break_info);
1278         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1279
1280         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1281                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1282                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1283         status = smb_raw_open(cli1->tree, tctx, &io);
1284         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1285         fnum = io.ntcreatex.out.file.fnum;
1286         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1287
1288         ZERO_STRUCT(break_info);
1289
1290         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1291         status = smb_raw_open(cli2->tree, tctx, &io);
1292         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1293
1294         torture_wait_for_oplock_break(tctx);
1295         CHECK_VAL(break_info.count, 1);
1296         CHECK_VAL(break_info.fnum, fnum);
1297         CHECK_VAL(break_info.level, 1);
1298         CHECK_VAL(break_info.failures, 0);
1299
1300         smbcli_close(cli1->tree, fnum);
1301
1302 done:
1303         smb_raw_exit(cli1->session);
1304         smb_raw_exit(cli2->session);
1305         smbcli_deltree(cli1->tree, BASEDIR);
1306         return ret;
1307 }
1308
1309 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1310 {
1311         const char *fname = BASEDIR "\\test_batch6.dat";
1312         NTSTATUS status;
1313         bool ret = true;
1314         union smb_open io;
1315         uint16_t fnum=0, fnum2=0;
1316         char c = 0;
1317
1318         if (!torture_setup_dir(cli1, BASEDIR)) {
1319                 return false;
1320         }
1321
1322         /* cleanup */
1323         smbcli_unlink(cli1->tree, fname);
1324
1325         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1326         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1327
1328         /*
1329           base ntcreatex parms
1330         */
1331         io.generic.level = RAW_OPEN_NTCREATEX;
1332         io.ntcreatex.in.root_fid.fnum = 0;
1333         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1334         io.ntcreatex.in.alloc_size = 0;
1335         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1336         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1337         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1338         io.ntcreatex.in.create_options = 0;
1339         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1340         io.ntcreatex.in.security_flags = 0;
1341         io.ntcreatex.in.fname = fname;
1342
1343         torture_comment(tctx, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1344         ZERO_STRUCT(break_info);
1345
1346         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
1347         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1348         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1349                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1350                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1351         status = smb_raw_open(cli1->tree, tctx, &io);
1352         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1353         fnum = io.ntcreatex.out.file.fnum;
1354         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1355
1356         ZERO_STRUCT(break_info);
1357
1358         status = smb_raw_open(cli2->tree, tctx, &io);
1359         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1360         fnum2 = io.ntcreatex.out.file.fnum;
1361         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1362
1363         //torture_wait_for_oplock_break(tctx);
1364         CHECK_VAL(break_info.count, 1);
1365         CHECK_VAL(break_info.fnum, fnum);
1366         CHECK_VAL(break_info.level, 1);
1367         CHECK_VAL(break_info.failures, 0);
1368         ZERO_STRUCT(break_info);
1369
1370         torture_comment(tctx, "write should trigger a break to none on both\n");
1371         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1372
1373         /* We expect two breaks */
1374         torture_wait_for_oplock_break(tctx);
1375         torture_wait_for_oplock_break(tctx);
1376
1377         CHECK_VAL(break_info.count, 2);
1378         CHECK_VAL(break_info.level, 0);
1379         CHECK_VAL(break_info.failures, 0);
1380
1381         smbcli_close(cli1->tree, fnum);
1382         smbcli_close(cli2->tree, fnum2);
1383
1384 done:
1385         smb_raw_exit(cli1->session);
1386         smb_raw_exit(cli2->session);
1387         smbcli_deltree(cli1->tree, BASEDIR);
1388         return ret;
1389 }
1390
1391 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1392 {
1393         const char *fname = BASEDIR "\\test_batch7.dat";
1394         NTSTATUS status;
1395         bool ret = true;
1396         union smb_open io;
1397         uint16_t fnum=0, fnum2=0;
1398
1399         if (!torture_setup_dir(cli1, BASEDIR)) {
1400                 return false;
1401         }
1402
1403         /* cleanup */
1404         smbcli_unlink(cli1->tree, fname);
1405
1406         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1407
1408         /*
1409           base ntcreatex parms
1410         */
1411         io.generic.level = RAW_OPEN_NTCREATEX;
1412         io.ntcreatex.in.root_fid.fnum = 0;
1413         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1414         io.ntcreatex.in.alloc_size = 0;
1415         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1416         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1417         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1418         io.ntcreatex.in.create_options = 0;
1419         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1420         io.ntcreatex.in.security_flags = 0;
1421         io.ntcreatex.in.fname = fname;
1422
1423         torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1424         ZERO_STRUCT(break_info);
1425         smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1426
1427         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1428         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1429         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1430                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1431                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1432         status = smb_raw_open(cli1->tree, tctx, &io);
1433         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1434         fnum2 = io.ntcreatex.out.file.fnum;
1435         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1436
1437         ZERO_STRUCT(break_info);
1438
1439         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1440                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1441                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1442         status = smb_raw_open(cli2->tree, tctx, &io);
1443         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1444         fnum = io.ntcreatex.out.file.fnum;
1445         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1446
1447         torture_wait_for_oplock_break(tctx);
1448         CHECK_VAL(break_info.count, 1);
1449         CHECK_VAL(break_info.fnum, fnum2);
1450         CHECK_VAL(break_info.level, 1);
1451         CHECK_VAL(break_info.failures, 0);
1452
1453         smbcli_close(cli2->tree, fnum);
1454
1455 done:
1456         smb_raw_exit(cli1->session);
1457         smb_raw_exit(cli2->session);
1458         smbcli_deltree(cli1->tree, BASEDIR);
1459         return ret;
1460 }
1461
1462 static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1463 {
1464         const char *fname = BASEDIR "\\test_batch8.dat";
1465         NTSTATUS status;
1466         bool ret = true;
1467         union smb_open io;
1468         uint16_t fnum=0, fnum2=0;
1469
1470         if (!torture_setup_dir(cli1, BASEDIR)) {
1471                 return false;
1472         }
1473
1474         /* cleanup */
1475         smbcli_unlink(cli1->tree, fname);
1476
1477         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1478
1479         /*
1480           base ntcreatex parms
1481         */
1482         io.generic.level = RAW_OPEN_NTCREATEX;
1483         io.ntcreatex.in.root_fid.fnum = 0;
1484         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1485         io.ntcreatex.in.alloc_size = 0;
1486         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1487         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1488         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1489         io.ntcreatex.in.create_options = 0;
1490         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1491         io.ntcreatex.in.security_flags = 0;
1492         io.ntcreatex.in.fname = fname;
1493
1494         torture_comment(tctx, "BATCH8: open with batch oplock\n");
1495         ZERO_STRUCT(break_info);
1496         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1497
1498         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1499                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1500                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1501         status = smb_raw_open(cli1->tree, tctx, &io);
1502         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1503         fnum = io.ntcreatex.out.file.fnum;
1504         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1505
1506         ZERO_STRUCT(break_info);
1507         torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
1508
1509         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1510                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1511                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1512         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1513         status = smb_raw_open(cli2->tree, tctx, &io);
1514         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1515         fnum2 = io.ntcreatex.out.file.fnum;
1516         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1517         torture_wait_for_oplock_break(tctx);
1518         CHECK_VAL(break_info.count, 0);
1519         CHECK_VAL(break_info.failures, 0);
1520
1521         smbcli_close(cli1->tree, fnum);
1522         smbcli_close(cli2->tree, fnum2);
1523
1524 done:
1525         smb_raw_exit(cli1->session);
1526         smb_raw_exit(cli2->session);
1527         smbcli_deltree(cli1->tree, BASEDIR);
1528         return ret;
1529 }
1530
1531 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1532 {
1533         const char *fname = BASEDIR "\\test_batch9.dat";
1534         NTSTATUS status;
1535         bool ret = true;
1536         union smb_open io;
1537         uint16_t fnum=0, fnum2=0;
1538         char c = 0;
1539
1540         if (!torture_setup_dir(cli1, BASEDIR)) {
1541                 return false;
1542         }
1543
1544         /* cleanup */
1545         smbcli_unlink(cli1->tree, fname);
1546
1547         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1548
1549         /*
1550           base ntcreatex parms
1551         */
1552         io.generic.level = RAW_OPEN_NTCREATEX;
1553         io.ntcreatex.in.root_fid.fnum = 0;
1554         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1555         io.ntcreatex.in.alloc_size = 0;
1556         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1557         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1558         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1559         io.ntcreatex.in.create_options = 0;
1560         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1561         io.ntcreatex.in.security_flags = 0;
1562         io.ntcreatex.in.fname = fname;
1563
1564         torture_comment(tctx, "BATCH9: open with attributes only can create file\n");
1565
1566         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1567                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1568                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1569         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1570         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1571         status = smb_raw_open(cli1->tree, tctx, &io);
1572         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1573         fnum = io.ntcreatex.out.file.fnum;
1574         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1575
1576         torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
1577
1578         ZERO_STRUCT(break_info);
1579         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1580
1581         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1582                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1583                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1584         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1585         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1586         status = smb_raw_open(cli2->tree, tctx, &io);
1587         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1588         fnum2 = io.ntcreatex.out.file.fnum;
1589         torture_wait_for_oplock_break(tctx);
1590         CHECK_VAL(break_info.count, 1);
1591         CHECK_VAL(break_info.fnum, fnum);
1592         CHECK_VAL(break_info.failures, 0);
1593         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1594         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1595         smbcli_close(cli2->tree, fnum2);
1596
1597         torture_comment(tctx, "third oplocked open should grant level2 without break\n");
1598         ZERO_STRUCT(break_info);
1599         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1600         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1601         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1602                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1603                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1604         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1605         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1606         status = smb_raw_open(cli2->tree, tctx, &io);
1607         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1608         fnum2 = io.ntcreatex.out.file.fnum;
1609         torture_wait_for_oplock_break(tctx);
1610         CHECK_VAL(break_info.count, 0);
1611         CHECK_VAL(break_info.failures, 0);
1612         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1613
1614         ZERO_STRUCT(break_info);
1615
1616         torture_comment(tctx, "write should trigger a break to none on both\n");
1617         smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
1618
1619         /* We expect two breaks */
1620         torture_wait_for_oplock_break(tctx);
1621         torture_wait_for_oplock_break(tctx);
1622
1623         CHECK_VAL(break_info.count, 2);
1624         CHECK_VAL(break_info.level, 0);
1625         CHECK_VAL(break_info.failures, 0);
1626
1627         smbcli_close(cli1->tree, fnum);
1628         smbcli_close(cli2->tree, fnum2);
1629
1630 done:
1631         smb_raw_exit(cli1->session);
1632         smb_raw_exit(cli2->session);
1633         smbcli_deltree(cli1->tree, BASEDIR);
1634         return ret;
1635 }
1636
1637 static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1638 {
1639         const char *fname = BASEDIR "\\test_batch10.dat";
1640         NTSTATUS status;
1641         bool ret = true;
1642         union smb_open io;
1643         uint16_t fnum=0, fnum2=0;
1644
1645         if (!torture_setup_dir(cli1, BASEDIR)) {
1646                 return false;
1647         }
1648
1649         /* cleanup */
1650         smbcli_unlink(cli1->tree, fname);
1651
1652         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1653
1654         /*
1655           base ntcreatex parms
1656         */
1657         io.generic.level = RAW_OPEN_NTCREATEX;
1658         io.ntcreatex.in.root_fid.fnum = 0;
1659         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1660         io.ntcreatex.in.alloc_size = 0;
1661         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1662         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1663         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1664         io.ntcreatex.in.create_options = 0;
1665         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1666         io.ntcreatex.in.security_flags = 0;
1667         io.ntcreatex.in.fname = fname;
1668
1669         torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
1670         ZERO_STRUCT(break_info);
1671         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1672         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1673         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1674                 NTCREATEX_SHARE_ACCESS_WRITE|
1675                 NTCREATEX_SHARE_ACCESS_DELETE;
1676         status = smb_raw_open(cli1->tree, tctx, &io);
1677         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1678         fnum = io.ntcreatex.out.file.fnum;
1679         torture_wait_for_oplock_break(tctx);
1680         CHECK_VAL(break_info.count, 0);
1681         CHECK_VAL(break_info.failures, 0);
1682         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1683
1684         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1685
1686         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1687                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1688                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1689         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1690         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1691                 NTCREATEX_SHARE_ACCESS_WRITE|
1692                 NTCREATEX_SHARE_ACCESS_DELETE;
1693         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1694         status = smb_raw_open(cli2->tree, tctx, &io);
1695         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1696         fnum2 = io.ntcreatex.out.file.fnum;
1697         torture_wait_for_oplock_break(tctx);
1698         CHECK_VAL(break_info.count, 0);
1699         CHECK_VAL(break_info.failures, 0);
1700         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1701
1702         torture_comment(tctx, "write should trigger a break to none\n");
1703         {
1704                 union smb_write wr;
1705                 wr.write.level = RAW_WRITE_WRITE;
1706                 wr.write.in.file.fnum = fnum;
1707                 wr.write.in.count = 1;
1708                 wr.write.in.offset = 0;
1709                 wr.write.in.remaining = 0;
1710                 wr.write.in.data = (const uint8_t *)"x";
1711                 status = smb_raw_write(cli1->tree, &wr);
1712                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1713         }
1714
1715         torture_wait_for_oplock_break(tctx);
1716
1717         CHECK_VAL(break_info.count, 1);
1718         CHECK_VAL(break_info.fnum, fnum2);
1719         CHECK_VAL(break_info.level, 0);
1720         CHECK_VAL(break_info.failures, 0);
1721
1722         smbcli_close(cli1->tree, fnum);
1723         smbcli_close(cli2->tree, fnum2);
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_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1733 {
1734         const char *fname = BASEDIR "\\test_batch11.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_WRITE;
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-eof on pathname breaks an exclusive oplock. */
1766         torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
1767
1768         ZERO_STRUCT(break_info);
1769
1770         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1771                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1772                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1773         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1774         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1775                 NTCREATEX_SHARE_ACCESS_WRITE|
1776                 NTCREATEX_SHARE_ACCESS_DELETE;
1777         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1778         status = smb_raw_open(cli1->tree, tctx, &io);
1779         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1780         fnum = io.ntcreatex.out.file.fnum;
1781         torture_wait_for_oplock_break(tctx);
1782         CHECK_VAL(break_info.count, 0);
1783         CHECK_VAL(break_info.failures, 0);
1784         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1785
1786         ZERO_STRUCT(sfi);
1787         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1788         sfi.generic.in.file.path = fname;
1789         sfi.end_of_file_info.in.size = 100;
1790
1791         status = smb_raw_setpathinfo(cli2->tree, &sfi);
1792         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1793
1794         torture_wait_for_oplock_break(tctx);
1795         CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
1796         CHECK_VAL(break_info.failures, 0);
1797         CHECK_VAL(break_info.level, 0);
1798
1799         smbcli_close(cli1->tree, fnum);
1800
1801 done:
1802         smb_raw_exit(cli1->session);
1803         smb_raw_exit(cli2->session);
1804         smbcli_deltree(cli1->tree, BASEDIR);
1805         return ret;
1806 }
1807
1808 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1809 {
1810         const char *fname = BASEDIR "\\test_batch12.dat";
1811         NTSTATUS status;
1812         bool ret = true;
1813         union smb_open io;
1814         union smb_setfileinfo sfi;
1815         uint16_t fnum=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
1826         /*
1827           base ntcreatex parms
1828         */
1829         io.generic.level = RAW_OPEN_NTCREATEX;
1830         io.ntcreatex.in.root_fid.fnum = 0;
1831         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1832         io.ntcreatex.in.alloc_size = 0;
1833         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1834         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1835         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1836         io.ntcreatex.in.create_options = 0;
1837         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1838         io.ntcreatex.in.security_flags = 0;
1839         io.ntcreatex.in.fname = fname;
1840
1841         /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1842         torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
1843
1844         ZERO_STRUCT(break_info);
1845         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1846
1847         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1848                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1849                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1850         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1851         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1852                 NTCREATEX_SHARE_ACCESS_WRITE|
1853                 NTCREATEX_SHARE_ACCESS_DELETE;
1854         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1855         status = smb_raw_open(cli1->tree, tctx, &io);
1856         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1857         fnum = io.ntcreatex.out.file.fnum;
1858         torture_wait_for_oplock_break(tctx);
1859         CHECK_VAL(break_info.count, 0);
1860         CHECK_VAL(break_info.failures, 0);
1861         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1862
1863         ZERO_STRUCT(sfi);
1864         sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
1865         sfi.generic.in.file.path = fname;
1866         sfi.allocation_info.in.alloc_size = 65536 * 8;
1867
1868         status = smb_raw_setpathinfo(cli2->tree, &sfi);
1869         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1870
1871         torture_wait_for_oplock_break(tctx);
1872         CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
1873         CHECK_VAL(break_info.failures, 0);
1874         CHECK_VAL(break_info.level, 0);
1875
1876         smbcli_close(cli1->tree, fnum);
1877
1878 done:
1879         smb_raw_exit(cli1->session);
1880         smb_raw_exit(cli2->session);
1881         smbcli_deltree(cli1->tree, BASEDIR);
1882         return ret;
1883 }
1884
1885 static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1886 {
1887         const char *fname = BASEDIR "\\test_batch13.dat";
1888         NTSTATUS status;
1889         bool ret = true;
1890         union smb_open io;
1891         uint16_t fnum=0, fnum2=0;
1892
1893         if (!torture_setup_dir(cli1, BASEDIR)) {
1894                 return false;
1895         }
1896
1897         /* cleanup */
1898         smbcli_unlink(cli1->tree, fname);
1899
1900         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1901         smbcli_oplock_handler(cli2->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, "BATCH13: 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_OVERWRITE 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         torture_wait_for_oplock_break(tctx);
1948         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1949         CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
1950         CHECK_VAL(break_info.failures, 0);
1951
1952         smbcli_close(cli1->tree, fnum);
1953         smbcli_close(cli2->tree, fnum2);
1954
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_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1963 {
1964         const char *fname = BASEDIR "\\test_batch14.dat";
1965         NTSTATUS status;
1966         bool ret = true;
1967         union smb_open io;
1968         uint16_t fnum=0, fnum2=0;
1969
1970         if (!torture_setup_dir(cli1, BASEDIR)) {
1971                 return false;
1972         }
1973
1974         /* cleanup */
1975         smbcli_unlink(cli1->tree, fname);
1976
1977         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1978
1979         /*
1980           base ntcreatex parms
1981         */
1982         io.generic.level = RAW_OPEN_NTCREATEX;
1983         io.ntcreatex.in.root_fid.fnum = 0;
1984         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1985         io.ntcreatex.in.alloc_size = 0;
1986         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1987         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1988         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1989         io.ntcreatex.in.create_options = 0;
1990         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1991         io.ntcreatex.in.security_flags = 0;
1992         io.ntcreatex.in.fname = fname;
1993
1994         torture_comment(tctx, "BATCH14: open with batch oplock\n");
1995         ZERO_STRUCT(break_info);
1996
1997         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1998                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1999                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2000         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2001                 NTCREATEX_SHARE_ACCESS_WRITE|
2002                 NTCREATEX_SHARE_ACCESS_DELETE;
2003         status = smb_raw_open(cli1->tree, tctx, &io);
2004         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2005         fnum = io.ntcreatex.out.file.fnum;
2006         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2007
2008         ZERO_STRUCT(break_info);
2009
2010         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
2011
2012         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
2013                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
2014                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2015         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
2016         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2017                 NTCREATEX_SHARE_ACCESS_WRITE|
2018                 NTCREATEX_SHARE_ACCESS_DELETE;
2019         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
2020         status = smb_raw_open(cli2->tree, tctx, &io);
2021         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2022         fnum2 = io.ntcreatex.out.file.fnum;
2023         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2024
2025         torture_wait_for_oplock_break(tctx);
2026         CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
2027         CHECK_VAL(break_info.failures, 0);
2028
2029         smbcli_close(cli1->tree, fnum);
2030         smbcli_close(cli2->tree, fnum2);
2031 done:
2032         smb_raw_exit(cli1->session);
2033         smb_raw_exit(cli2->session);
2034         smbcli_deltree(cli1->tree, BASEDIR);
2035         return ret;
2036 }
2037
2038 static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2039 {
2040         const char *fname = BASEDIR "\\test_batch15.dat";
2041         NTSTATUS status;
2042         bool ret = true;
2043         union smb_open io;
2044         union smb_fileinfo qfi;
2045         uint16_t fnum=0;
2046
2047         if (!torture_setup_dir(cli1, BASEDIR)) {
2048                 return false;
2049         }
2050
2051         /* cleanup */
2052         smbcli_unlink(cli1->tree, fname);
2053
2054         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2055
2056         /*
2057           base ntcreatex parms
2058         */
2059         io.generic.level = RAW_OPEN_NTCREATEX;
2060         io.ntcreatex.in.root_fid.fnum = 0;
2061         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2062         io.ntcreatex.in.alloc_size = 0;
2063         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2064         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2065         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2066         io.ntcreatex.in.create_options = 0;
2067         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2068         io.ntcreatex.in.security_flags = 0;
2069         io.ntcreatex.in.fname = fname;
2070
2071         /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
2072         torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
2073
2074         ZERO_STRUCT(break_info);
2075
2076         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2077                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2078                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2079         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2080         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2081                 NTCREATEX_SHARE_ACCESS_WRITE|
2082                 NTCREATEX_SHARE_ACCESS_DELETE;
2083         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2084         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2085         status = smb_raw_open(cli1->tree, tctx, &io);
2086         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2087         fnum = io.ntcreatex.out.file.fnum;
2088
2089         torture_wait_for_oplock_break(tctx);
2090         CHECK_VAL(break_info.count, 0);
2091         CHECK_VAL(break_info.failures, 0);
2092         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2093
2094         ZERO_STRUCT(qfi);
2095         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2096         qfi.generic.in.file.path = fname;
2097
2098         status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
2099         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2100
2101         torture_wait_for_oplock_break(tctx);
2102         CHECK_VAL(break_info.count, 0);
2103
2104         smbcli_close(cli1->tree, fnum);
2105
2106 done:
2107         smb_raw_exit(cli1->session);
2108         smb_raw_exit(cli2->session);
2109         smbcli_deltree(cli1->tree, BASEDIR);
2110         return ret;
2111 }
2112
2113 static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2114 {
2115         const char *fname = BASEDIR "\\test_batch16.dat";
2116         NTSTATUS status;
2117         bool ret = true;
2118         union smb_open io;
2119         uint16_t fnum=0, fnum2=0;
2120
2121         if (!torture_setup_dir(cli1, BASEDIR)) {
2122                 return false;
2123         }
2124
2125         /* cleanup */
2126         smbcli_unlink(cli1->tree, fname);
2127
2128         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2129         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
2130
2131         /*
2132           base ntcreatex parms
2133         */
2134         io.generic.level = RAW_OPEN_NTCREATEX;
2135         io.ntcreatex.in.root_fid.fnum = 0;
2136         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2137         io.ntcreatex.in.alloc_size = 0;
2138         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2139         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2140         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2141         io.ntcreatex.in.create_options = 0;
2142         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2143         io.ntcreatex.in.security_flags = 0;
2144         io.ntcreatex.in.fname = fname;
2145
2146         torture_comment(tctx, "BATCH16: open with batch oplock\n");
2147         ZERO_STRUCT(break_info);
2148
2149         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2150                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2151                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2152         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2153                 NTCREATEX_SHARE_ACCESS_WRITE|
2154                 NTCREATEX_SHARE_ACCESS_DELETE;
2155         status = smb_raw_open(cli1->tree, tctx, &io);
2156         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2157         fnum = io.ntcreatex.out.file.fnum;
2158         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2159
2160         ZERO_STRUCT(break_info);
2161
2162         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
2163
2164         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2165                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2166                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2167         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
2168         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2169                 NTCREATEX_SHARE_ACCESS_WRITE|
2170                 NTCREATEX_SHARE_ACCESS_DELETE;
2171         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2172         status = smb_raw_open(cli2->tree, tctx, &io);
2173         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2174         fnum2 = io.ntcreatex.out.file.fnum;
2175         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2176
2177         torture_wait_for_oplock_break(tctx);
2178         CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
2179         CHECK_VAL(break_info.failures, 0);
2180
2181         smbcli_close(cli1->tree, fnum);
2182         smbcli_close(cli2->tree, fnum2);
2183
2184 done:
2185         smb_raw_exit(cli1->session);
2186         smb_raw_exit(cli2->session);
2187         smbcli_deltree(cli1->tree, BASEDIR);
2188         return ret;
2189 }
2190
2191 static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2192 {
2193         const char *fname1 = BASEDIR "\\test_batch17_1.dat";
2194         const char *fname2 = BASEDIR "\\test_batch17_2.dat";
2195         NTSTATUS status;
2196         bool ret = true;
2197         union smb_open io;
2198         union smb_rename rn;
2199         uint16_t fnum=0;
2200
2201         if (!torture_setup_dir(cli1, BASEDIR)) {
2202                 return false;
2203         }
2204
2205         /* cleanup */
2206         smbcli_unlink(cli1->tree, fname1);
2207         smbcli_unlink(cli1->tree, fname2);
2208
2209         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2210
2211         /*
2212           base ntcreatex parms
2213         */
2214         io.generic.level = RAW_OPEN_NTCREATEX;
2215         io.ntcreatex.in.root_fid.fnum = 0;
2216         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2217         io.ntcreatex.in.alloc_size = 0;
2218         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2219         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2220         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2221         io.ntcreatex.in.create_options = 0;
2222         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2223         io.ntcreatex.in.security_flags = 0;
2224         io.ntcreatex.in.fname = fname1;
2225
2226         torture_comment(tctx, "BATCH17: open a file with an batch oplock (share mode: none)\n");
2227
2228         ZERO_STRUCT(break_info);
2229         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2230                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2231                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2232
2233         status = smb_raw_open(cli1->tree, tctx, &io);
2234         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2235         fnum = io.ntcreatex.out.file.fnum;
2236         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2237
2238         torture_comment(tctx, "rename should trigger a break\n");
2239         ZERO_STRUCT(rn);
2240         rn.generic.level = RAW_RENAME_RENAME;
2241         rn.rename.in.pattern1 = fname1;
2242         rn.rename.in.pattern2 = fname2;
2243         rn.rename.in.attrib = 0;
2244
2245         torture_comment(tctx, "trying rename while first file open\n");
2246         status = smb_raw_rename(cli2->tree, &rn);
2247         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2248
2249         torture_wait_for_oplock_break(tctx);
2250         CHECK_VAL(break_info.count, 1);
2251         CHECK_VAL(break_info.failures, 0);
2252         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2253
2254         smbcli_close(cli1->tree, fnum);
2255
2256 done:
2257         smb_raw_exit(cli1->session);
2258         smb_raw_exit(cli2->session);
2259         smbcli_deltree(cli1->tree, BASEDIR);
2260         return ret;
2261 }
2262
2263 static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2264 {
2265         const char *fname1 = BASEDIR "\\test_batch18_1.dat";
2266         const char *fname2 = BASEDIR "\\test_batch18_2.dat";
2267         NTSTATUS status;
2268         bool ret = true;
2269         union smb_open io;
2270         union smb_rename rn;
2271         uint16_t fnum=0;
2272
2273         if (!torture_setup_dir(cli1, BASEDIR)) {
2274                 return false;
2275         }
2276
2277         /* cleanup */
2278         smbcli_unlink(cli1->tree, fname1);
2279         smbcli_unlink(cli1->tree, fname2);
2280
2281         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2282
2283         /*
2284           base ntcreatex parms
2285         */
2286         io.generic.level = RAW_OPEN_NTCREATEX;
2287         io.ntcreatex.in.root_fid.fnum = 0;
2288         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2289         io.ntcreatex.in.alloc_size = 0;
2290         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2291         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
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, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2299
2300         ZERO_STRUCT(break_info);
2301         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2302                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2303                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2304
2305         status = smb_raw_open(cli1->tree, tctx, &io);
2306         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2307         fnum = io.ntcreatex.out.file.fnum;
2308         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2309
2310         torture_comment(tctx, "ntrename should trigger a break\n");
2311         ZERO_STRUCT(rn);
2312         rn.generic.level = RAW_RENAME_NTRENAME;
2313         rn.ntrename.in.attrib   = 0;
2314         rn.ntrename.in.flags    = RENAME_FLAG_RENAME;
2315         rn.ntrename.in.old_name = fname1;
2316         rn.ntrename.in.new_name = fname2;
2317         torture_comment(tctx, "trying rename while first file open\n");
2318         status = smb_raw_rename(cli2->tree, &rn);
2319         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2320
2321         torture_wait_for_oplock_break(tctx);
2322         CHECK_VAL(break_info.count, 1);
2323         CHECK_VAL(break_info.failures, 0);
2324         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2325
2326         smbcli_close(cli1->tree, fnum);
2327
2328 done:
2329         smb_raw_exit(cli1->session);
2330         smb_raw_exit(cli2->session);
2331         smbcli_deltree(cli1->tree, BASEDIR);
2332         return ret;
2333 }
2334
2335 static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2336 {
2337         const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2338         const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2339         const char *fname3 = BASEDIR "\\test_batch19_3.dat";
2340         NTSTATUS status;
2341         bool ret = true;
2342         union smb_open io;
2343         union smb_fileinfo qfi;
2344         union smb_setfileinfo sfi;
2345         uint16_t fnum=0;
2346
2347         if (!torture_setup_dir(cli1, BASEDIR)) {
2348                 return false;
2349         }
2350
2351         /* cleanup */
2352         smbcli_unlink(cli1->tree, fname1);
2353         smbcli_unlink(cli1->tree, fname2);
2354         smbcli_unlink(cli1->tree, fname3);
2355
2356         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2357
2358         /*
2359           base ntcreatex parms
2360         */
2361         io.generic.level = RAW_OPEN_NTCREATEX;
2362         io.ntcreatex.in.root_fid.fnum = 0;
2363         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2364         io.ntcreatex.in.alloc_size = 0;
2365         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2366         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2367             NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
2368         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2369         io.ntcreatex.in.create_options = 0;
2370         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2371         io.ntcreatex.in.security_flags = 0;
2372         io.ntcreatex.in.fname = fname1;
2373
2374         torture_comment(tctx, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2375         ZERO_STRUCT(break_info);
2376         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2377                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2378                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2379         status = smb_raw_open(cli1->tree, tctx, &io);
2380         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2381         fnum = io.ntcreatex.out.file.fnum;
2382         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2383
2384         torture_comment(tctx, "setpathinfo rename info should trigger a break "
2385             "to none\n");
2386         ZERO_STRUCT(sfi);
2387         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2388         sfi.generic.in.file.path = fname1;
2389         sfi.rename_information.in.overwrite     = 0;
2390         sfi.rename_information.in.root_fid      = 0;
2391         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2392
2393         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2394         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2395
2396         torture_wait_for_oplock_break(tctx);
2397
2398         CHECK_VAL(break_info.failures, 0);
2399
2400         if (TARGET_IS_WINXP(tctx)) {
2401                 /* Win XP breaks to level2. */
2402                 CHECK_VAL(break_info.count, 1);
2403                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2404         } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
2405             TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
2406                 /* Win2K3/2k8 incorrectly doesn't break at all. */
2407                 CHECK_VAL(break_info.count, 0);
2408         } else {
2409                 /* win7/2k8r2 break to none. */
2410                 CHECK_VAL(break_info.count, 1);
2411                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2412         }
2413
2414         ZERO_STRUCT(qfi);
2415         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2416         qfi.generic.in.file.fnum = fnum;
2417
2418         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2419         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2420         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2421
2422         /* Close and re-open file with oplock. */
2423         smbcli_close(cli1->tree, fnum);
2424         status = smb_raw_open(cli1->tree, tctx, &io);
2425         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2426         fnum = io.ntcreatex.out.file.fnum;
2427         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2428
2429         torture_comment(tctx, "setfileinfo rename info on a client's own fid "
2430             "should not trigger a break nor a violation\n");
2431         ZERO_STRUCT(break_info);
2432         ZERO_STRUCT(sfi);
2433         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2434         sfi.generic.in.file.fnum = fnum;
2435         sfi.rename_information.in.overwrite     = 0;
2436         sfi.rename_information.in.root_fid      = 0;
2437         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2438
2439         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2440         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2441
2442         torture_wait_for_oplock_break(tctx);
2443         if (TARGET_IS_WINXP(tctx)) {
2444                 /* XP incorrectly breaks to level2. */
2445                 CHECK_VAL(break_info.count, 1);
2446                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2447         } else {
2448                 CHECK_VAL(break_info.count, 0);
2449         }
2450
2451         ZERO_STRUCT(qfi);
2452         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2453         qfi.generic.in.file.fnum = fnum;
2454
2455         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2456         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2457         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2458
2459 done:
2460         smbcli_close(cli1->tree, fnum);
2461         smb_raw_exit(cli1->session);
2462         smb_raw_exit(cli2->session);
2463         smbcli_deltree(cli1->tree, BASEDIR);
2464         return ret;
2465 }
2466
2467 /****************************************************
2468  Called from raw-rename - we need oplock handling for
2469  this test so this is why it's in oplock.c, not rename.c
2470 ****************************************************/
2471
2472 bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2473 {
2474         const char *fname1 = BASEDIR "\\test_trans2rename_1.dat";
2475         const char *fname2 = BASEDIR "\\test_trans2rename_2.dat";
2476         const char *fname3 = BASEDIR "\\test_trans2rename_3.dat";
2477         NTSTATUS status;
2478         bool ret = true;
2479         union smb_open io;
2480         union smb_fileinfo qfi;
2481         union smb_setfileinfo sfi;
2482         uint16_t fnum=0;
2483
2484         if (!torture_setup_dir(cli1, BASEDIR)) {
2485                 return false;
2486         }
2487
2488         /* cleanup */
2489         smbcli_unlink(cli1->tree, fname1);
2490         smbcli_unlink(cli1->tree, fname2);
2491         smbcli_unlink(cli1->tree, fname3);
2492
2493         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2494
2495         /*
2496           base ntcreatex parms
2497         */
2498         io.generic.level = RAW_OPEN_NTCREATEX;
2499         io.ntcreatex.in.root_fid.fnum = 0;
2500         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2501         io.ntcreatex.in.alloc_size = 0;
2502         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2503         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2504             NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
2505         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2506         io.ntcreatex.in.create_options = 0;
2507         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2508         io.ntcreatex.in.security_flags = 0;
2509         io.ntcreatex.in.fname = fname1;
2510
2511         torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n");
2512         ZERO_STRUCT(break_info);
2513         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2514                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2515         status = smb_raw_open(cli1->tree, tctx, &io);
2516         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2517         fnum = io.ntcreatex.out.file.fnum;
2518         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2519
2520         torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2521         ZERO_STRUCT(sfi);
2522         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2523         sfi.generic.in.file.path = fname1;
2524         sfi.rename_information.in.overwrite     = 0;
2525         sfi.rename_information.in.root_fid      = 0;
2526         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2527
2528         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2529
2530         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2531
2532         torture_wait_for_oplock_break(tctx);
2533         CHECK_VAL(break_info.count, 0);
2534
2535         ZERO_STRUCT(qfi);
2536         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2537         qfi.generic.in.file.fnum = fnum;
2538
2539         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2540         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2541         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2542
2543         torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2544         ZERO_STRUCT(sfi);
2545         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2546         sfi.generic.in.file.fnum = fnum;
2547         sfi.rename_information.in.overwrite     = 0;
2548         sfi.rename_information.in.root_fid      = 0;
2549         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2550
2551         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2552         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2553
2554         torture_wait_for_oplock_break(tctx);
2555         CHECK_VAL(break_info.count, 0);
2556
2557         ZERO_STRUCT(qfi);
2558         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2559         qfi.generic.in.file.fnum = fnum;
2560
2561         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2562         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2563         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2564
2565 done:
2566         smbcli_close(cli1->tree, fnum);
2567         smb_raw_exit(cli1->session);
2568         smb_raw_exit(cli2->session);
2569         smbcli_deltree(cli1->tree, BASEDIR);
2570         return ret;
2571 }
2572
2573 /****************************************************
2574  Called from raw-rename - we need oplock handling for
2575  this test so this is why it's in oplock.c, not rename.c
2576 ****************************************************/
2577
2578 bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1)
2579 {
2580         const char *fname1 = BASEDIR "\\test_nttransrename_1.dat";
2581         const char *fname2 = BASEDIR "\\test_nttransrename_2.dat";
2582         NTSTATUS status;
2583         bool ret = true;
2584         union smb_open io;
2585         union smb_fileinfo qfi, qpi;
2586         union smb_rename rn;
2587         uint16_t fnum=0;
2588
2589         if (!torture_setup_dir(cli1, BASEDIR)) {
2590                 return false;
2591         }
2592
2593         /* cleanup */
2594         smbcli_unlink(cli1->tree, fname1);
2595         smbcli_unlink(cli1->tree, fname2);
2596
2597         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2598
2599         /*
2600           base ntcreatex parms
2601         */
2602         io.generic.level = RAW_OPEN_NTCREATEX;
2603         io.ntcreatex.in.root_fid.fnum = 0;
2604         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2605         io.ntcreatex.in.alloc_size = 0;
2606         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2607         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2608         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2609         io.ntcreatex.in.create_options = 0;
2610         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2611         io.ntcreatex.in.security_flags = 0;
2612         io.ntcreatex.in.fname = fname1;
2613
2614         torture_comment(tctx, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2615         ZERO_STRUCT(break_info);
2616         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2617                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2618         status = smb_raw_open(cli1->tree, tctx, &io);
2619         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2620         fnum = io.ntcreatex.out.file.fnum;
2621         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2622
2623         torture_comment(tctx, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2624         ZERO_STRUCT(rn);
2625         rn.generic.level = RAW_RENAME_NTTRANS;
2626         rn.nttrans.in.file.fnum = fnum;
2627         rn.nttrans.in.flags     = 0;
2628         rn.nttrans.in.new_name  = fname2+strlen(BASEDIR)+1;
2629
2630         status = smb_raw_rename(cli1->tree, &rn);
2631         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2632
2633         torture_wait_for_oplock_break(tctx);
2634         CHECK_VAL(break_info.count, 0);
2635
2636         /* w2k3 does nothing, it doesn't rename the file */
2637         torture_comment(tctx, "nttrans_rename: the server should have done nothing\n");
2638         ZERO_STRUCT(qfi);
2639         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2640         qfi.generic.in.file.fnum = fnum;
2641
2642         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2643         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2644         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname1);
2645
2646         ZERO_STRUCT(qpi);
2647         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2648         qpi.generic.in.file.path = fname1;
2649
2650         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2651         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2652         CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2653
2654         ZERO_STRUCT(qpi);
2655         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2656         qpi.generic.in.file.path = fname2;
2657
2658         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2659         CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2660
2661         torture_comment(tctx, "nttrans_rename: after closing the file the file is still not renamed\n");
2662         status = smbcli_close(cli1->tree, fnum);
2663         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2664
2665         ZERO_STRUCT(qpi);
2666         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2667         qpi.generic.in.file.path = fname1;
2668
2669         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2670         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2671         CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2672
2673         ZERO_STRUCT(qpi);
2674         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2675         qpi.generic.in.file.path = fname2;
2676
2677         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2678         CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2679
2680         torture_comment(tctx, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
2681         ZERO_STRUCT(rn);
2682         rn.generic.level = RAW_RENAME_NTTRANS;
2683         rn.nttrans.in.file.fnum = fnum+1;
2684         rn.nttrans.in.flags     = 0;
2685         rn.nttrans.in.new_name  = fname2+strlen(BASEDIR)+1;
2686
2687         status = smb_raw_rename(cli1->tree, &rn);
2688
2689         CHECK_STATUS(tctx, status, NT_STATUS_INVALID_HANDLE);
2690
2691 done:
2692         smb_raw_exit(cli1->session);
2693         smbcli_deltree(cli1->tree, BASEDIR);
2694         return ret;
2695 }
2696
2697
2698 static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2699 {
2700         const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2701         const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2702         const char *fname3 = BASEDIR "\\test_batch20_3.dat";
2703         NTSTATUS status;
2704         bool ret = true;
2705         union smb_open io;
2706         union smb_fileinfo qfi;
2707         union smb_setfileinfo sfi;
2708         uint16_t fnum=0,fnum2=0;
2709
2710         if (!torture_setup_dir(cli1, BASEDIR)) {
2711                 return false;
2712         }
2713
2714         /* cleanup */
2715         smbcli_unlink(cli1->tree, fname1);
2716         smbcli_unlink(cli1->tree, fname2);
2717         smbcli_unlink(cli1->tree, fname3);
2718
2719         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2720
2721         /*
2722           base ntcreatex parms
2723         */
2724         io.generic.level = RAW_OPEN_NTCREATEX;
2725         io.ntcreatex.in.root_fid.fnum = 0;
2726         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2727         io.ntcreatex.in.alloc_size = 0;
2728         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2729         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2730         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2731         io.ntcreatex.in.create_options = 0;
2732         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2733         io.ntcreatex.in.security_flags = 0;
2734         io.ntcreatex.in.fname = fname1;
2735
2736         torture_comment(tctx, "BATCH20: open a file with an batch oplock (share mode: all)\n");
2737         ZERO_STRUCT(break_info);
2738         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2739                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2740                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2741         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2742                 NTCREATEX_SHARE_ACCESS_WRITE|
2743                 NTCREATEX_SHARE_ACCESS_DELETE;
2744         status = smb_raw_open(cli1->tree, tctx, &io);
2745         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2746         fnum = io.ntcreatex.out.file.fnum;
2747         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2748
2749         ZERO_STRUCT(sfi);
2750         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2751         sfi.generic.in.file.path = fname1;
2752         sfi.rename_information.in.overwrite     = 0;
2753         sfi.rename_information.in.root_fid      = 0;
2754         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2755
2756         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2757         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2758
2759         torture_wait_for_oplock_break(tctx);
2760         CHECK_VAL(break_info.failures, 0);
2761
2762         if (TARGET_IS_WINXP(tctx)) {
2763                 /* Win XP breaks to level2. */
2764                 CHECK_VAL(break_info.count, 1);
2765                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2766         } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
2767             TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
2768                 /* Win2K3/2k8 incorrectly doesn't break at all. */
2769                 CHECK_VAL(break_info.count, 0);
2770         } else {
2771                 /* win7/2k8r2 break to none. */
2772                 CHECK_VAL(break_info.count, 1);
2773                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2774         }
2775
2776         ZERO_STRUCT(qfi);
2777         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2778         qfi.generic.in.file.fnum = fnum;
2779
2780         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2781         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2782         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2783
2784         torture_comment(tctx, "open a file with the new name an batch oplock (share mode: all)\n");
2785         ZERO_STRUCT(break_info);
2786         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2787                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2788                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2789         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2790                 NTCREATEX_SHARE_ACCESS_WRITE|
2791                 NTCREATEX_SHARE_ACCESS_DELETE;
2792         io.ntcreatex.in.fname = fname2;
2793         status = smb_raw_open(cli2->tree, tctx, &io);
2794         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2795         fnum2 = io.ntcreatex.out.file.fnum;
2796         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2797
2798         torture_wait_for_oplock_break(tctx);
2799
2800         if (TARGET_IS_WINXP(tctx)) {
2801                 /* XP broke to level2, and doesn't break again. */
2802                 CHECK_VAL(break_info.count, 0);
2803         } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
2804             TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
2805                 /* Win2K3 incorrectly didn't break before so break now. */
2806                 CHECK_VAL(break_info.count, 1);
2807                 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2808         } else {
2809                 /* win7/2k8r2 broke to none, and doesn't break again. */
2810                 CHECK_VAL(break_info.count, 0);
2811         }
2812
2813         ZERO_STRUCT(break_info);
2814
2815         ZERO_STRUCT(sfi);
2816         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2817         sfi.generic.in.file.fnum = fnum;
2818         sfi.rename_information.in.overwrite     = 0;
2819         sfi.rename_information.in.root_fid      = 0;
2820         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2821
2822         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2823         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2824
2825         torture_wait_for_oplock_break(tctx);
2826         CHECK_VAL(break_info.count, 0);
2827
2828         ZERO_STRUCT(qfi);
2829         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2830         qfi.generic.in.file.fnum = fnum;
2831
2832         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2833         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2834         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2835
2836         ZERO_STRUCT(qfi);
2837         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2838         qfi.generic.in.file.fnum = fnum2;
2839
2840         status = smb_raw_fileinfo(cli2->tree, tctx, &qfi);
2841         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2842         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2843
2844
2845 done:
2846         smbcli_close(cli1->tree, fnum);
2847         smbcli_close(cli2->tree, fnum2);
2848         smb_raw_exit(cli1->session);
2849         smb_raw_exit(cli2->session);
2850         smbcli_deltree(cli1->tree, BASEDIR);
2851         return ret;
2852 }
2853
2854 static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2855 {
2856         const char *fname = BASEDIR "\\test_batch21.dat";
2857         NTSTATUS status;
2858         bool ret = true;
2859         union smb_open io;
2860         struct smb_echo e;
2861         uint16_t fnum=0;
2862         char c = 0;
2863         ssize_t wr;
2864
2865         if (!torture_setup_dir(cli1, BASEDIR)) {
2866                 return false;
2867         }
2868
2869         /* cleanup */
2870         smbcli_unlink(cli1->tree, fname);
2871
2872         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2873
2874         /*
2875           base ntcreatex parms
2876         */
2877         io.generic.level = RAW_OPEN_NTCREATEX;
2878         io.ntcreatex.in.root_fid.fnum = 0;
2879         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2880         io.ntcreatex.in.alloc_size = 0;
2881         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2882         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2883         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2884         io.ntcreatex.in.create_options = 0;
2885         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2886         io.ntcreatex.in.security_flags = 0;
2887         io.ntcreatex.in.fname = fname;
2888
2889         /*
2890           with a batch oplock we get a break
2891         */
2892         torture_comment(tctx, "BATCH21: open with batch oplock\n");
2893         ZERO_STRUCT(break_info);
2894         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2895                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2896                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2897         status = smb_raw_open(cli1->tree, tctx, &io);
2898         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2899         fnum = io.ntcreatex.out.file.fnum;
2900         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2901
2902         torture_comment(tctx, "writing should not generate a break\n");
2903         wr = smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
2904         CHECK_VAL(wr, 1);
2905         CHECK_STATUS(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_OK);
2906
2907         ZERO_STRUCT(e);
2908         e.in.repeat_count = 1;
2909         status = smb_raw_echo(cli1->transport, &e);
2910         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2911
2912         torture_wait_for_oplock_break(tctx);
2913         CHECK_VAL(break_info.count, 0);
2914
2915         smbcli_close(cli1->tree, fnum);
2916
2917 done:
2918         smb_raw_exit(cli1->session);
2919         smb_raw_exit(cli2->session);
2920         smbcli_deltree(cli1->tree, BASEDIR);
2921         return ret;
2922 }
2923
2924 static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2925 {
2926         const char *fname = BASEDIR "\\test_batch22.dat";
2927         NTSTATUS status;
2928         bool ret = true;
2929         union smb_open io;
2930         uint16_t fnum = 0, fnum2 = 0, fnum3 = 0;
2931         struct timeval tv;
2932         int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2933         int te;
2934
2935         if (!torture_setup_dir(cli1, BASEDIR)) {
2936                 return false;
2937         }
2938
2939         /* cleanup */
2940         smbcli_unlink(cli1->tree, fname);
2941
2942         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2943         /*
2944           base ntcreatex parms
2945         */
2946         io.generic.level = RAW_OPEN_NTCREATEX;
2947         io.ntcreatex.in.root_fid.fnum = 0;
2948         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2949         io.ntcreatex.in.alloc_size = 0;
2950         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2951         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2952         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2953         io.ntcreatex.in.create_options = 0;
2954         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2955         io.ntcreatex.in.security_flags = 0;
2956         io.ntcreatex.in.fname = fname;
2957
2958         /*
2959           with a batch oplock we get a break
2960         */
2961         torture_comment(tctx, "BATCH22: open with batch oplock\n");
2962         ZERO_STRUCT(break_info);
2963         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2964                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2965                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2966         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2967                 NTCREATEX_SHARE_ACCESS_WRITE|
2968                 NTCREATEX_SHARE_ACCESS_DELETE;
2969         status = smb_raw_open(cli1->tree, tctx, &io);
2970         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2971         fnum = io.ntcreatex.out.file.fnum;
2972         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2973
2974         torture_comment(tctx, "a 2nd open should not succeed after the oplock "
2975                         "break timeout\n");
2976         tv = timeval_current();
2977         smbcli_oplock_handler(cli1->transport, oplock_handler_timeout, cli1->tree);
2978         status = smb_raw_open(cli1->tree, tctx, &io);
2979
2980         if (TARGET_IS_W2K3(tctx)) {
2981                 /* 2k3 has an issue here. xp/win7 are ok. */
2982                 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2983         } else {
2984                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2985         }
2986
2987         fnum2 = io.ntcreatex.out.file.fnum;
2988
2989         torture_wait_for_oplock_break(tctx);
2990         te = (int)timeval_elapsed(&tv);
2991
2992         /*
2993          * Some servers detect clients that let oplocks timeout, so this check
2994          * only shows a warning message instead failing the test to eliminate
2995          * failures from repeated runs of the test.  This isn't ideal, but
2996          * it's better than not running the test at all.
2997          */
2998         CHECK_RANGE(te, timeout - 1, timeout + 15);
2999
3000         CHECK_VAL(break_info.count, 1);
3001         CHECK_VAL(break_info.fnum, fnum);
3002         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3003         CHECK_VAL(break_info.failures, 0);
3004         ZERO_STRUCT(break_info);
3005
3006         torture_comment(tctx, "a 2nd open should succeed after the oplock "
3007                         "release without break\n");
3008         tv = timeval_current();
3009         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3010         status = smb_raw_open(cli1->tree, tctx, &io);
3011         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3012 #if 0
3013         /* Samba 3.6.0 and above behave as Windows. */
3014         if (TARGET_IS_SAMBA3(tctx)) {
3015                 /* samba3 doesn't grant additional oplocks to bad clients. */
3016                 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
3017         } else {
3018                 CHECK_VAL(io.ntcreatex.out.oplock_level,
3019                         LEVEL_II_OPLOCK_RETURN);
3020         }
3021 #else
3022         CHECK_VAL(io.ntcreatex.out.oplock_level,
3023                   LEVEL_II_OPLOCK_RETURN);
3024 #endif
3025         torture_wait_for_oplock_break(tctx);
3026         te = (int)timeval_elapsed(&tv);
3027         /* it should come in without delay */
3028         CHECK_RANGE(te+1, 0, timeout);
3029         fnum3 = io.ntcreatex.out.file.fnum;
3030
3031         CHECK_VAL(break_info.count, 0);
3032
3033         smbcli_close(cli1->tree, fnum);
3034         smbcli_close(cli1->tree, fnum2);
3035         smbcli_close(cli1->tree, fnum3);
3036
3037 done:
3038         smb_raw_exit(cli1->session);
3039         smb_raw_exit(cli2->session);
3040         smbcli_deltree(cli1->tree, BASEDIR);
3041         return ret;
3042 }
3043
3044 static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3045 {
3046         const char *fname = BASEDIR "\\test_batch23.dat";
3047         NTSTATUS status;
3048         bool ret = true;
3049         union smb_open io;
3050         uint16_t fnum=0, fnum2=0,fnum3=0;
3051         struct smbcli_state *cli3 = NULL;
3052
3053         if (!torture_setup_dir(cli1, BASEDIR)) {
3054                 return false;
3055         }
3056
3057         /* cleanup */
3058         smbcli_unlink(cli1->tree, fname);
3059
3060         ret = open_connection_no_level2_oplocks(tctx, &cli3);
3061         CHECK_VAL(ret, true);
3062
3063         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3064         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3065         smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
3066
3067         /*
3068           base ntcreatex parms
3069         */
3070         io.generic.level = RAW_OPEN_NTCREATEX;
3071         io.ntcreatex.in.root_fid.fnum = 0;
3072         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3073         io.ntcreatex.in.alloc_size = 0;
3074         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3075         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3076         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3077         io.ntcreatex.in.create_options = 0;
3078         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3079         io.ntcreatex.in.security_flags = 0;
3080         io.ntcreatex.in.fname = fname;
3081
3082         torture_comment(tctx, "BATCH23: a open and ask for a batch oplock\n");
3083         ZERO_STRUCT(break_info);
3084
3085         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
3086         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
3087         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3088                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3089                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3090         status = smb_raw_open(cli1->tree, tctx, &io);
3091         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3092         fnum = io.ntcreatex.out.file.fnum;
3093         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3094
3095         ZERO_STRUCT(break_info);
3096
3097         torture_comment(tctx, "a 2nd open without level2 oplock support should generate a break to level2\n");
3098         status = smb_raw_open(cli3->tree, tctx, &io);
3099         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3100         fnum3 = io.ntcreatex.out.file.fnum;
3101         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
3102
3103         torture_wait_for_oplock_break(tctx);
3104         CHECK_VAL(break_info.count, 1);
3105         CHECK_VAL(break_info.fnum, fnum);
3106         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3107         CHECK_VAL(break_info.failures, 0);
3108
3109         ZERO_STRUCT(break_info);
3110
3111         torture_comment(tctx, "a 3rd open with level2 oplock support should not generate a break\n");
3112         status = smb_raw_open(cli2->tree, tctx, &io);
3113         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3114         fnum2 = io.ntcreatex.out.file.fnum;
3115         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
3116
3117         torture_wait_for_oplock_break(tctx);
3118         CHECK_VAL(break_info.count, 0);
3119
3120         smbcli_close(cli1->tree, fnum);
3121         smbcli_close(cli2->tree, fnum2);
3122         smbcli_close(cli3->tree, fnum3);
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_batch24(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3133 {
3134         const char *fname = BASEDIR "\\test_batch24.dat";
3135         NTSTATUS status;
3136         bool ret = true;
3137         union smb_open io;
3138         uint16_t fnum2=0,fnum3=0;
3139         struct smbcli_state *cli3 = NULL;
3140
3141         if (!torture_setup_dir(cli1, BASEDIR)) {
3142                 return false;
3143         }
3144
3145         /* cleanup */
3146         smbcli_unlink(cli1->tree, fname);
3147
3148         ret = open_connection_no_level2_oplocks(tctx, &cli3);
3149         CHECK_VAL(ret, true);
3150
3151         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3152         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3153         smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
3154
3155         /*
3156           base ntcreatex parms
3157         */
3158         io.generic.level = RAW_OPEN_NTCREATEX;
3159         io.ntcreatex.in.root_fid.fnum = 0;
3160         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3161         io.ntcreatex.in.alloc_size = 0;
3162         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3163         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3164         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3165         io.ntcreatex.in.create_options = 0;
3166         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3167         io.ntcreatex.in.security_flags = 0;
3168         io.ntcreatex.in.fname = fname;
3169
3170         torture_comment(tctx, "BATCH24: a open without level support and ask for a batch oplock\n");
3171         ZERO_STRUCT(break_info);
3172
3173         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
3174         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
3175         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3176                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3177                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3178         status = smb_raw_open(cli3->tree, tctx, &io);
3179         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3180         fnum3 = io.ntcreatex.out.file.fnum;
3181         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3182
3183         ZERO_STRUCT(break_info);
3184
3185         torture_comment(tctx, "a 2nd open with level2 oplock support should generate a break to none\n");
3186         status = smb_raw_open(cli2->tree, tctx, &io);
3187         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3188         fnum2 = io.ntcreatex.out.file.fnum;
3189         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
3190
3191         torture_wait_for_oplock_break(tctx);
3192         CHECK_VAL(break_info.count, 1);
3193         CHECK_VAL(break_info.fnum, fnum3);
3194         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3195         CHECK_VAL(break_info.failures, 0);
3196
3197         smbcli_close(cli3->tree, fnum3);
3198         smbcli_close(cli2->tree, fnum2);
3199
3200 done:
3201         smb_raw_exit(cli1->session);
3202         smb_raw_exit(cli2->session);
3203         smb_raw_exit(cli3->session);
3204         smbcli_deltree(cli1->tree, BASEDIR);
3205         return ret;
3206 }
3207
3208 static bool test_raw_oplock_batch25(struct torture_context *tctx,
3209                                     struct smbcli_state *cli1,
3210                                     struct smbcli_state *cli2)
3211 {
3212         const char *fname = BASEDIR "\\test_batch25.dat";
3213         NTSTATUS status;
3214         bool ret = true;
3215         union smb_open io;
3216         union smb_setfileinfo sfi;
3217         uint16_t fnum=0;
3218
3219         if (!torture_setup_dir(cli1, BASEDIR)) {
3220                 return false;
3221         }
3222
3223         /* cleanup */
3224         smbcli_unlink(cli1->tree, fname);
3225
3226         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, 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_NONE;
3237         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3238         io.ntcreatex.in.create_options = 0;
3239         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3240         io.ntcreatex.in.security_flags = 0;
3241         io.ntcreatex.in.fname = fname;
3242
3243         torture_comment(tctx, "BATCH25: open a file with an batch oplock "
3244                         "(share mode: none)\n");
3245
3246         ZERO_STRUCT(break_info);
3247         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3248                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3249                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3250         status = smb_raw_open(cli1->tree, tctx, &io);
3251         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3252         fnum = io.ntcreatex.out.file.fnum;
3253         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3254
3255         torture_comment(tctx, "setpathinfo attribute info should not trigger "
3256                         "a break nor a violation\n");
3257         ZERO_STRUCT(sfi);
3258         sfi.generic.level = RAW_SFILEINFO_SETATTR;
3259         sfi.generic.in.file.path        = fname;
3260         sfi.setattr.in.attrib           = FILE_ATTRIBUTE_HIDDEN;
3261         sfi.setattr.in.write_time       = 0;
3262
3263         status = smb_raw_setpathinfo(cli2->tree, &sfi);
3264         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3265
3266         torture_wait_for_oplock_break(tctx);
3267         CHECK_VAL(break_info.count, 0);
3268
3269         smbcli_close(cli1->tree, fnum);
3270
3271 done:
3272         smb_raw_exit(cli1->session);
3273         smb_raw_exit(cli2->session);
3274         smbcli_deltree(cli1->tree, BASEDIR);
3275         return ret;
3276 }
3277
3278 /**
3279  * Similar to batch17/18, but test with open share mode rather than
3280  * share_none.
3281  */
3282 static bool test_raw_oplock_batch26(struct torture_context *tctx,
3283     struct smbcli_state *cli1, struct smbcli_state *cli2)
3284 {
3285         const char *fname1 = BASEDIR "\\test_batch26_1.dat";
3286         const char *fname2 = BASEDIR "\\test_batch26_2.dat";
3287         NTSTATUS status;
3288         bool ret = true;
3289         union smb_open io;
3290         union smb_rename rn;
3291         uint16_t fnum=0;
3292
3293         if (!torture_setup_dir(cli1, BASEDIR)) {
3294                 return false;
3295         }
3296
3297         /* cleanup */
3298         smbcli_unlink(cli1->tree, fname1);
3299         smbcli_unlink(cli1->tree, fname2);
3300
3301         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3302             cli1->tree);
3303
3304         /*
3305           base ntcreatex parms
3306         */
3307         io.generic.level = RAW_OPEN_NTCREATEX;
3308         io.ntcreatex.in.root_fid.fnum = 0;
3309         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3310         io.ntcreatex.in.alloc_size = 0;
3311         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3312         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3313             NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
3314         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3315         io.ntcreatex.in.create_options = 0;
3316         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3317         io.ntcreatex.in.security_flags = 0;
3318         io.ntcreatex.in.fname = fname1;
3319
3320         torture_comment(tctx, "BATCH26: open a file with an batch oplock "
3321             "(share mode: none)\n");
3322
3323         ZERO_STRUCT(break_info);
3324         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3325                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3326                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3327
3328
3329         status = smb_raw_open(cli1->tree, tctx, &io);
3330         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3331         fnum = io.ntcreatex.out.file.fnum;
3332         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3333
3334         torture_comment(tctx, "rename should trigger a break\n");
3335         ZERO_STRUCT(rn);
3336         rn.generic.level = RAW_RENAME_RENAME;
3337         rn.rename.in.pattern1 = fname1;
3338         rn.rename.in.pattern2 = fname2;
3339         rn.rename.in.attrib = 0;
3340
3341         torture_comment(tctx, "trying rename while first file open\n");
3342         status = smb_raw_rename(cli2->tree, &rn);
3343         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
3344
3345         torture_wait_for_oplock_break(tctx);
3346         CHECK_VAL(break_info.count, 1);
3347         CHECK_VAL(break_info.failures, 0);
3348         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3349
3350         /* Close and reopen with batch again. */
3351         smbcli_close(cli1->tree, fnum);
3352         ZERO_STRUCT(break_info);
3353
3354         status = smb_raw_open(cli1->tree, tctx, &io);
3355         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3356         fnum = io.ntcreatex.out.file.fnum;
3357         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3358
3359         /* Now try ntrename. */
3360         torture_comment(tctx, "ntrename should trigger a break\n");
3361         ZERO_STRUCT(rn);
3362         rn.generic.level = RAW_RENAME_NTRENAME;
3363         rn.ntrename.in.attrib   = 0;
3364         rn.ntrename.in.flags    = RENAME_FLAG_RENAME;
3365         rn.ntrename.in.old_name = fname1;
3366         rn.ntrename.in.new_name = fname2;
3367         torture_comment(tctx, "trying rename while first file open\n");
3368         status = smb_raw_rename(cli2->tree, &rn);
3369         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
3370
3371         torture_wait_for_oplock_break(tctx);
3372         CHECK_VAL(break_info.count, 1);
3373         CHECK_VAL(break_info.failures, 0);
3374         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3375
3376         smbcli_close(cli1->tree, fnum);
3377
3378 done:
3379         smb_raw_exit(cli1->session);
3380         smb_raw_exit(cli2->session);
3381         smbcli_deltree(cli1->tree, BASEDIR);
3382         return ret;
3383 }
3384
3385 /* Test how oplocks work on streams. */
3386 static bool test_raw_oplock_stream1(struct torture_context *tctx,
3387                                     struct smbcli_state *cli1,
3388                                     struct smbcli_state *cli2)
3389 {
3390         NTSTATUS status;
3391         union smb_open io;
3392         const char *fname_base = BASEDIR "\\test_stream1.txt";
3393         const char *stream = "Stream One:$DATA";
3394         const char *fname_stream, *fname_default_stream;
3395         const char *default_stream = "::$DATA";
3396         bool ret = true;
3397         int fnum = -1;
3398         int i;
3399         int stream_fnum = -1;
3400         uint32_t batch_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
3401             NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK | NTCREATEX_FLAGS_EXTENDED;
3402         uint32_t exclusive_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
3403             NTCREATEX_FLAGS_EXTENDED;
3404
3405 #define NSTREAM_OPLOCK_RESULTS 8
3406         struct {
3407                 const char **fname;
3408                 bool open_base_file;
3409                 uint32_t oplock_req;
3410                 uint32_t oplock_granted;
3411         } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
3412                 /* Request oplock on stream without the base file open. */
3413                 {&fname_stream, false, batch_req, NO_OPLOCK_RETURN},
3414                 {&fname_default_stream, false, batch_req, NO_OPLOCK_RETURN},
3415                 {&fname_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3416                 {&fname_default_stream, false,  exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3417
3418                 /* Request oplock on stream with the base file open. */
3419                 {&fname_stream, true, batch_req, NO_OPLOCK_RETURN},
3420                 {&fname_default_stream, true, batch_req, NO_OPLOCK_RETURN},
3421                 {&fname_stream, true, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3422                 {&fname_default_stream, true,  exclusive_req, LEVEL_II_OPLOCK_RETURN},
3423
3424         };
3425
3426
3427         /* Only passes against windows at the moment. */
3428         if (torture_setting_bool(tctx, "samba3", false) ||
3429             torture_setting_bool(tctx, "samba4", false)) {
3430                 torture_skip(tctx, "STREAM1 disabled against samba3+4\n");
3431         }
3432
3433         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
3434         fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
3435                                                default_stream);
3436
3437         if (!torture_setup_dir(cli1, BASEDIR)) {
3438                 return false;
3439         }
3440         smbcli_unlink(cli1->tree, fname_base);
3441
3442         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3443         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3444
3445         /* Setup generic open parameters. */
3446         io.generic.level = RAW_OPEN_NTCREATEX;
3447         io.ntcreatex.in.root_fid.fnum = 0;
3448         io.ntcreatex.in.access_mask = (SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|
3449             SEC_FILE_APPEND_DATA|SEC_STD_READ_CONTROL);
3450         io.ntcreatex.in.create_options = 0;
3451         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3452         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3453             NTCREATEX_SHARE_ACCESS_WRITE;
3454         io.ntcreatex.in.alloc_size = 0;
3455         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3456         io.ntcreatex.in.security_flags = 0;
3457
3458         /* Create the file with a stream */
3459         io.ntcreatex.in.fname = fname_stream;
3460         io.ntcreatex.in.flags = 0;
3461         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
3462         status = smb_raw_open(cli1->tree, tctx, &io);
3463         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3464         smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3465
3466         /* Change the disposition to open now that the file has been created. */
3467         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
3468
3469         /* Try some permutations of taking oplocks on streams. */
3470         for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
3471                 const char *fname = *stream_oplock_results[i].fname;
3472                 bool open_base_file = stream_oplock_results[i].open_base_file;
3473                 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
3474                 uint32_t oplock_granted =
3475                     stream_oplock_results[i].oplock_granted;
3476                 int base_fnum = -1;
3477
3478                 if (open_base_file) {
3479                         torture_comment(tctx, "Opening base file: %s with "
3480                             "%d\n", fname_base, batch_req);
3481                         io.ntcreatex.in.fname = fname_base;
3482                         io.ntcreatex.in.flags = batch_req;
3483                         status = smb_raw_open(cli2->tree, tctx, &io);
3484                         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3485                         CHECK_VAL(io.ntcreatex.out.oplock_level,
3486                             BATCH_OPLOCK_RETURN);
3487                         base_fnum = io.ntcreatex.out.file.fnum;
3488                 }
3489
3490                 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
3491                     fname, oplock_req);
3492                 io.ntcreatex.in.fname = fname;
3493                 io.ntcreatex.in.flags = oplock_req;
3494
3495                 /* Do the open with the desired oplock on the stream. */
3496                 status = smb_raw_open(cli1->tree, tctx, &io);
3497                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3498                 CHECK_VAL(io.ntcreatex.out.oplock_level, oplock_granted);
3499                 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3500
3501                 /* Cleanup the base file if it was opened. */
3502                 if (base_fnum != -1) {
3503                         smbcli_close(cli2->tree, base_fnum);
3504                 }
3505         }
3506
3507         /* Open the stream with an exclusive oplock. */
3508         torture_comment(tctx, "Opening stream: %s with %d\n",
3509             fname_stream, exclusive_req);
3510         io.ntcreatex.in.fname = fname_stream;
3511         io.ntcreatex.in.flags = exclusive_req;
3512         status = smb_raw_open(cli1->tree, tctx, &io);
3513         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3514         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
3515         stream_fnum = io.ntcreatex.out.file.fnum;
3516
3517         /* Open the base file and see if it contends. */
3518         ZERO_STRUCT(break_info);
3519         torture_comment(tctx, "Opening base file: %s with "
3520             "%d\n", fname_base, batch_req);
3521         io.ntcreatex.in.fname = fname_base;
3522         io.ntcreatex.in.flags = batch_req;
3523         status = smb_raw_open(cli2->tree, tctx, &io);
3524         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3525         CHECK_VAL(io.ntcreatex.out.oplock_level,
3526             BATCH_OPLOCK_RETURN);
3527         smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3528
3529         torture_wait_for_oplock_break(tctx);
3530         CHECK_VAL(break_info.count, 0);
3531         CHECK_VAL(break_info.failures, 0);
3532
3533         /* Open the stream again to see if it contends. */
3534         ZERO_STRUCT(break_info);
3535         torture_comment(tctx, "Opening stream again: %s with "
3536             "%d\n", fname_base, batch_req);
3537         io.ntcreatex.in.fname = fname_stream;
3538         io.ntcreatex.in.flags = exclusive_req;
3539         status = smb_raw_open(cli2->tree, tctx, &io);
3540         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3541         CHECK_VAL(io.ntcreatex.out.oplock_level,
3542             LEVEL_II_OPLOCK_RETURN);
3543         smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3544
3545         torture_wait_for_oplock_break(tctx);
3546         CHECK_VAL(break_info.count, 1);
3547         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3548         CHECK_VAL(break_info.failures, 0);
3549
3550         /* Close the stream. */
3551         if (stream_fnum != -1) {
3552                 smbcli_close(cli1->tree, stream_fnum);
3553         }
3554
3555  done:
3556         smbcli_close(cli1->tree, fnum);
3557         smb_raw_exit(cli1->session);
3558         smb_raw_exit(cli2->session);
3559         smbcli_deltree(cli1->tree, BASEDIR);
3560         return ret;
3561 }
3562
3563 static bool test_raw_oplock_doc(struct torture_context *tctx,
3564                                 struct smbcli_state *cli)
3565 {
3566         const char *fname = BASEDIR "\\test_oplock_doc.dat";
3567         NTSTATUS status;
3568         bool ret = true;
3569         union smb_open io;
3570         uint16_t fnum=0;
3571
3572         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
3573
3574         /* cleanup */
3575         smbcli_unlink(cli->tree, fname);
3576
3577         smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_given,
3578                               cli->tree);
3579
3580         /*
3581           base ntcreatex parms
3582         */
3583         io.generic.level = RAW_OPEN_NTCREATEX;
3584         io.ntcreatex.in.root_fid.fnum = 0;
3585         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3586         io.ntcreatex.in.alloc_size = 0;
3587         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3588         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3589         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3590         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3591         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3592         io.ntcreatex.in.security_flags = 0;
3593         io.ntcreatex.in.fname = fname;
3594
3595         torture_comment(tctx, "open a delete-on-close file with a batch "
3596                         "oplock\n");
3597         ZERO_STRUCT(break_info);
3598         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3599             NTCREATEX_FLAGS_REQUEST_OPLOCK |
3600             NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3601
3602         status = smb_raw_open(cli->tree, tctx, &io);
3603         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3604         fnum = io.ntcreatex.out.file.fnum;
3605         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3606
3607         smbcli_close(cli->tree, fnum);
3608
3609 done:
3610         smb_raw_exit(cli->session);
3611         smbcli_deltree(cli->tree, BASEDIR);
3612         return ret;
3613 }
3614
3615 /* Open a file with a batch oplock, then open it again from a second client
3616  * requesting no oplock. Having two open file handles should break our own
3617  * oplock during BRL acquisition.
3618  */
3619 static bool test_raw_oplock_brl1(struct torture_context *tctx,
3620                                  struct smbcli_state *cli1,
3621                                  struct smbcli_state *cli2)
3622 {
3623         const char *fname = BASEDIR "\\test_batch_brl.dat";
3624         /*int fname, f;*/
3625         bool ret = true;
3626         uint8_t buf[1000];
3627         union smb_open io;
3628         NTSTATUS status;
3629         uint16_t fnum=0;
3630         uint16_t fnum2=0;
3631
3632         if (!torture_setup_dir(cli1, BASEDIR)) {
3633                 return false;
3634         }
3635
3636         /* cleanup */
3637         smbcli_unlink(cli1->tree, fname);
3638
3639         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3640                               cli1->tree);
3641
3642         /*
3643           base ntcreatex parms
3644         */
3645         io.generic.level = RAW_OPEN_NTCREATEX;
3646         io.ntcreatex.in.root_fid.fnum = 0;
3647         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3648                                       SEC_RIGHTS_FILE_WRITE;
3649         io.ntcreatex.in.alloc_size = 0;
3650         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3651         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3652                                        NTCREATEX_SHARE_ACCESS_WRITE;
3653         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3654         io.ntcreatex.in.create_options = 0;
3655         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3656         io.ntcreatex.in.security_flags = 0;
3657         io.ntcreatex.in.fname = fname;
3658
3659         /*
3660           with a batch oplock we get a break
3661         */
3662         torture_comment(tctx, "open with batch oplock\n");
3663         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3664                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3665                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3666
3667         status = smb_raw_open(cli1->tree, tctx, &io);
3668         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3669         fnum = io.ntcreatex.out.file.fnum;
3670         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3671         /* create a file with bogus data */
3672         memset(buf, 0, sizeof(buf));
3673
3674         if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3675                          sizeof(buf))
3676         {
3677                 torture_comment(tctx, "Failed to create file\n");
3678                 goto done;
3679         }
3680
3681         torture_comment(tctx, "a 2nd open should give a break\n");
3682         ZERO_STRUCT(break_info);
3683
3684         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3685         status = smb_raw_open(cli2->tree, tctx, &io);
3686         fnum2 = io.ntcreatex.out.file.fnum;
3687         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3688         CHECK_VAL(break_info.count, 1);
3689         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3690         CHECK_VAL(break_info.failures, 0);
3691         CHECK_VAL(break_info.fnum, fnum);
3692
3693         ZERO_STRUCT(break_info);
3694
3695         torture_comment(tctx, "a self BRL acquisition should break to none\n");
3696
3697         status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3698         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3699
3700         torture_wait_for_oplock_break(tctx);
3701         CHECK_VAL(break_info.count, 1);
3702         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3703         CHECK_VAL(break_info.fnum, fnum);
3704         CHECK_VAL(break_info.failures, 0);
3705
3706         /* expect no oplock break */
3707         ZERO_STRUCT(break_info);
3708         status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3709         CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3710
3711         torture_wait_for_oplock_break(tctx);
3712         CHECK_VAL(break_info.count, 0);
3713         CHECK_VAL(break_info.level, 0);
3714         CHECK_VAL(break_info.fnum, 0);
3715         CHECK_VAL(break_info.failures, 0);
3716
3717         smbcli_close(cli1->tree, fnum);
3718         smbcli_close(cli2->tree, fnum2);
3719
3720 done:
3721         smb_raw_exit(cli1->session);
3722         smb_raw_exit(cli2->session);
3723         smbcli_deltree(cli1->tree, BASEDIR);
3724         return ret;
3725
3726 }
3727
3728 /* Open a file with a batch oplock on one client and then acquire a brl.
3729  * We should not contend our own oplock.
3730  */
3731 static bool test_raw_oplock_brl2(struct torture_context *tctx, struct smbcli_state *cli1)
3732 {
3733         const char *fname = BASEDIR "\\test_batch_brl.dat";
3734         /*int fname, f;*/
3735         bool ret = true;
3736         uint8_t buf[1000];
3737         union smb_open io;
3738         NTSTATUS status;
3739         uint16_t fnum=0;
3740
3741         if (!torture_setup_dir(cli1, BASEDIR)) {
3742                 return false;
3743         }
3744
3745         /* cleanup */
3746         smbcli_unlink(cli1->tree, fname);
3747
3748         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3749                               cli1->tree);
3750
3751         /*
3752           base ntcreatex parms
3753         */
3754         io.generic.level = RAW_OPEN_NTCREATEX;
3755         io.ntcreatex.in.root_fid.fnum = 0;
3756         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3757                                       SEC_RIGHTS_FILE_WRITE;
3758         io.ntcreatex.in.alloc_size = 0;
3759         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3760         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3761                                        NTCREATEX_SHARE_ACCESS_WRITE;
3762         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3763         io.ntcreatex.in.create_options = 0;
3764         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3765         io.ntcreatex.in.security_flags = 0;
3766         io.ntcreatex.in.fname = fname;
3767
3768         /*
3769           with a batch oplock we get a break
3770         */
3771         torture_comment(tctx, "open with batch oplock\n");
3772         ZERO_STRUCT(break_info);
3773         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3774                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3775                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3776
3777         status = smb_raw_open(cli1->tree, tctx, &io);
3778         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3779         fnum = io.ntcreatex.out.file.fnum;
3780         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3781
3782         /* create a file with bogus data */
3783         memset(buf, 0, sizeof(buf));
3784
3785         if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3786                          sizeof(buf))
3787         {
3788                 torture_comment(tctx, "Failed to create file\n");
3789                 goto done;
3790         }
3791
3792         torture_comment(tctx, "a self BRL acquisition should not break to "
3793                         "none\n");
3794
3795         status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3796         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3797
3798         status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3799         CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3800
3801         /* With one file handle open a BRL should not contend our oplock.
3802          * Thus, no oplock break will be received and the entire break_info
3803          * struct will be 0 */
3804         torture_wait_for_oplock_break(tctx);
3805         CHECK_VAL(break_info.fnum, 0);
3806         CHECK_VAL(break_info.count, 0);
3807         CHECK_VAL(break_info.level, 0);
3808         CHECK_VAL(break_info.failures, 0);
3809
3810         smbcli_close(cli1->tree, fnum);
3811
3812 done:
3813         smb_raw_exit(cli1->session);
3814         smbcli_deltree(cli1->tree, BASEDIR);
3815         return ret;
3816 }
3817
3818 /* Open a file with a batch oplock twice from one client and then acquire a
3819  * brl. BRL acquisition should break our own oplock.
3820  */
3821 static bool test_raw_oplock_brl3(struct torture_context *tctx,
3822                                  struct smbcli_state *cli1)
3823 {
3824         const char *fname = BASEDIR "\\test_batch_brl.dat";
3825         bool ret = true;
3826         uint8_t buf[1000];
3827         bool correct = true;
3828         union smb_open io;
3829         NTSTATUS status;
3830         uint16_t fnum=0;
3831         uint16_t fnum2=0;
3832
3833         if (!torture_setup_dir(cli1, BASEDIR)) {
3834                 return false;
3835         }
3836
3837         /* cleanup */
3838         smbcli_unlink(cli1->tree, fname);
3839
3840         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3841                               cli1->tree);
3842
3843         /*
3844           base ntcreatex parms
3845         */
3846         io.generic.level = RAW_OPEN_NTCREATEX;
3847         io.ntcreatex.in.root_fid.fnum = 0;
3848         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3849                                       SEC_RIGHTS_FILE_WRITE;
3850         io.ntcreatex.in.alloc_size = 0;
3851         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3852         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3853                                        NTCREATEX_SHARE_ACCESS_WRITE;
3854         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3855         io.ntcreatex.in.create_options = 0;
3856         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3857         io.ntcreatex.in.security_flags = 0;
3858         io.ntcreatex.in.fname = fname;
3859
3860         /*
3861           with a batch oplock we get a break
3862         */
3863         torture_comment(tctx, "open with batch oplock\n");
3864         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3865                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3866                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3867
3868         status = smb_raw_open(cli1->tree, tctx, &io);
3869         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3870         fnum = io.ntcreatex.out.file.fnum;
3871         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3872
3873         /* create a file with bogus data */
3874         memset(buf, 0, sizeof(buf));
3875
3876         if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3877                          sizeof(buf))
3878         {
3879                 torture_comment(tctx, "Failed to create file\n");
3880                 correct = false;
3881                 goto done;
3882         }
3883
3884         torture_comment(tctx, "a 2nd open should give a break\n");
3885         ZERO_STRUCT(break_info);
3886
3887         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3888         status = smb_raw_open(cli1->tree, tctx, &io);
3889         fnum2 = io.ntcreatex.out.file.fnum;
3890         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3891         CHECK_VAL(break_info.count, 1);
3892         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3893         CHECK_VAL(break_info.failures, 0);
3894         CHECK_VAL(break_info.fnum, fnum);
3895
3896         ZERO_STRUCT(break_info);
3897
3898         torture_comment(tctx, "a self BRL acquisition should break to none\n");
3899
3900         status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3901         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3902
3903         torture_wait_for_oplock_break(tctx);
3904         CHECK_VAL(break_info.count, 1);
3905         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3906         CHECK_VAL(break_info.fnum, fnum);
3907         CHECK_VAL(break_info.failures, 0);
3908
3909         /* expect no oplock break */
3910         ZERO_STRUCT(break_info);
3911         status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3912         CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3913
3914         torture_wait_for_oplock_break(tctx);
3915         CHECK_VAL(break_info.count, 0);
3916         CHECK_VAL(break_info.level, 0);
3917         CHECK_VAL(break_info.fnum, 0);
3918         CHECK_VAL(break_info.failures, 0);
3919
3920         smbcli_close(cli1->tree, fnum);
3921         smbcli_close(cli1->tree, fnum2);
3922
3923 done:
3924         smb_raw_exit(cli1->session);
3925         smbcli_deltree(cli1->tree, BASEDIR);
3926         return ret;
3927 }
3928
3929 /*
3930  * Open a file with an exclusive oplock from the 1st client and acquire a
3931  * brl. Then open the same file from the 2nd client that should give oplock
3932  * break with level2 to the 1st and return no oplock to the 2nd.
3933  */
3934 static bool test_raw_oplock_brl4(struct torture_context *tctx,
3935                                  struct smbcli_state *cli1,
3936                                  struct smbcli_state *cli2)
3937 {
3938         const char *fname = BASEDIR "\\test_batch_brl.dat";
3939         bool ret = true;
3940         uint8_t buf[1000];
3941         union smb_open io;
3942         NTSTATUS status;
3943         uint16_t fnum = 0;
3944         uint16_t fnum2 = 0;
3945
3946         if (!torture_setup_dir(cli1, BASEDIR)) {
3947                 return false;
3948         }
3949
3950         /* cleanup */
3951         smbcli_unlink(cli1->tree, fname);
3952
3953         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3954                               cli1->tree);
3955
3956         /*
3957           base ntcreatex parms
3958         */
3959         io.generic.level = RAW_OPEN_NTCREATEX;
3960         io.ntcreatex.in.root_fid.fnum = 0;
3961         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3962                                       SEC_RIGHTS_FILE_WRITE;
3963         io.ntcreatex.in.alloc_size = 0;
3964         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3965         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3966                                        NTCREATEX_SHARE_ACCESS_WRITE;
3967         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3968         io.ntcreatex.in.create_options = 0;
3969         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3970         io.ntcreatex.in.security_flags = 0;
3971         io.ntcreatex.in.fname = fname;
3972
3973         torture_comment(tctx, "open with exclusive oplock\n");
3974         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3975                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
3976
3977         status = smb_raw_open(cli1->tree, tctx, &io);
3978
3979         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3980         fnum = io.ntcreatex.out.file.fnum;
3981         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
3982
3983         /* create a file with bogus data */
3984         memset(buf, 0, sizeof(buf));
3985
3986         if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3987                          sizeof(buf))
3988         {
3989                 torture_comment(tctx, "Failed to create file\n");
3990                 goto done;
3991         }
3992
3993         status = smbcli_lock(cli1->tree, fnum, 0, 1, 0, WRITE_LOCK);
3994         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3995
3996         torture_comment(tctx, "a 2nd open should give a break to the 1st\n");
3997         ZERO_STRUCT(break_info);
3998
3999         status = smb_raw_open(cli2->tree, tctx, &io);
4000
4001         CHECK_STATUS(tctx, status, NT_STATUS_OK);
4002         CHECK_VAL(break_info.count, 1);
4003         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
4004         CHECK_VAL(break_info.failures, 0);
4005         CHECK_VAL(break_info.fnum, fnum);
4006
4007         torture_comment(tctx, "and return no oplock to the 2nd\n");
4008         fnum2 = io.ntcreatex.out.file.fnum;
4009         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
4010
4011         smbcli_close(cli1->tree, fnum);
4012         smbcli_close(cli2->tree, fnum2);
4013
4014 done:
4015         smb_raw_exit(cli1->session);
4016         smb_raw_exit(cli2->session);
4017         smbcli_deltree(cli1->tree, BASEDIR);
4018         return ret;
4019 }
4020
4021 /*
4022    basic testing of oplocks
4023 */
4024 struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
4025 {
4026         struct torture_suite *suite = torture_suite_create(mem_ctx, "oplock");
4027
4028         torture_suite_add_2smb_test(suite, "exclusive1", test_raw_oplock_exclusive1);
4029         torture_suite_add_2smb_test(suite, "exclusive2", test_raw_oplock_exclusive2);
4030         torture_suite_add_2smb_test(suite, "exclusive3", test_raw_oplock_exclusive3);
4031         torture_suite_add_2smb_test(suite, "exclusive4", test_raw_oplock_exclusive4);
4032         torture_suite_add_2smb_test(suite, "exclusive5", test_raw_oplock_exclusive5);
4033         torture_suite_add_2smb_test(suite, "exclusive6", test_raw_oplock_exclusive6);
4034         torture_suite_add_2smb_test(suite, "exclusive7", test_raw_oplock_exclusive7);
4035         torture_suite_add_2smb_test(suite, "exclusive8",
4036                                     test_raw_oplock_exclusive8);
4037         torture_suite_add_2smb_test(suite, "batch1", test_raw_oplock_batch1);
4038         torture_suite_add_2smb_test(suite, "batch2", test_raw_oplock_batch2);
4039         torture_suite_add_2smb_test(suite, "batch3", test_raw_oplock_batch3);
4040         torture_suite_add_2smb_test(suite, "batch4", test_raw_oplock_batch4);
4041         torture_suite_add_2smb_test(suite, "batch5", test_raw_oplock_batch5);
4042         torture_suite_add_2smb_test(suite, "batch6", test_raw_oplock_batch6);
4043         torture_suite_add_2smb_test(suite, "batch7", test_raw_oplock_batch7);
4044         torture_suite_add_2smb_test(suite, "batch8", test_raw_oplock_batch8);
4045         torture_suite_add_2smb_test(suite, "batch9", test_raw_oplock_batch9);
4046         torture_suite_add_2smb_test(suite, "batch10", test_raw_oplock_batch10);
4047         torture_suite_add_2smb_test(suite, "batch11", test_raw_oplock_batch11);
4048         torture_suite_add_2smb_test(suite, "batch12", test_raw_oplock_batch12);
4049         torture_suite_add_2smb_test(suite, "batch13", test_raw_oplock_batch13);
4050         torture_suite_add_2smb_test(suite, "batch14", test_raw_oplock_batch14);
4051         torture_suite_add_2smb_test(suite, "batch15", test_raw_oplock_batch15);
4052         torture_suite_add_2smb_test(suite, "batch16", test_raw_oplock_batch16);
4053         torture_suite_add_2smb_test(suite, "batch17", test_raw_oplock_batch17);
4054         torture_suite_add_2smb_test(suite, "batch18", test_raw_oplock_batch18);
4055         torture_suite_add_2smb_test(suite, "batch19", test_raw_oplock_batch19);
4056         torture_suite_add_2smb_test(suite, "batch20", test_raw_oplock_batch20);
4057         torture_suite_add_2smb_test(suite, "batch21", test_raw_oplock_batch21);
4058         torture_suite_add_2smb_test(suite, "batch22", test_raw_oplock_batch22);
4059         torture_suite_add_2smb_test(suite, "batch23", test_raw_oplock_batch23);
4060         torture_suite_add_2smb_test(suite, "batch24", test_raw_oplock_batch24);
4061         torture_suite_add_2smb_test(suite, "batch25", test_raw_oplock_batch25);
4062         torture_suite_add_2smb_test(suite, "batch26", test_raw_oplock_batch26);
4063         torture_suite_add_2smb_test(suite, "stream1", test_raw_oplock_stream1);
4064         torture_suite_add_1smb_test(suite, "doc1", test_raw_oplock_doc);
4065         torture_suite_add_2smb_test(suite, "brl1", test_raw_oplock_brl1);
4066         torture_suite_add_1smb_test(suite, "brl2", test_raw_oplock_brl2);
4067         torture_suite_add_1smb_test(suite, "brl3", test_raw_oplock_brl3);
4068         torture_suite_add_2smb_test(suite, "brl4", test_raw_oplock_brl4);
4069
4070         return suite;
4071 }
4072
4073 /*
4074    stress testing of oplocks
4075 */
4076 bool torture_bench_oplock(struct torture_context *torture)
4077 {
4078         struct smbcli_state **cli;
4079         bool ret = true;
4080         TALLOC_CTX *mem_ctx = talloc_new(torture);
4081         int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
4082         int i, count=0;
4083         int timelimit = torture_setting_int(torture, "timelimit", 10);
4084         union smb_open io;
4085         struct timeval tv;
4086
4087         cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
4088
4089         torture_comment(torture, "Opening %d connections\n", torture_nprocs);
4090         for (i=0;i<torture_nprocs;i++) {
4091                 if (!torture_open_connection_ev(&cli[i], i, torture, torture->ev)) {
4092                         return false;
4093                 }
4094                 talloc_steal(mem_ctx, cli[i]);
4095                 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close, 
4096                                       cli[i]->tree);
4097         }
4098
4099         if (!torture_setup_dir(cli[0], BASEDIR)) {
4100                 ret = false;
4101                 goto done;
4102         }
4103
4104         io.ntcreatex.level = RAW_OPEN_NTCREATEX;
4105         io.ntcreatex.in.root_fid.fnum = 0;
4106         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
4107         io.ntcreatex.in.alloc_size = 0;
4108         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4109         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
4110         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4111         io.ntcreatex.in.create_options = 0;
4112         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4113         io.ntcreatex.in.security_flags = 0;
4114         io.ntcreatex.in.fname = BASEDIR "\\test.dat";
4115         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
4116                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
4117                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4118
4119         tv = timeval_current(); 
4120
4121         /*
4122           we open the same file with SHARE_ACCESS_NONE from all the
4123           connections in a round robin fashion. Each open causes an
4124           oplock break on the previous connection, which is answered
4125           by the oplock_handler_close() to close the file.
4126
4127           This measures how fast we can pass on oplocks, and stresses
4128           the oplock handling code
4129         */
4130         torture_comment(torture, "Running for %d seconds\n", timelimit);
4131         while (timeval_elapsed(&tv) < timelimit) {
4132                 for (i=0;i<torture_nprocs;i++) {
4133                         NTSTATUS status;
4134
4135                         status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
4136                         CHECK_STATUS(torture, status, NT_STATUS_OK);
4137                         count++;
4138                 }
4139
4140                 if (torture_setting_bool(torture, "progress", true)) {
4141                         torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
4142                 }
4143         }
4144
4145         torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
4146
4147         smb_raw_exit(cli[torture_nprocs-1]->session);
4148         
4149 done:
4150         smb_raw_exit(cli[0]->session);
4151         smbcli_deltree(cli[0]->tree, BASEDIR);
4152         talloc_free(mem_ctx);
4153         return ret;
4154 }
4155
4156
4157 static struct hold_oplock_info {
4158         const char *fname;
4159         bool close_on_break;
4160         uint32_t share_access;
4161         uint16_t fnum;
4162 } hold_info[] = {
4163         { BASEDIR "\\notshared_close", true,  
4164           NTCREATEX_SHARE_ACCESS_NONE, },
4165         { BASEDIR "\\notshared_noclose", false, 
4166           NTCREATEX_SHARE_ACCESS_NONE, },
4167         { BASEDIR "\\shared_close", true,  
4168           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
4169         { BASEDIR "\\shared_noclose", false,  
4170           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
4171 };
4172
4173 static bool oplock_handler_hold(struct smbcli_transport *transport, 
4174                                 uint16_t tid, uint16_t fnum, uint8_t level, 
4175                                 void *private_data)
4176 {
4177         struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
4178         struct hold_oplock_info *info;
4179         int i;
4180
4181         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4182                 if (hold_info[i].fnum == fnum) break;
4183         }
4184
4185         if (i == ARRAY_SIZE(hold_info)) {
4186                 printf("oplock break for unknown fnum %u\n", fnum);
4187                 return false;
4188         }
4189
4190         info = &hold_info[i];
4191
4192         if (info->close_on_break) {
4193                 printf("oplock break on %s - closing\n",
4194                        info->fname);
4195                 oplock_handler_close(transport, tid, fnum, level, private_data);
4196                 return true;
4197         }
4198
4199         printf("oplock break on %s - acking break\n", info->fname);
4200
4201         return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
4202 }
4203
4204
4205 /* 
4206    used for manual testing of oplocks - especially interaction with
4207    other filesystems (such as NFS and local access)
4208 */
4209 bool torture_hold_oplock(struct torture_context *torture, 
4210                          struct smbcli_state *cli)
4211 {
4212         struct tevent_context *ev = torture->ev;
4213         int i;
4214
4215         printf("Setting up open files with oplocks in %s\n", BASEDIR);
4216
4217         torture_assert(torture, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
4218
4219         smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
4220
4221         /* setup the files */
4222         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4223                 union smb_open io;
4224                 NTSTATUS status;
4225                 char c = 1;
4226
4227                 io.generic.level = RAW_OPEN_NTCREATEX;
4228                 io.ntcreatex.in.root_fid.fnum = 0;
4229                 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
4230                 io.ntcreatex.in.alloc_size = 0;
4231                 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4232                 io.ntcreatex.in.share_access = hold_info[i].share_access;
4233                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4234                 io.ntcreatex.in.create_options = 0;
4235                 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4236                 io.ntcreatex.in.security_flags = 0;
4237                 io.ntcreatex.in.fname = hold_info[i].fname;
4238                 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
4239                         NTCREATEX_FLAGS_REQUEST_OPLOCK |
4240                         NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4241                 printf("opening %s\n", hold_info[i].fname);
4242
4243                 status = smb_raw_open(cli->tree, cli, &io);
4244                 if (!NT_STATUS_IS_OK(status)) {
4245                         printf("Failed to open %s - %s\n", 
4246                                hold_info[i].fname, nt_errstr(status));
4247                         return false;
4248                 }
4249
4250                 if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
4251                         printf("Oplock not granted for %s - expected %d but got %d\n", 
4252                                hold_info[i].fname, BATCH_OPLOCK_RETURN, 
4253                                 io.ntcreatex.out.oplock_level);
4254                         return false;
4255                 }
4256                 hold_info[i].fnum = io.ntcreatex.out.file.fnum;
4257
4258                 /* make the file non-zero size */
4259                 if (smbcli_write(cli->tree, hold_info[i].fnum, 0, &c, 0, 1) != 1) {
4260                         printf("Failed to write to file\n");
4261                         return false;
4262                 }
4263         }
4264
4265         printf("Waiting for oplock events\n");
4266         tevent_loop_wait(ev);
4267
4268         return true;
4269 }