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