s4/torture: Allow receiving of oplock break requests in any order
[gd/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 "torture/torture.h"
22 #include "torture/smbtorture.h"
23 #include "librpc/gen_ndr/security.h"
24 #include "librpc/gen_ndr/ndr_security.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "libcli/raw/raw_proto.h"
27 #include "libcli/security/security.h"
28 #include "libcli/libcli.h"
29 #include "torture/util.h"
30 #include "lib/events/events.h"
31 #include "param/param.h"
32 #include "lib/cmdline/popt_common.h"
33 #include "libcli/resolve/resolve.h"
34
35 #define CHECK_VAL(v, correct) do { \
36         if ((v) != (correct)) { \
37                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
38                                 __location__, #v, (int)v, (int)correct); \
39                 ret = false; \
40         }} while (0)
41
42 #define CHECK_RANGE(v, min, max) do { \
43         if ((v) < (min) || (v) > (max)) { \
44                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got %d - should be between %d and %d\n", \
45                                 __location__, #v, (int)v, (int)min, (int)max); \
46                 ret = false; \
47         }} while (0)
48
49 #define CHECK_STRMATCH(v, correct) do { \
50         if (!v || strstr((v),(correct)) == NULL) { \
51                 torture_result(tctx, TORTURE_FAIL,  "(%s): wrong value for %s got '%s' - should be '%s'\n", \
52                                 __location__, #v, v?v:"NULL", correct); \
53                 ret = false; \
54         } \
55 } while (0)
56
57 #define CHECK_STATUS(tctx, status, correct) do { \
58         if (!NT_STATUS_EQUAL(status, correct)) { \
59                 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
60                        nt_errstr(status), nt_errstr(correct)); \
61                 ret = false; \
62                 goto done; \
63         }} while (0)
64
65
66 static struct {
67         int fnum;
68         uint8_t level;
69         int count;
70         int failures;
71 } break_info;
72
73 #define BASEDIR "\\test_oplock"
74
75 /*
76   a handler function for oplock break requests. Ack it as a break to level II if possible
77 */
78 static bool oplock_handler_ack_to_given(struct smbcli_transport *transport,
79                                         uint16_t tid, uint16_t fnum,
80                                         uint8_t level, void *private_data)
81 {
82         struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
83         const char *name;
84
85         break_info.fnum = fnum;
86         break_info.level = level;
87         break_info.count++;
88
89         switch (level) {
90         case OPLOCK_BREAK_TO_LEVEL_II:
91                 name = "level II";
92                 break;
93         case OPLOCK_BREAK_TO_NONE:
94                 name = "none";
95                 break;
96         default:
97                 name = "unknown";
98                 break_info.failures++;
99         }
100         printf("Acking to %s [0x%02X] in oplock handler\n",
101                 name, level);
102
103         return smbcli_oplock_ack(tree, fnum, level);
104 }
105
106 /*
107   a handler function for oplock break requests. Ack it as a break to none
108 */
109 static bool oplock_handler_ack_to_none(struct smbcli_transport *transport, 
110                                        uint16_t tid, uint16_t fnum, 
111                                        uint8_t level, void *private_data)
112 {
113         struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
114         break_info.fnum = fnum;
115         break_info.level = level;
116         break_info.count++;
117
118         printf("Acking to none in oplock handler\n");
119
120         return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
121 }
122
123 /*
124   a handler function for oplock break requests. Let it timeout
125 */
126 static bool oplock_handler_timeout(struct smbcli_transport *transport,
127                                    uint16_t tid, uint16_t fnum,
128                                    uint8_t level, void *private_data)
129 {
130         break_info.fnum = fnum;
131         break_info.level = level;
132         break_info.count++;
133
134         printf("Let oplock break timeout\n");
135         return true;
136 }
137
138 static void oplock_handler_close_recv(struct smbcli_request *req)
139 {
140         NTSTATUS status;
141         status = smbcli_request_simple_recv(req);
142         if (!NT_STATUS_IS_OK(status)) {
143                 printf("close failed in oplock_handler_close\n");
144                 break_info.failures++;
145         }
146 }
147
148 /*
149   a handler function for oplock break requests - close the file
150 */
151 static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t tid, 
152                                  uint16_t fnum, uint8_t level, void *private_data)
153 {
154         union smb_close io;
155         struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
156         struct smbcli_request *req;
157
158         break_info.fnum = fnum;
159         break_info.level = level;
160         break_info.count++;
161
162         io.close.level = RAW_CLOSE_CLOSE;
163         io.close.in.file.fnum = fnum;
164         io.close.in.write_time = 0;
165         req = smb_raw_close_send(tree, &io);
166         if (req == NULL) {
167                 printf("failed to send close in oplock_handler_close\n");
168                 return false;
169         }
170
171         req->async.fn = oplock_handler_close_recv;
172         req->async.private_data = NULL;
173
174         return true;
175 }
176
177 static bool open_connection_no_level2_oplocks(struct torture_context *tctx,
178                                               struct smbcli_state **c)
179 {
180         NTSTATUS status;
181         struct smbcli_options options;
182         struct smbcli_session_options session_options;
183
184         lp_smbcli_options(tctx->lp_ctx, &options);
185         lp_smbcli_session_options(tctx->lp_ctx, &session_options);
186
187         options.use_level2_oplocks = false;
188
189         status = smbcli_full_connection(tctx, c,
190                                         torture_setting_string(tctx, "host", NULL),
191                                         lp_smb_ports(tctx->lp_ctx),
192                                         torture_setting_string(tctx, "share", NULL),
193                                         NULL, lp_socket_options(tctx->lp_ctx), cmdline_credentials,
194                                         lp_resolve_context(tctx->lp_ctx),
195                                         tctx->ev, &options, &session_options,
196                                         lp_iconv_convenience(tctx->lp_ctx),
197                                         lp_gensec_settings(tctx, tctx->lp_ctx));
198         if (!NT_STATUS_IS_OK(status)) {
199                 torture_comment(tctx, "Failed to open connection - %s\n",
200                                 nt_errstr(status));
201                 return false;
202         }
203
204         return true;
205 }
206
207 /*
208    Timer handler function notifies the registering function that time is up
209 */
210 static void timeout_cb(struct tevent_context *ev,
211                        struct tevent_timer *te,
212                        struct timeval current_time,
213                        void *private_data)
214 {
215         bool *timesup = (bool *)private_data;
216         *timesup = true;
217         return;
218 }
219
220 /*
221    Wait a short period of time to receive a single oplock break request
222 */
223 static void torture_wait_for_oplock_break(struct torture_context *tctx)
224 {
225         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
226         struct tevent_timer *te = NULL;
227         struct timeval ne;
228         bool timesup = false;
229         int old_count = break_info.count;
230
231         /* Wait .1 seconds for an oplock break */
232         ne = tevent_timeval_current_ofs(0, 100000);
233
234         if ((te = event_add_timed(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup))
235             == NULL)
236         {
237                 torture_comment(tctx, "Failed to wait for an oplock break. "
238                                       "test results may not be accurate.");
239                 goto done;
240         }
241
242         while (!timesup && break_info.count < old_count + 1) {
243                 if (event_loop_once(tctx->ev) != 0) {
244                         torture_comment(tctx, "Failed to wait for an oplock "
245                                               "break. test results may not be "
246                                               "accurate.");
247                         goto done;
248                 }
249         }
250
251 done:
252         /* We don't know if the timed event fired and was freed, we received
253          * our oplock break, or some other event triggered the loop.  Thus,
254          * we create a tmp_ctx to be able to safely free/remove the timed
255          * event in all 3 cases. */
256         talloc_free(tmp_ctx);
257
258         return;
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 = 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 = 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 = 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_NONE;
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, 1);
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 = 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 = 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, 1);
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 = 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 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
700 {
701         const char *fname = BASEDIR "\\test_batch1.dat";
702         NTSTATUS status;
703         bool ret = true;
704         union smb_open io;
705         union smb_unlink unl;
706         uint16_t fnum=0;
707         char c = 0;
708
709         if (!torture_setup_dir(cli1, BASEDIR)) {
710                 return false;
711         }
712
713         /* cleanup */
714         smbcli_unlink(cli1->tree, fname);
715
716         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
717
718         /*
719           base ntcreatex parms
720         */
721         io.generic.level = RAW_OPEN_NTCREATEX;
722         io.ntcreatex.in.root_fid = 0;
723         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
724         io.ntcreatex.in.alloc_size = 0;
725         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
726         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
727         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
728         io.ntcreatex.in.create_options = 0;
729         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
730         io.ntcreatex.in.security_flags = 0;
731         io.ntcreatex.in.fname = fname;
732
733         /*
734           with a batch oplock we get a break
735         */
736         torture_comment(tctx, "BATCH1: open with batch oplock\n");
737         ZERO_STRUCT(break_info);
738         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
739                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
740                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
741         status = smb_raw_open(cli1->tree, tctx, &io);
742         CHECK_STATUS(tctx, status, NT_STATUS_OK);
743         fnum = io.ntcreatex.out.file.fnum;
744         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
745
746         torture_comment(tctx, "unlink should generate a break\n");
747         unl.unlink.in.pattern = fname;
748         unl.unlink.in.attrib = 0;
749         status = smb_raw_unlink(cli2->tree, &unl);
750         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
751
752         torture_wait_for_oplock_break(tctx);
753         CHECK_VAL(break_info.count, 1);
754         CHECK_VAL(break_info.fnum, fnum);
755         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
756         CHECK_VAL(break_info.failures, 0);
757
758         torture_comment(tctx, "2nd unlink should not generate a break\n");
759         ZERO_STRUCT(break_info);
760         status = smb_raw_unlink(cli2->tree, &unl);
761         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
762
763         torture_wait_for_oplock_break(tctx);
764         CHECK_VAL(break_info.count, 0);
765
766         torture_comment(tctx, "writing should generate a self break to none\n");
767         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
768
769         torture_wait_for_oplock_break(tctx);
770         torture_wait_for_oplock_break(tctx);
771         CHECK_VAL(break_info.count, 1);
772         CHECK_VAL(break_info.fnum, fnum);
773         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
774         CHECK_VAL(break_info.failures, 0);
775
776         smbcli_close(cli1->tree, fnum);
777
778 done:
779         smb_raw_exit(cli1->session);
780         smb_raw_exit(cli2->session);
781         smbcli_deltree(cli1->tree, BASEDIR);
782         return ret;
783 }
784
785 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
786 {
787         const char *fname = BASEDIR "\\test_batch2.dat";
788         NTSTATUS status;
789         bool ret = true;
790         union smb_open io;
791         union smb_unlink unl;
792         uint16_t fnum=0;
793         char c = 0;
794
795         if (!torture_setup_dir(cli1, BASEDIR)) {
796                 return false;
797         }
798
799         /* cleanup */
800         smbcli_unlink(cli1->tree, fname);
801
802         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
803
804         /*
805           base ntcreatex parms
806         */
807         io.generic.level = RAW_OPEN_NTCREATEX;
808         io.ntcreatex.in.root_fid = 0;
809         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
810         io.ntcreatex.in.alloc_size = 0;
811         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
812         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
813         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
814         io.ntcreatex.in.create_options = 0;
815         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
816         io.ntcreatex.in.security_flags = 0;
817         io.ntcreatex.in.fname = fname;
818
819         torture_comment(tctx, "BATCH2: open with batch oplock\n");
820         ZERO_STRUCT(break_info);
821         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
822                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
823                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
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, BATCH_OPLOCK_RETURN);
828
829         torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
830         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
831         unl.unlink.in.pattern = fname;
832         unl.unlink.in.attrib = 0;
833         status = smb_raw_unlink(cli2->tree, &unl);
834         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
835
836         torture_wait_for_oplock_break(tctx);
837         CHECK_VAL(break_info.count, 1);
838         CHECK_VAL(break_info.fnum, fnum);
839         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
840         CHECK_VAL(break_info.failures, 0);
841
842         torture_comment(tctx, "2nd unlink should not generate a break\n");
843         ZERO_STRUCT(break_info);
844         status = smb_raw_unlink(cli2->tree, &unl);
845         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
846
847         torture_wait_for_oplock_break(tctx);
848         CHECK_VAL(break_info.count, 0);
849
850         torture_comment(tctx, "writing should not generate a break\n");
851         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
852
853         torture_wait_for_oplock_break(tctx);
854         CHECK_VAL(break_info.count, 0);
855
856         smbcli_close(cli1->tree, fnum);
857
858 done:
859         smb_raw_exit(cli1->session);
860         smb_raw_exit(cli2->session);
861         smbcli_deltree(cli1->tree, BASEDIR);
862         return ret;
863 }
864
865 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
866 {
867         const char *fname = BASEDIR "\\test_batch3.dat";
868         NTSTATUS status;
869         bool ret = true;
870         union smb_open io;
871         union smb_unlink unl;
872         uint16_t fnum=0;
873
874         if (!torture_setup_dir(cli1, BASEDIR)) {
875                 return false;
876         }
877
878         /* cleanup */
879         smbcli_unlink(cli1->tree, fname);
880
881         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
882
883         /*
884           base ntcreatex parms
885         */
886         io.generic.level = RAW_OPEN_NTCREATEX;
887         io.ntcreatex.in.root_fid = 0;
888         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
889         io.ntcreatex.in.alloc_size = 0;
890         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
891         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
892         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
893         io.ntcreatex.in.create_options = 0;
894         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
895         io.ntcreatex.in.security_flags = 0;
896         io.ntcreatex.in.fname = fname;
897
898         torture_comment(tctx, "BATCH3: if we close on break then the unlink can succeed\n");
899         ZERO_STRUCT(break_info);
900         smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
901         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
902                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
903                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
904         status = smb_raw_open(cli1->tree, tctx, &io);
905         CHECK_STATUS(tctx, status, NT_STATUS_OK);
906         fnum = io.ntcreatex.out.file.fnum;
907         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
908
909         unl.unlink.in.pattern = fname;
910         unl.unlink.in.attrib = 0;
911         ZERO_STRUCT(break_info);
912         status = smb_raw_unlink(cli2->tree, &unl);
913         CHECK_STATUS(tctx, status, NT_STATUS_OK);
914
915         torture_wait_for_oplock_break(tctx);
916         CHECK_VAL(break_info.count, 1);
917         CHECK_VAL(break_info.fnum, fnum);
918         CHECK_VAL(break_info.level, 1);
919         CHECK_VAL(break_info.failures, 0);
920
921         smbcli_close(cli1->tree, fnum);
922
923 done:
924         smb_raw_exit(cli1->session);
925         smb_raw_exit(cli2->session);
926         smbcli_deltree(cli1->tree, BASEDIR);
927         return ret;
928 }
929
930 static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
931 {
932         const char *fname = BASEDIR "\\test_batch4.dat";
933         NTSTATUS status;
934         bool ret = true;
935         union smb_open io;
936         union smb_read rd;
937         uint16_t fnum=0;
938
939         if (!torture_setup_dir(cli1, BASEDIR)) {
940                 return false;
941         }
942
943         /* cleanup */
944         smbcli_unlink(cli1->tree, fname);
945
946         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
947
948         /*
949           base ntcreatex parms
950         */
951         io.generic.level = RAW_OPEN_NTCREATEX;
952         io.ntcreatex.in.root_fid = 0;
953         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
954         io.ntcreatex.in.alloc_size = 0;
955         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
956         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
957         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
958         io.ntcreatex.in.create_options = 0;
959         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
960         io.ntcreatex.in.security_flags = 0;
961         io.ntcreatex.in.fname = fname;
962
963         torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
964         ZERO_STRUCT(break_info);
965         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
966
967         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
968                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
969                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
970         status = smb_raw_open(cli1->tree, tctx, &io);
971         CHECK_STATUS(tctx, status, NT_STATUS_OK);
972         fnum = io.ntcreatex.out.file.fnum;
973         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
974
975         rd.read.level = RAW_READ_READ;
976         rd.read.in.file.fnum = fnum;
977         rd.read.in.count = 1;
978         rd.read.in.offset = 0;
979         rd.read.in.remaining = 0;
980         status = smb_raw_read(cli1->tree, &rd);
981         CHECK_STATUS(tctx, status, NT_STATUS_OK);
982         torture_wait_for_oplock_break(tctx);
983         CHECK_VAL(break_info.count, 0);
984         CHECK_VAL(break_info.failures, 0);
985
986         smbcli_close(cli1->tree, fnum);
987
988 done:
989         smb_raw_exit(cli1->session);
990         smb_raw_exit(cli2->session);
991         smbcli_deltree(cli1->tree, BASEDIR);
992         return ret;
993 }
994
995 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
996 {
997         const char *fname = BASEDIR "\\test_batch5.dat";
998         NTSTATUS status;
999         bool ret = true;
1000         union smb_open io;
1001         uint16_t fnum=0;
1002
1003         if (!torture_setup_dir(cli1, BASEDIR)) {
1004                 return false;
1005         }
1006
1007         /* cleanup */
1008         smbcli_unlink(cli1->tree, fname);
1009
1010         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1011
1012         /*
1013           base ntcreatex parms
1014         */
1015         io.generic.level = RAW_OPEN_NTCREATEX;
1016         io.ntcreatex.in.root_fid = 0;
1017         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1018         io.ntcreatex.in.alloc_size = 0;
1019         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1020         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1021         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1022         io.ntcreatex.in.create_options = 0;
1023         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1024         io.ntcreatex.in.security_flags = 0;
1025         io.ntcreatex.in.fname = fname;
1026
1027         torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1028         ZERO_STRUCT(break_info);
1029         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1030
1031         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1032                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1033                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1034         status = smb_raw_open(cli1->tree, tctx, &io);
1035         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1036         fnum = io.ntcreatex.out.file.fnum;
1037         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1038
1039         ZERO_STRUCT(break_info);
1040
1041         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1042         status = smb_raw_open(cli2->tree, tctx, &io);
1043         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1044
1045         torture_wait_for_oplock_break(tctx);
1046         CHECK_VAL(break_info.count, 1);
1047         CHECK_VAL(break_info.fnum, fnum);
1048         CHECK_VAL(break_info.level, 1);
1049         CHECK_VAL(break_info.failures, 0);
1050
1051         smbcli_close(cli1->tree, fnum);
1052
1053 done:
1054         smb_raw_exit(cli1->session);
1055         smb_raw_exit(cli2->session);
1056         smbcli_deltree(cli1->tree, BASEDIR);
1057         return ret;
1058 }
1059
1060 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1061 {
1062         const char *fname = BASEDIR "\\test_batch6.dat";
1063         NTSTATUS status;
1064         bool ret = true;
1065         union smb_open io;
1066         uint16_t fnum=0, fnum2=0;
1067         char c = 0;
1068
1069         if (!torture_setup_dir(cli1, BASEDIR)) {
1070                 return false;
1071         }
1072
1073         /* cleanup */
1074         smbcli_unlink(cli1->tree, fname);
1075
1076         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1077         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1078
1079         /*
1080           base ntcreatex parms
1081         */
1082         io.generic.level = RAW_OPEN_NTCREATEX;
1083         io.ntcreatex.in.root_fid = 0;
1084         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1085         io.ntcreatex.in.alloc_size = 0;
1086         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1087         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1088         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1089         io.ntcreatex.in.create_options = 0;
1090         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1091         io.ntcreatex.in.security_flags = 0;
1092         io.ntcreatex.in.fname = fname;
1093
1094         torture_comment(tctx, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1095         ZERO_STRUCT(break_info);
1096
1097         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
1098         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1099         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1100                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1101                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1102         status = smb_raw_open(cli1->tree, tctx, &io);
1103         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1104         fnum = io.ntcreatex.out.file.fnum;
1105         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1106
1107         ZERO_STRUCT(break_info);
1108
1109         status = smb_raw_open(cli2->tree, tctx, &io);
1110         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1111         fnum2 = io.ntcreatex.out.file.fnum;
1112         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1113
1114         //torture_wait_for_oplock_break(tctx);
1115         CHECK_VAL(break_info.count, 1);
1116         CHECK_VAL(break_info.fnum, fnum);
1117         CHECK_VAL(break_info.level, 1);
1118         CHECK_VAL(break_info.failures, 0);
1119         ZERO_STRUCT(break_info);
1120
1121         torture_comment(tctx, "write should trigger a break to none on both\n");
1122         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1123
1124         /* We expect two breaks */
1125         torture_wait_for_oplock_break(tctx);
1126         torture_wait_for_oplock_break(tctx);
1127
1128         CHECK_VAL(break_info.count, 2);
1129         CHECK_VAL(break_info.level, 0);
1130         CHECK_VAL(break_info.failures, 0);
1131
1132         smbcli_close(cli1->tree, fnum);
1133         smbcli_close(cli2->tree, fnum2);
1134
1135 done:
1136         smb_raw_exit(cli1->session);
1137         smb_raw_exit(cli2->session);
1138         smbcli_deltree(cli1->tree, BASEDIR);
1139         return ret;
1140 }
1141
1142 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1143 {
1144         const char *fname = BASEDIR "\\test_batch7.dat";
1145         NTSTATUS status;
1146         bool ret = true;
1147         union smb_open io;
1148         uint16_t fnum=0, fnum2=0;
1149
1150         if (!torture_setup_dir(cli1, BASEDIR)) {
1151                 return false;
1152         }
1153
1154         /* cleanup */
1155         smbcli_unlink(cli1->tree, fname);
1156
1157         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1158
1159         /*
1160           base ntcreatex parms
1161         */
1162         io.generic.level = RAW_OPEN_NTCREATEX;
1163         io.ntcreatex.in.root_fid = 0;
1164         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1165         io.ntcreatex.in.alloc_size = 0;
1166         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1167         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1168         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1169         io.ntcreatex.in.create_options = 0;
1170         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1171         io.ntcreatex.in.security_flags = 0;
1172         io.ntcreatex.in.fname = fname;
1173
1174         torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1175         ZERO_STRUCT(break_info);
1176         smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1177
1178         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1179         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1180         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1181                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1182                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1183         status = smb_raw_open(cli1->tree, tctx, &io);
1184         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1185         fnum2 = io.ntcreatex.out.file.fnum;
1186         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1187
1188         ZERO_STRUCT(break_info);
1189
1190         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1191                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1192                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1193         status = smb_raw_open(cli2->tree, tctx, &io);
1194         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1195         fnum = io.ntcreatex.out.file.fnum;
1196         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1197
1198         torture_wait_for_oplock_break(tctx);
1199         CHECK_VAL(break_info.count, 1);
1200         CHECK_VAL(break_info.fnum, fnum2);
1201         CHECK_VAL(break_info.level, 1);
1202         CHECK_VAL(break_info.failures, 0);
1203
1204         smbcli_close(cli2->tree, fnum);
1205
1206 done:
1207         smb_raw_exit(cli1->session);
1208         smb_raw_exit(cli2->session);
1209         smbcli_deltree(cli1->tree, BASEDIR);
1210         return ret;
1211 }
1212
1213 static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1214 {
1215         const char *fname = BASEDIR "\\test_batch8.dat";
1216         NTSTATUS status;
1217         bool ret = true;
1218         union smb_open io;
1219         uint16_t fnum=0, fnum2=0;
1220
1221         if (!torture_setup_dir(cli1, BASEDIR)) {
1222                 return false;
1223         }
1224
1225         /* cleanup */
1226         smbcli_unlink(cli1->tree, fname);
1227
1228         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1229
1230         /*
1231           base ntcreatex parms
1232         */
1233         io.generic.level = RAW_OPEN_NTCREATEX;
1234         io.ntcreatex.in.root_fid = 0;
1235         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1236         io.ntcreatex.in.alloc_size = 0;
1237         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1238         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1239         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1240         io.ntcreatex.in.create_options = 0;
1241         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1242         io.ntcreatex.in.security_flags = 0;
1243         io.ntcreatex.in.fname = fname;
1244
1245         torture_comment(tctx, "BATCH8: open with batch oplock\n");
1246         ZERO_STRUCT(break_info);
1247         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1248
1249         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1250                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1251                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1252         status = smb_raw_open(cli1->tree, tctx, &io);
1253         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1254         fnum = io.ntcreatex.out.file.fnum;
1255         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1256
1257         ZERO_STRUCT(break_info);
1258         torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
1259
1260         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1261                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1262                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1263         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1264         status = smb_raw_open(cli2->tree, tctx, &io);
1265         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1266         fnum2 = io.ntcreatex.out.file.fnum;
1267         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1268         torture_wait_for_oplock_break(tctx);
1269         CHECK_VAL(break_info.count, 0);
1270         CHECK_VAL(break_info.failures, 0);
1271
1272         smbcli_close(cli1->tree, fnum);
1273         smbcli_close(cli2->tree, fnum2);
1274
1275 done:
1276         smb_raw_exit(cli1->session);
1277         smb_raw_exit(cli2->session);
1278         smbcli_deltree(cli1->tree, BASEDIR);
1279         return ret;
1280 }
1281
1282 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1283 {
1284         const char *fname = BASEDIR "\\test_batch9.dat";
1285         NTSTATUS status;
1286         bool ret = true;
1287         union smb_open io;
1288         uint16_t fnum=0, fnum2=0;
1289         char c = 0;
1290
1291         if (!torture_setup_dir(cli1, BASEDIR)) {
1292                 return false;
1293         }
1294
1295         /* cleanup */
1296         smbcli_unlink(cli1->tree, fname);
1297
1298         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1299
1300         /*
1301           base ntcreatex parms
1302         */
1303         io.generic.level = RAW_OPEN_NTCREATEX;
1304         io.ntcreatex.in.root_fid = 0;
1305         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1306         io.ntcreatex.in.alloc_size = 0;
1307         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1308         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1309         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1310         io.ntcreatex.in.create_options = 0;
1311         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1312         io.ntcreatex.in.security_flags = 0;
1313         io.ntcreatex.in.fname = fname;
1314
1315         torture_comment(tctx, "BATCH9: open with attributes only can create file\n");
1316
1317         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1318                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1319                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1320         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1321         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1322         status = smb_raw_open(cli1->tree, tctx, &io);
1323         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1324         fnum = io.ntcreatex.out.file.fnum;
1325         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1326
1327         torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
1328
1329         ZERO_STRUCT(break_info);
1330         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1331
1332         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1333                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1334                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1335         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1336         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1337         status = smb_raw_open(cli2->tree, tctx, &io);
1338         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1339         fnum2 = io.ntcreatex.out.file.fnum;
1340         torture_wait_for_oplock_break(tctx);
1341         CHECK_VAL(break_info.count, 1);
1342         CHECK_VAL(break_info.fnum, fnum);
1343         CHECK_VAL(break_info.failures, 0);
1344         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1345         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1346         smbcli_close(cli2->tree, fnum2);
1347
1348         torture_comment(tctx, "third oplocked open should grant level2 without break\n");
1349         ZERO_STRUCT(break_info);
1350         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1351         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1352         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1353                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1354                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1355         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1356         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1357         status = smb_raw_open(cli2->tree, tctx, &io);
1358         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1359         fnum2 = io.ntcreatex.out.file.fnum;
1360         torture_wait_for_oplock_break(tctx);
1361         CHECK_VAL(break_info.count, 0);
1362         CHECK_VAL(break_info.failures, 0);
1363         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1364
1365         ZERO_STRUCT(break_info);
1366
1367         torture_comment(tctx, "write should trigger a break to none on both\n");
1368         smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
1369
1370         /* We expect two breaks */
1371         torture_wait_for_oplock_break(tctx);
1372         torture_wait_for_oplock_break(tctx);
1373
1374         CHECK_VAL(break_info.count, 2);
1375         CHECK_VAL(break_info.level, 0);
1376         CHECK_VAL(break_info.failures, 0);
1377
1378         smbcli_close(cli1->tree, fnum);
1379         smbcli_close(cli2->tree, fnum2);
1380
1381 done:
1382         smb_raw_exit(cli1->session);
1383         smb_raw_exit(cli2->session);
1384         smbcli_deltree(cli1->tree, BASEDIR);
1385         return ret;
1386 }
1387
1388 static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1389 {
1390         const char *fname = BASEDIR "\\test_batch10.dat";
1391         NTSTATUS status;
1392         bool ret = true;
1393         union smb_open io;
1394         uint16_t fnum=0, fnum2=0;
1395
1396         if (!torture_setup_dir(cli1, BASEDIR)) {
1397                 return false;
1398         }
1399
1400         /* cleanup */
1401         smbcli_unlink(cli1->tree, fname);
1402
1403         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1404
1405         /*
1406           base ntcreatex parms
1407         */
1408         io.generic.level = RAW_OPEN_NTCREATEX;
1409         io.ntcreatex.in.root_fid = 0;
1410         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1411         io.ntcreatex.in.alloc_size = 0;
1412         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1413         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1414         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1415         io.ntcreatex.in.create_options = 0;
1416         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1417         io.ntcreatex.in.security_flags = 0;
1418         io.ntcreatex.in.fname = fname;
1419
1420         torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
1421         ZERO_STRUCT(break_info);
1422         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1423         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1424         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1425                 NTCREATEX_SHARE_ACCESS_WRITE|
1426                 NTCREATEX_SHARE_ACCESS_DELETE;
1427         status = smb_raw_open(cli1->tree, tctx, &io);
1428         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1429         fnum = io.ntcreatex.out.file.fnum;
1430         torture_wait_for_oplock_break(tctx);
1431         CHECK_VAL(break_info.count, 0);
1432         CHECK_VAL(break_info.failures, 0);
1433         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1434
1435         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1436
1437         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1438                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1439                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1440         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1441         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1442                 NTCREATEX_SHARE_ACCESS_WRITE|
1443                 NTCREATEX_SHARE_ACCESS_DELETE;
1444         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1445         status = smb_raw_open(cli2->tree, tctx, &io);
1446         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1447         fnum2 = io.ntcreatex.out.file.fnum;
1448         torture_wait_for_oplock_break(tctx);
1449         CHECK_VAL(break_info.count, 0);
1450         CHECK_VAL(break_info.failures, 0);
1451         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1452
1453         torture_comment(tctx, "write should trigger a break to none\n");
1454         {
1455                 union smb_write wr;
1456                 wr.write.level = RAW_WRITE_WRITE;
1457                 wr.write.in.file.fnum = fnum;
1458                 wr.write.in.count = 1;
1459                 wr.write.in.offset = 0;
1460                 wr.write.in.remaining = 0;
1461                 wr.write.in.data = (const uint8_t *)"x";
1462                 status = smb_raw_write(cli1->tree, &wr);
1463                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1464         }
1465
1466         torture_wait_for_oplock_break(tctx);
1467
1468         CHECK_VAL(break_info.count, 1);
1469         CHECK_VAL(break_info.fnum, fnum2);
1470         CHECK_VAL(break_info.level, 0);
1471         CHECK_VAL(break_info.failures, 0);
1472
1473         smbcli_close(cli1->tree, fnum);
1474         smbcli_close(cli2->tree, fnum2);
1475
1476 done:
1477         smb_raw_exit(cli1->session);
1478         smb_raw_exit(cli2->session);
1479         smbcli_deltree(cli1->tree, BASEDIR);
1480         return ret;
1481 }
1482
1483 static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1484 {
1485         const char *fname = BASEDIR "\\test_batch11.dat";
1486         NTSTATUS status;
1487         bool ret = true;
1488         union smb_open io;
1489         union smb_setfileinfo sfi;
1490         uint16_t fnum=0;
1491
1492         if (!torture_setup_dir(cli1, BASEDIR)) {
1493                 return false;
1494         }
1495
1496         /* cleanup */
1497         smbcli_unlink(cli1->tree, fname);
1498
1499         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1500
1501         /*
1502           base ntcreatex parms
1503         */
1504         io.generic.level = RAW_OPEN_NTCREATEX;
1505         io.ntcreatex.in.root_fid = 0;
1506         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1507         io.ntcreatex.in.alloc_size = 0;
1508         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1509         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1510         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1511         io.ntcreatex.in.create_options = 0;
1512         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1513         io.ntcreatex.in.security_flags = 0;
1514         io.ntcreatex.in.fname = fname;
1515
1516         /* Test if a set-eof on pathname breaks an exclusive oplock. */
1517         torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
1518
1519         ZERO_STRUCT(break_info);
1520
1521         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1522                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1523                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1524         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1525         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1526                 NTCREATEX_SHARE_ACCESS_WRITE|
1527                 NTCREATEX_SHARE_ACCESS_DELETE;
1528         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1529         status = smb_raw_open(cli1->tree, tctx, &io);
1530         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1531         fnum = 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, BATCH_OPLOCK_RETURN);
1536
1537         ZERO_STRUCT(sfi);
1538         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1539         sfi.generic.in.file.path = fname;
1540         sfi.end_of_file_info.in.size = 100;
1541
1542         status = smb_raw_setpathinfo(cli2->tree, &sfi);
1543         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1544
1545         torture_wait_for_oplock_break(tctx);
1546         CHECK_VAL(break_info.count, 1);
1547         CHECK_VAL(break_info.failures, 0);
1548         CHECK_VAL(break_info.level, 0);
1549
1550         smbcli_close(cli1->tree, fnum);
1551
1552 done:
1553         smb_raw_exit(cli1->session);
1554         smb_raw_exit(cli2->session);
1555         smbcli_deltree(cli1->tree, BASEDIR);
1556         return ret;
1557 }
1558
1559 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1560 {
1561         const char *fname = BASEDIR "\\test_batch12.dat";
1562         NTSTATUS status;
1563         bool ret = true;
1564         union smb_open io;
1565         union smb_setfileinfo sfi;
1566         uint16_t fnum=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 = 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         /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1593         torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
1594
1595         ZERO_STRUCT(break_info);
1596         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1597
1598         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1599                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1600                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1601         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1602         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1603                 NTCREATEX_SHARE_ACCESS_WRITE|
1604                 NTCREATEX_SHARE_ACCESS_DELETE;
1605         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1606         status = smb_raw_open(cli1->tree, tctx, &io);
1607         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1608         fnum = io.ntcreatex.out.file.fnum;
1609         torture_wait_for_oplock_break(tctx);
1610         CHECK_VAL(break_info.count, 0);
1611         CHECK_VAL(break_info.failures, 0);
1612         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1613
1614         ZERO_STRUCT(sfi);
1615         sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
1616         sfi.generic.in.file.path = fname;
1617         sfi.allocation_info.in.alloc_size = 65536 * 8;
1618
1619         status = smb_raw_setpathinfo(cli2->tree, &sfi);
1620         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1621
1622         torture_wait_for_oplock_break(tctx);
1623         CHECK_VAL(break_info.count, 1);
1624         CHECK_VAL(break_info.failures, 0);
1625         CHECK_VAL(break_info.level, 0);
1626
1627         smbcli_close(cli1->tree, fnum);
1628
1629 done:
1630         smb_raw_exit(cli1->session);
1631         smb_raw_exit(cli2->session);
1632         smbcli_deltree(cli1->tree, BASEDIR);
1633         return ret;
1634 }
1635
1636 static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1637 {
1638         const char *fname = BASEDIR "\\test_batch13.dat";
1639         NTSTATUS status;
1640         bool ret = true;
1641         union smb_open io;
1642         uint16_t fnum=0, fnum2=0;
1643
1644         if (!torture_setup_dir(cli1, BASEDIR)) {
1645                 return false;
1646         }
1647
1648         /* cleanup */
1649         smbcli_unlink(cli1->tree, fname);
1650
1651         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1652         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
1653
1654         /*
1655           base ntcreatex parms
1656         */
1657         io.generic.level = RAW_OPEN_NTCREATEX;
1658         io.ntcreatex.in.root_fid = 0;
1659         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1660         io.ntcreatex.in.alloc_size = 0;
1661         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1662         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1663         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1664         io.ntcreatex.in.create_options = 0;
1665         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1666         io.ntcreatex.in.security_flags = 0;
1667         io.ntcreatex.in.fname = fname;
1668
1669         torture_comment(tctx, "BATCH13: open with batch oplock\n");
1670         ZERO_STRUCT(break_info);
1671
1672         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1673                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1674                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1675         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1676                 NTCREATEX_SHARE_ACCESS_WRITE|
1677                 NTCREATEX_SHARE_ACCESS_DELETE;
1678         status = smb_raw_open(cli1->tree, tctx, &io);
1679         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1680         fnum = io.ntcreatex.out.file.fnum;
1681         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1682
1683         ZERO_STRUCT(break_info);
1684
1685         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1686
1687         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1688                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1689                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1690         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1691         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1692                 NTCREATEX_SHARE_ACCESS_WRITE|
1693                 NTCREATEX_SHARE_ACCESS_DELETE;
1694         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1695         status = smb_raw_open(cli2->tree, tctx, &io);
1696         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1697         fnum2 = io.ntcreatex.out.file.fnum;
1698         torture_wait_for_oplock_break(tctx);
1699         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1700         CHECK_VAL(break_info.count, 1);
1701         CHECK_VAL(break_info.failures, 0);
1702
1703         smbcli_close(cli1->tree, fnum);
1704         smbcli_close(cli2->tree, fnum2);
1705
1706 done:
1707         smb_raw_exit(cli1->session);
1708         smb_raw_exit(cli2->session);
1709         smbcli_deltree(cli1->tree, BASEDIR);
1710         return ret;
1711 }
1712
1713 static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1714 {
1715         const char *fname = BASEDIR "\\test_batch14.dat";
1716         NTSTATUS status;
1717         bool ret = true;
1718         union smb_open io;
1719         uint16_t fnum=0, fnum2=0;
1720
1721         if (!torture_setup_dir(cli1, BASEDIR)) {
1722                 return false;
1723         }
1724
1725         /* cleanup */
1726         smbcli_unlink(cli1->tree, fname);
1727
1728         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1729
1730         /*
1731           base ntcreatex parms
1732         */
1733         io.generic.level = RAW_OPEN_NTCREATEX;
1734         io.ntcreatex.in.root_fid = 0;
1735         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1736         io.ntcreatex.in.alloc_size = 0;
1737         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1738         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1739         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1740         io.ntcreatex.in.create_options = 0;
1741         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1742         io.ntcreatex.in.security_flags = 0;
1743         io.ntcreatex.in.fname = fname;
1744
1745         torture_comment(tctx, "BATCH14: open with batch oplock\n");
1746         ZERO_STRUCT(break_info);
1747
1748         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1749                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1750                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1751         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1752                 NTCREATEX_SHARE_ACCESS_WRITE|
1753                 NTCREATEX_SHARE_ACCESS_DELETE;
1754         status = smb_raw_open(cli1->tree, tctx, &io);
1755         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1756         fnum = io.ntcreatex.out.file.fnum;
1757         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1758
1759         ZERO_STRUCT(break_info);
1760
1761         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
1762
1763         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1764                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1765                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1766         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1767         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1768                 NTCREATEX_SHARE_ACCESS_WRITE|
1769                 NTCREATEX_SHARE_ACCESS_DELETE;
1770         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1771         status = smb_raw_open(cli2->tree, tctx, &io);
1772         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1773         fnum2 = io.ntcreatex.out.file.fnum;
1774         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1775
1776         torture_wait_for_oplock_break(tctx);
1777         CHECK_VAL(break_info.count, 1);
1778         CHECK_VAL(break_info.failures, 0);
1779
1780         smbcli_close(cli1->tree, fnum);
1781         smbcli_close(cli2->tree, fnum2);
1782 done:
1783         smb_raw_exit(cli1->session);
1784         smb_raw_exit(cli2->session);
1785         smbcli_deltree(cli1->tree, BASEDIR);
1786         return ret;
1787 }
1788
1789 static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1790 {
1791         const char *fname = BASEDIR "\\test_batch15.dat";
1792         NTSTATUS status;
1793         bool ret = true;
1794         union smb_open io;
1795         union smb_fileinfo qfi;
1796         uint16_t fnum=0;
1797
1798         if (!torture_setup_dir(cli1, BASEDIR)) {
1799                 return false;
1800         }
1801
1802         /* cleanup */
1803         smbcli_unlink(cli1->tree, fname);
1804
1805         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1806
1807         /*
1808           base ntcreatex parms
1809         */
1810         io.generic.level = RAW_OPEN_NTCREATEX;
1811         io.ntcreatex.in.root_fid = 0;
1812         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1813         io.ntcreatex.in.alloc_size = 0;
1814         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1815         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1816         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1817         io.ntcreatex.in.create_options = 0;
1818         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1819         io.ntcreatex.in.security_flags = 0;
1820         io.ntcreatex.in.fname = fname;
1821
1822         /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
1823         torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
1824
1825         ZERO_STRUCT(break_info);
1826
1827         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1828                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1829                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1830         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1831         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1832                 NTCREATEX_SHARE_ACCESS_WRITE|
1833                 NTCREATEX_SHARE_ACCESS_DELETE;
1834         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1835         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1836         status = smb_raw_open(cli1->tree, tctx, &io);
1837         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1838         fnum = io.ntcreatex.out.file.fnum;
1839
1840         torture_wait_for_oplock_break(tctx);
1841         CHECK_VAL(break_info.count, 0);
1842         CHECK_VAL(break_info.failures, 0);
1843         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1844
1845         ZERO_STRUCT(qfi);
1846         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1847         qfi.generic.in.file.path = fname;
1848
1849         status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
1850         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1851
1852         torture_wait_for_oplock_break(tctx);
1853         CHECK_VAL(break_info.count, 0);
1854
1855         smbcli_close(cli1->tree, fnum);
1856
1857 done:
1858         smb_raw_exit(cli1->session);
1859         smb_raw_exit(cli2->session);
1860         smbcli_deltree(cli1->tree, BASEDIR);
1861         return ret;
1862 }
1863
1864 static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1865 {
1866         const char *fname = BASEDIR "\\test_batch16.dat";
1867         NTSTATUS status;
1868         bool ret = true;
1869         union smb_open io;
1870         uint16_t fnum=0, fnum2=0;
1871
1872         if (!torture_setup_dir(cli1, BASEDIR)) {
1873                 return false;
1874         }
1875
1876         /* cleanup */
1877         smbcli_unlink(cli1->tree, fname);
1878
1879         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1880         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
1881
1882         /*
1883           base ntcreatex parms
1884         */
1885         io.generic.level = RAW_OPEN_NTCREATEX;
1886         io.ntcreatex.in.root_fid = 0;
1887         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1888         io.ntcreatex.in.alloc_size = 0;
1889         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1890         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1891         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1892         io.ntcreatex.in.create_options = 0;
1893         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1894         io.ntcreatex.in.security_flags = 0;
1895         io.ntcreatex.in.fname = fname;
1896
1897         torture_comment(tctx, "BATCH16: open with batch oplock\n");
1898         ZERO_STRUCT(break_info);
1899
1900         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1901                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1902                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1903         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1904                 NTCREATEX_SHARE_ACCESS_WRITE|
1905                 NTCREATEX_SHARE_ACCESS_DELETE;
1906         status = smb_raw_open(cli1->tree, tctx, &io);
1907         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1908         fnum = io.ntcreatex.out.file.fnum;
1909         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1910
1911         ZERO_STRUCT(break_info);
1912
1913         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
1914
1915         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1916                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1917                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1918         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1919         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1920                 NTCREATEX_SHARE_ACCESS_WRITE|
1921                 NTCREATEX_SHARE_ACCESS_DELETE;
1922         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1923         status = smb_raw_open(cli2->tree, tctx, &io);
1924         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1925         fnum2 = io.ntcreatex.out.file.fnum;
1926         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1927
1928         torture_wait_for_oplock_break(tctx);
1929         CHECK_VAL(break_info.count, 1);
1930         CHECK_VAL(break_info.failures, 0);
1931
1932         smbcli_close(cli1->tree, fnum);
1933         smbcli_close(cli2->tree, fnum2);
1934
1935 done:
1936         smb_raw_exit(cli1->session);
1937         smb_raw_exit(cli2->session);
1938         smbcli_deltree(cli1->tree, BASEDIR);
1939         return ret;
1940 }
1941
1942 static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1943 {
1944         const char *fname1 = BASEDIR "\\test_batch17_1.dat";
1945         const char *fname2 = BASEDIR "\\test_batch17_2.dat";
1946         NTSTATUS status;
1947         bool ret = true;
1948         union smb_open io;
1949         union smb_rename rn;
1950         uint16_t fnum=0;
1951
1952         if (!torture_setup_dir(cli1, BASEDIR)) {
1953                 return false;
1954         }
1955
1956         /* cleanup */
1957         smbcli_unlink(cli1->tree, fname1);
1958         smbcli_unlink(cli1->tree, fname2);
1959
1960         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1961
1962         /*
1963           base ntcreatex parms
1964         */
1965         io.generic.level = RAW_OPEN_NTCREATEX;
1966         io.ntcreatex.in.root_fid = 0;
1967         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1968         io.ntcreatex.in.alloc_size = 0;
1969         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1970         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1971         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1972         io.ntcreatex.in.create_options = 0;
1973         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1974         io.ntcreatex.in.security_flags = 0;
1975         io.ntcreatex.in.fname = fname1;
1976
1977         torture_comment(tctx, "BATCH17: open a file with an batch oplock (share mode: none)\n");
1978
1979         ZERO_STRUCT(break_info);
1980         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1981                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1982                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1983
1984         status = smb_raw_open(cli1->tree, tctx, &io);
1985         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1986         fnum = io.ntcreatex.out.file.fnum;
1987         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1988
1989         torture_comment(tctx, "rename should trigger a break\n");
1990         ZERO_STRUCT(rn);
1991         rn.generic.level = RAW_RENAME_RENAME;
1992         rn.rename.in.pattern1 = fname1;
1993         rn.rename.in.pattern2 = fname2;
1994         rn.rename.in.attrib = 0;
1995
1996         torture_comment(tctx, "trying rename while first file open\n");
1997         status = smb_raw_rename(cli2->tree, &rn);
1998         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1999
2000         torture_wait_for_oplock_break(tctx);
2001         CHECK_VAL(break_info.count, 1);
2002         CHECK_VAL(break_info.failures, 0);
2003         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2004
2005         smbcli_close(cli1->tree, fnum);
2006
2007 done:
2008         smb_raw_exit(cli1->session);
2009         smb_raw_exit(cli2->session);
2010         smbcli_deltree(cli1->tree, BASEDIR);
2011         return ret;
2012 }
2013
2014 static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2015 {
2016         const char *fname1 = BASEDIR "\\test_batch18_1.dat";
2017         const char *fname2 = BASEDIR "\\test_batch18_2.dat";
2018         NTSTATUS status;
2019         bool ret = true;
2020         union smb_open io;
2021         union smb_rename rn;
2022         uint16_t fnum=0;
2023
2024         if (!torture_setup_dir(cli1, BASEDIR)) {
2025                 return false;
2026         }
2027
2028         /* cleanup */
2029         smbcli_unlink(cli1->tree, fname1);
2030         smbcli_unlink(cli1->tree, fname2);
2031
2032         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2033
2034         /*
2035           base ntcreatex parms
2036         */
2037         io.generic.level = RAW_OPEN_NTCREATEX;
2038         io.ntcreatex.in.root_fid = 0;
2039         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2040         io.ntcreatex.in.alloc_size = 0;
2041         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2042         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2043         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2044         io.ntcreatex.in.create_options = 0;
2045         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2046         io.ntcreatex.in.security_flags = 0;
2047         io.ntcreatex.in.fname = fname1;
2048
2049         torture_comment(tctx, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2050
2051         ZERO_STRUCT(break_info);
2052         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2053                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2054                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2055
2056         status = smb_raw_open(cli1->tree, tctx, &io);
2057         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2058         fnum = io.ntcreatex.out.file.fnum;
2059         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2060
2061         torture_comment(tctx, "ntrename should trigger a break\n");
2062         ZERO_STRUCT(rn);
2063         rn.generic.level = RAW_RENAME_NTRENAME;
2064         rn.ntrename.in.attrib   = 0;
2065         rn.ntrename.in.flags    = RENAME_FLAG_RENAME;
2066         rn.ntrename.in.old_name = fname1;
2067         rn.ntrename.in.new_name = fname2;
2068         torture_comment(tctx, "trying rename while first file open\n");
2069         status = smb_raw_rename(cli2->tree, &rn);
2070         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2071
2072         torture_wait_for_oplock_break(tctx);
2073         CHECK_VAL(break_info.count, 1);
2074         CHECK_VAL(break_info.failures, 0);
2075         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2076
2077         smbcli_close(cli1->tree, fnum);
2078
2079 done:
2080         smb_raw_exit(cli1->session);
2081         smb_raw_exit(cli2->session);
2082         smbcli_deltree(cli1->tree, BASEDIR);
2083         return ret;
2084 }
2085
2086 static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2087 {
2088         const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2089         const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2090         const char *fname3 = BASEDIR "\\test_batch19_3.dat";
2091         NTSTATUS status;
2092         bool ret = true;
2093         union smb_open io;
2094         union smb_fileinfo qfi;
2095         union smb_setfileinfo sfi;
2096         uint16_t fnum=0;
2097
2098         if (!torture_setup_dir(cli1, BASEDIR)) {
2099                 return false;
2100         }
2101
2102         /* cleanup */
2103         smbcli_unlink(cli1->tree, fname1);
2104         smbcli_unlink(cli1->tree, fname2);
2105         smbcli_unlink(cli1->tree, fname3);
2106
2107         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2108
2109         /*
2110           base ntcreatex parms
2111         */
2112         io.generic.level = RAW_OPEN_NTCREATEX;
2113         io.ntcreatex.in.root_fid = 0;
2114         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2115         io.ntcreatex.in.alloc_size = 0;
2116         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2117         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2118         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2119         io.ntcreatex.in.create_options = 0;
2120         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2121         io.ntcreatex.in.security_flags = 0;
2122         io.ntcreatex.in.fname = fname1;
2123
2124         torture_comment(tctx, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2125         ZERO_STRUCT(break_info);
2126         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2127                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2128                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2129         status = smb_raw_open(cli1->tree, tctx, &io);
2130         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2131         fnum = io.ntcreatex.out.file.fnum;
2132         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2133
2134         torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2135         ZERO_STRUCT(sfi);
2136         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2137         sfi.generic.in.file.path = fname1;
2138         sfi.rename_information.in.overwrite     = 0;
2139         sfi.rename_information.in.root_fid      = 0;
2140         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2141
2142         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2143         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2144
2145         torture_wait_for_oplock_break(tctx);
2146         CHECK_VAL(break_info.count, 0);
2147
2148         ZERO_STRUCT(qfi);
2149         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2150         qfi.generic.in.file.fnum = fnum;
2151
2152         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2153         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2154         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2155
2156         torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2157         ZERO_STRUCT(sfi);
2158         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2159         sfi.generic.in.file.fnum = fnum;
2160         sfi.rename_information.in.overwrite     = 0;
2161         sfi.rename_information.in.root_fid      = 0;
2162         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2163
2164         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2165         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2166
2167         torture_wait_for_oplock_break(tctx);
2168         CHECK_VAL(break_info.count, 0);
2169
2170         ZERO_STRUCT(qfi);
2171         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2172         qfi.generic.in.file.fnum = fnum;
2173
2174         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2175         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2176         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2177
2178         smbcli_close(cli1->tree, fnum);
2179
2180 done:
2181         smb_raw_exit(cli1->session);
2182         smb_raw_exit(cli2->session);
2183         smbcli_deltree(cli1->tree, BASEDIR);
2184         return ret;
2185 }
2186
2187 /****************************************************
2188  Called from raw-rename - we need oplock handling for
2189  this test so this is why it's in oplock.c, not rename.c
2190 ****************************************************/
2191
2192 bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2193 {
2194         const char *fname1 = BASEDIR "\\test_trans2rename_1.dat";
2195         const char *fname2 = BASEDIR "\\test_trans2rename_2.dat";
2196         const char *fname3 = BASEDIR "\\test_trans2rename_3.dat";
2197         NTSTATUS status;
2198         bool ret = true;
2199         union smb_open io;
2200         union smb_fileinfo qfi;
2201         union smb_setfileinfo sfi;
2202         uint16_t fnum=0;
2203
2204         if (!torture_setup_dir(cli1, BASEDIR)) {
2205                 return false;
2206         }
2207
2208         /* cleanup */
2209         smbcli_unlink(cli1->tree, fname1);
2210         smbcli_unlink(cli1->tree, fname2);
2211         smbcli_unlink(cli1->tree, fname3);
2212
2213         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2214
2215         /*
2216           base ntcreatex parms
2217         */
2218         io.generic.level = RAW_OPEN_NTCREATEX;
2219         io.ntcreatex.in.root_fid = 0;
2220         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2221         io.ntcreatex.in.alloc_size = 0;
2222         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2223         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2224         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2225         io.ntcreatex.in.create_options = 0;
2226         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2227         io.ntcreatex.in.security_flags = 0;
2228         io.ntcreatex.in.fname = fname1;
2229
2230         torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n");
2231         ZERO_STRUCT(break_info);
2232         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2233                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2234         status = smb_raw_open(cli1->tree, tctx, &io);
2235         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2236         fnum = io.ntcreatex.out.file.fnum;
2237         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2238
2239         torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2240         ZERO_STRUCT(sfi);
2241         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2242         sfi.generic.in.file.path = fname1;
2243         sfi.rename_information.in.overwrite     = 0;
2244         sfi.rename_information.in.root_fid      = 0;
2245         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2246
2247         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2248
2249         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2250
2251         torture_wait_for_oplock_break(tctx);
2252         CHECK_VAL(break_info.count, 0);
2253
2254         ZERO_STRUCT(qfi);
2255         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2256         qfi.generic.in.file.fnum = fnum;
2257
2258         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2259         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2260         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2261
2262         torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2263         ZERO_STRUCT(sfi);
2264         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2265         sfi.generic.in.file.fnum = fnum;
2266         sfi.rename_information.in.overwrite     = 0;
2267         sfi.rename_information.in.root_fid      = 0;
2268         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2269
2270         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2271         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2272
2273         torture_wait_for_oplock_break(tctx);
2274         CHECK_VAL(break_info.count, 0);
2275
2276         ZERO_STRUCT(qfi);
2277         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2278         qfi.generic.in.file.fnum = fnum;
2279
2280         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2281         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2282         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2283
2284         smbcli_close(cli1->tree, fnum);
2285
2286 done:
2287         smb_raw_exit(cli1->session);
2288         smb_raw_exit(cli2->session);
2289         smbcli_deltree(cli1->tree, BASEDIR);
2290         return ret;
2291 }
2292
2293 /****************************************************
2294  Called from raw-rename - we need oplock handling for
2295  this test so this is why it's in oplock.c, not rename.c
2296 ****************************************************/
2297
2298 bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1)
2299 {
2300         const char *fname1 = BASEDIR "\\test_nttransrename_1.dat";
2301         const char *fname2 = BASEDIR "\\test_nttransrename_2.dat";
2302         NTSTATUS status;
2303         bool ret = true;
2304         union smb_open io;
2305         union smb_fileinfo qfi, qpi;
2306         union smb_rename rn;
2307         uint16_t fnum=0;
2308
2309         if (!torture_setup_dir(cli1, BASEDIR)) {
2310                 return false;
2311         }
2312
2313         /* cleanup */
2314         smbcli_unlink(cli1->tree, fname1);
2315         smbcli_unlink(cli1->tree, fname2);
2316
2317         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2318
2319         /*
2320           base ntcreatex parms
2321         */
2322         io.generic.level = RAW_OPEN_NTCREATEX;
2323         io.ntcreatex.in.root_fid = 0;
2324         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2325         io.ntcreatex.in.alloc_size = 0;
2326         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2327         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2328         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2329         io.ntcreatex.in.create_options = 0;
2330         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2331         io.ntcreatex.in.security_flags = 0;
2332         io.ntcreatex.in.fname = fname1;
2333
2334         torture_comment(tctx, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2335         ZERO_STRUCT(break_info);
2336         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2337                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2338         status = smb_raw_open(cli1->tree, tctx, &io);
2339         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2340         fnum = io.ntcreatex.out.file.fnum;
2341         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2342
2343         torture_comment(tctx, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2344         ZERO_STRUCT(rn);
2345         rn.generic.level = RAW_RENAME_NTTRANS;
2346         rn.nttrans.in.file.fnum = fnum;
2347         rn.nttrans.in.flags     = 0;
2348         rn.nttrans.in.new_name  = fname2+strlen(BASEDIR)+1;
2349
2350         status = smb_raw_rename(cli1->tree, &rn);
2351         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2352
2353         torture_wait_for_oplock_break(tctx);
2354         CHECK_VAL(break_info.count, 0);
2355
2356         /* w2k3 does nothing, it doesn't rename the file */
2357         torture_comment(tctx, "nttrans_rename: the server should have done nothing\n");
2358         ZERO_STRUCT(qfi);
2359         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2360         qfi.generic.in.file.fnum = fnum;
2361
2362         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2363         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2364         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname1);
2365
2366         ZERO_STRUCT(qpi);
2367         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2368         qpi.generic.in.file.path = fname1;
2369
2370         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2371         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2372         CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2373
2374         ZERO_STRUCT(qpi);
2375         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2376         qpi.generic.in.file.path = fname2;
2377
2378         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2379         CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2380
2381         torture_comment(tctx, "nttrans_rename: after closing the file the file is still not renamed\n");
2382         status = smbcli_close(cli1->tree, fnum);
2383         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2384
2385         ZERO_STRUCT(qpi);
2386         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2387         qpi.generic.in.file.path = fname1;
2388
2389         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2390         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2391         CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2392
2393         ZERO_STRUCT(qpi);
2394         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2395         qpi.generic.in.file.path = fname2;
2396
2397         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2398         CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2399
2400         torture_comment(tctx, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
2401         ZERO_STRUCT(rn);
2402         rn.generic.level = RAW_RENAME_NTTRANS;
2403         rn.nttrans.in.file.fnum = fnum+1;
2404         rn.nttrans.in.flags     = 0;
2405         rn.nttrans.in.new_name  = fname2+strlen(BASEDIR)+1;
2406
2407         status = smb_raw_rename(cli1->tree, &rn);
2408
2409         CHECK_STATUS(tctx, status, NT_STATUS_INVALID_HANDLE);
2410
2411 done:
2412         smb_raw_exit(cli1->session);
2413         smbcli_deltree(cli1->tree, BASEDIR);
2414         return ret;
2415 }
2416
2417
2418 static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2419 {
2420         const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2421         const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2422         const char *fname3 = BASEDIR "\\test_batch20_3.dat";
2423         NTSTATUS status;
2424         bool ret = true;
2425         union smb_open io;
2426         union smb_fileinfo qfi;
2427         union smb_setfileinfo sfi;
2428         uint16_t fnum=0,fnum2=0;
2429
2430         if (!torture_setup_dir(cli1, BASEDIR)) {
2431                 return false;
2432         }
2433
2434         /* cleanup */
2435         smbcli_unlink(cli1->tree, fname1);
2436         smbcli_unlink(cli1->tree, fname2);
2437         smbcli_unlink(cli1->tree, fname3);
2438
2439         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2440
2441         /*
2442           base ntcreatex parms
2443         */
2444         io.generic.level = RAW_OPEN_NTCREATEX;
2445         io.ntcreatex.in.root_fid = 0;
2446         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2447         io.ntcreatex.in.alloc_size = 0;
2448         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2449         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2450         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2451         io.ntcreatex.in.create_options = 0;
2452         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2453         io.ntcreatex.in.security_flags = 0;
2454         io.ntcreatex.in.fname = fname1;
2455
2456         torture_comment(tctx, "BATCH20: open a file with an batch oplock (share mode: all)\n");
2457         ZERO_STRUCT(break_info);
2458         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2459                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2460                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2461         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2462                 NTCREATEX_SHARE_ACCESS_WRITE|
2463                 NTCREATEX_SHARE_ACCESS_DELETE;
2464         status = smb_raw_open(cli1->tree, tctx, &io);
2465         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2466         fnum = io.ntcreatex.out.file.fnum;
2467         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2468
2469         torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2470         ZERO_STRUCT(sfi);
2471         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2472         sfi.generic.in.file.path = fname1;
2473         sfi.rename_information.in.overwrite     = 0;
2474         sfi.rename_information.in.root_fid      = 0;
2475         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2476
2477         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2478         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2479
2480         torture_wait_for_oplock_break(tctx);
2481         CHECK_VAL(break_info.count, 0);
2482
2483         ZERO_STRUCT(qfi);
2484         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2485         qfi.generic.in.file.fnum = fnum;
2486
2487         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2488         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2489         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2490
2491         torture_comment(tctx, "open a file with the new name an batch oplock (share mode: all)\n");
2492         ZERO_STRUCT(break_info);
2493         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2494                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2495                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2496         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2497                 NTCREATEX_SHARE_ACCESS_WRITE|
2498                 NTCREATEX_SHARE_ACCESS_DELETE;
2499         io.ntcreatex.in.fname = fname2;
2500         status = smb_raw_open(cli2->tree, tctx, &io);
2501         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2502         fnum2 = io.ntcreatex.out.file.fnum;
2503         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2504
2505         torture_wait_for_oplock_break(tctx);
2506         CHECK_VAL(break_info.count, 1);
2507         CHECK_VAL(break_info.failures, 0);
2508         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2509
2510         torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2511         ZERO_STRUCT(sfi);
2512         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2513         sfi.generic.in.file.fnum = fnum;
2514         sfi.rename_information.in.overwrite     = 0;
2515         sfi.rename_information.in.root_fid      = 0;
2516         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2517
2518         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2519         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2520
2521         torture_wait_for_oplock_break(tctx);
2522         CHECK_VAL(break_info.count, 1);
2523         CHECK_VAL(break_info.failures, 0);
2524         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2525
2526         ZERO_STRUCT(qfi);
2527         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2528         qfi.generic.in.file.fnum = fnum;
2529
2530         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2531         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2532         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2533
2534         ZERO_STRUCT(qfi);
2535         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2536         qfi.generic.in.file.fnum = fnum2;
2537
2538         status = smb_raw_fileinfo(cli2->tree, tctx, &qfi);
2539         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2540         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2541
2542         smbcli_close(cli1->tree, fnum);
2543
2544 done:
2545         smb_raw_exit(cli1->session);
2546         smb_raw_exit(cli2->session);
2547         smbcli_deltree(cli1->tree, BASEDIR);
2548         return ret;
2549 }
2550
2551 static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2552 {
2553         const char *fname = BASEDIR "\\test_batch21.dat";
2554         NTSTATUS status;
2555         bool ret = true;
2556         union smb_open io;
2557         struct smb_echo e;
2558         uint16_t fnum=0;
2559         char c = 0;
2560         ssize_t wr;
2561
2562         if (!torture_setup_dir(cli1, BASEDIR)) {
2563                 return false;
2564         }
2565
2566         /* cleanup */
2567         smbcli_unlink(cli1->tree, fname);
2568
2569         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2570
2571         /*
2572           base ntcreatex parms
2573         */
2574         io.generic.level = RAW_OPEN_NTCREATEX;
2575         io.ntcreatex.in.root_fid = 0;
2576         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2577         io.ntcreatex.in.alloc_size = 0;
2578         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2579         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2580         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2581         io.ntcreatex.in.create_options = 0;
2582         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2583         io.ntcreatex.in.security_flags = 0;
2584         io.ntcreatex.in.fname = fname;
2585
2586         /*
2587           with a batch oplock we get a break
2588         */
2589         torture_comment(tctx, "BATCH21: open with batch oplock\n");
2590         ZERO_STRUCT(break_info);
2591         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2592                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2593                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2594         status = smb_raw_open(cli1->tree, tctx, &io);
2595         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2596         fnum = io.ntcreatex.out.file.fnum;
2597         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2598
2599         torture_comment(tctx, "writing should not generate a break\n");
2600         wr = smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
2601         CHECK_VAL(wr, 1);
2602         CHECK_STATUS(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_OK);
2603
2604         ZERO_STRUCT(e);
2605         e.in.repeat_count = 1;
2606         status = smb_raw_echo(cli1->transport, &e);
2607         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2608
2609         torture_wait_for_oplock_break(tctx);
2610         CHECK_VAL(break_info.count, 0);
2611
2612         smbcli_close(cli1->tree, fnum);
2613
2614 done:
2615         smb_raw_exit(cli1->session);
2616         smb_raw_exit(cli2->session);
2617         smbcli_deltree(cli1->tree, BASEDIR);
2618         return ret;
2619 }
2620
2621 static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2622 {
2623         const char *fname = BASEDIR "\\test_batch22.dat";
2624         NTSTATUS status;
2625         bool ret = true;
2626         union smb_open io;
2627         uint16_t fnum=0, fnum2=0;
2628         struct timeval tv;
2629         int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2630         int te;
2631
2632         if (torture_setting_bool(tctx, "samba3", false)) {
2633                 torture_skip(tctx, "BATCH22 disabled against samba3\n");
2634         }
2635
2636         if (!torture_setup_dir(cli1, BASEDIR)) {
2637                 return false;
2638         }
2639
2640         /* cleanup */
2641         smbcli_unlink(cli1->tree, fname);
2642
2643         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2644
2645         /*
2646           base ntcreatex parms
2647         */
2648         io.generic.level = RAW_OPEN_NTCREATEX;
2649         io.ntcreatex.in.root_fid = 0;
2650         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2651         io.ntcreatex.in.alloc_size = 0;
2652         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2653         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2654         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2655         io.ntcreatex.in.create_options = 0;
2656         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2657         io.ntcreatex.in.security_flags = 0;
2658         io.ntcreatex.in.fname = fname;
2659
2660         /*
2661           with a batch oplock we get a break
2662         */
2663         torture_comment(tctx, "BATCH22: open with batch oplock\n");
2664         ZERO_STRUCT(break_info);
2665         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2666                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2667                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2668         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2669                 NTCREATEX_SHARE_ACCESS_WRITE|
2670                 NTCREATEX_SHARE_ACCESS_DELETE;
2671         status = smb_raw_open(cli1->tree, tctx, &io);
2672         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2673         fnum = io.ntcreatex.out.file.fnum;
2674         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2675
2676         torture_comment(tctx, "a 2nd open should not succeed after the oplock "
2677                         "break timeout\n");
2678         tv = timeval_current();
2679         smbcli_oplock_handler(cli1->transport, oplock_handler_timeout, cli1->tree);
2680         status = smb_raw_open(cli1->tree, tctx, &io);
2681         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2682         torture_wait_for_oplock_break(tctx);
2683         te = (int)timeval_elapsed(&tv);
2684         CHECK_RANGE(te, timeout - 1, timeout + 15);
2685
2686         CHECK_VAL(break_info.count, 1);
2687         CHECK_VAL(break_info.fnum, fnum);
2688         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2689         CHECK_VAL(break_info.failures, 0);
2690         ZERO_STRUCT(break_info);
2691
2692         torture_comment(tctx, "a 2nd open should succeed after the oplock "
2693                         "release without break\n");
2694         tv = timeval_current();
2695         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2696         status = smb_raw_open(cli1->tree, tctx, &io);
2697         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2698         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2699         torture_wait_for_oplock_break(tctx);
2700         te = (int)timeval_elapsed(&tv);
2701         /* it should come in without delay */
2702         CHECK_RANGE(te+1, 0, timeout);
2703         fnum2 = io.ntcreatex.out.file.fnum;
2704
2705         CHECK_VAL(break_info.count, 0);
2706
2707         smbcli_close(cli1->tree, fnum);
2708         smbcli_close(cli1->tree, fnum2);
2709
2710 done:
2711         smb_raw_exit(cli1->session);
2712         smb_raw_exit(cli2->session);
2713         smbcli_deltree(cli1->tree, BASEDIR);
2714         return ret;
2715 }
2716
2717 static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2718 {
2719         const char *fname = BASEDIR "\\test_batch23.dat";
2720         NTSTATUS status;
2721         bool ret = true;
2722         union smb_open io;
2723         uint16_t fnum=0, fnum2=0,fnum3=0;
2724         struct smbcli_state *cli3 = NULL;
2725
2726         if (!torture_setup_dir(cli1, BASEDIR)) {
2727                 return false;
2728         }
2729
2730         /* cleanup */
2731         smbcli_unlink(cli1->tree, fname);
2732
2733         ret = open_connection_no_level2_oplocks(tctx, &cli3);
2734         CHECK_VAL(ret, true);
2735
2736         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2737         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2738         smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
2739
2740         /*
2741           base ntcreatex parms
2742         */
2743         io.generic.level = RAW_OPEN_NTCREATEX;
2744         io.ntcreatex.in.root_fid = 0;
2745         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2746         io.ntcreatex.in.alloc_size = 0;
2747         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2748         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2749         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2750         io.ntcreatex.in.create_options = 0;
2751         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2752         io.ntcreatex.in.security_flags = 0;
2753         io.ntcreatex.in.fname = fname;
2754
2755         torture_comment(tctx, "BATCH23: a open and ask for a batch oplock\n");
2756         ZERO_STRUCT(break_info);
2757
2758         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
2759         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2760         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2761                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2762                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2763         status = smb_raw_open(cli1->tree, tctx, &io);
2764         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2765         fnum = io.ntcreatex.out.file.fnum;
2766         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2767
2768         ZERO_STRUCT(break_info);
2769
2770         torture_comment(tctx, "a 2nd open without level2 oplock support should generate a break to level2\n");
2771         status = smb_raw_open(cli3->tree, tctx, &io);
2772         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2773         fnum3 = io.ntcreatex.out.file.fnum;
2774         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
2775
2776         torture_wait_for_oplock_break(tctx);
2777         CHECK_VAL(break_info.count, 1);
2778         CHECK_VAL(break_info.fnum, fnum);
2779         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2780         CHECK_VAL(break_info.failures, 0);
2781
2782         ZERO_STRUCT(break_info);
2783
2784         torture_comment(tctx, "a 3rd open with level2 oplock support should not generate a break\n");
2785         status = smb_raw_open(cli2->tree, tctx, &io);
2786         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2787         fnum2 = io.ntcreatex.out.file.fnum;
2788         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2789
2790         torture_wait_for_oplock_break(tctx);
2791         CHECK_VAL(break_info.count, 0);
2792
2793         smbcli_close(cli1->tree, fnum);
2794         smbcli_close(cli2->tree, fnum2);
2795         smbcli_close(cli3->tree, fnum3);
2796
2797 done:
2798         smb_raw_exit(cli1->session);
2799         smb_raw_exit(cli2->session);
2800         smb_raw_exit(cli3->session);
2801         smbcli_deltree(cli1->tree, BASEDIR);
2802         return ret;
2803 }
2804
2805 static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2806 {
2807         const char *fname = BASEDIR "\\test_batch24.dat";
2808         NTSTATUS status;
2809         bool ret = true;
2810         union smb_open io;
2811         uint16_t fnum2=0,fnum3=0;
2812         struct smbcli_state *cli3 = NULL;
2813
2814         if (!torture_setup_dir(cli1, BASEDIR)) {
2815                 return false;
2816         }
2817
2818         /* cleanup */
2819         smbcli_unlink(cli1->tree, fname);
2820
2821         ret = open_connection_no_level2_oplocks(tctx, &cli3);
2822         CHECK_VAL(ret, true);
2823
2824         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2825         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2826         smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
2827
2828         /*
2829           base ntcreatex parms
2830         */
2831         io.generic.level = RAW_OPEN_NTCREATEX;
2832         io.ntcreatex.in.root_fid = 0;
2833         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2834         io.ntcreatex.in.alloc_size = 0;
2835         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2836         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2837         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2838         io.ntcreatex.in.create_options = 0;
2839         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2840         io.ntcreatex.in.security_flags = 0;
2841         io.ntcreatex.in.fname = fname;
2842
2843         torture_comment(tctx, "BATCH24: a open without level support and ask for a batch oplock\n");
2844         ZERO_STRUCT(break_info);
2845
2846         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
2847         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2848         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2849                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2850                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2851         status = smb_raw_open(cli3->tree, tctx, &io);
2852         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2853         fnum3 = io.ntcreatex.out.file.fnum;
2854         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2855
2856         ZERO_STRUCT(break_info);
2857
2858         torture_comment(tctx, "a 2nd open with level2 oplock support should generate a break to none\n");
2859         status = smb_raw_open(cli2->tree, tctx, &io);
2860         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2861         fnum2 = io.ntcreatex.out.file.fnum;
2862         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2863
2864         torture_wait_for_oplock_break(tctx);
2865         CHECK_VAL(break_info.count, 1);
2866         CHECK_VAL(break_info.fnum, fnum3);
2867         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2868         CHECK_VAL(break_info.failures, 0);
2869
2870         smbcli_close(cli3->tree, fnum3);
2871         smbcli_close(cli2->tree, fnum2);
2872
2873 done:
2874         smb_raw_exit(cli1->session);
2875         smb_raw_exit(cli2->session);
2876         smb_raw_exit(cli3->session);
2877         smbcli_deltree(cli1->tree, BASEDIR);
2878         return ret;
2879 }
2880
2881 static bool test_raw_oplock_batch25(struct torture_context *tctx,
2882                                     struct smbcli_state *cli1,
2883                                     struct smbcli_state *cli2)
2884 {
2885         const char *fname = BASEDIR "\\test_batch25.dat";
2886         NTSTATUS status;
2887         bool ret = true;
2888         union smb_open io;
2889         union smb_setfileinfo sfi;
2890         uint16_t fnum=0;
2891
2892         if (!torture_setup_dir(cli1, BASEDIR)) {
2893                 return false;
2894         }
2895
2896         /* cleanup */
2897         smbcli_unlink(cli1->tree, fname);
2898
2899         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2900
2901         /*
2902           base ntcreatex parms
2903         */
2904         io.generic.level = RAW_OPEN_NTCREATEX;
2905         io.ntcreatex.in.root_fid = 0;
2906         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2907         io.ntcreatex.in.alloc_size = 0;
2908         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2909         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2910         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2911         io.ntcreatex.in.create_options = 0;
2912         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2913         io.ntcreatex.in.security_flags = 0;
2914         io.ntcreatex.in.fname = fname;
2915
2916         torture_comment(tctx, "BATCH25: open a file with an batch oplock "
2917                         "(share mode: none)\n");
2918
2919         ZERO_STRUCT(break_info);
2920         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2921                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2922                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2923         status = smb_raw_open(cli1->tree, tctx, &io);
2924         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2925         fnum = io.ntcreatex.out.file.fnum;
2926         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2927
2928         torture_comment(tctx, "setpathinfo attribute info should not trigger "
2929                         "a break nor a violation\n");
2930         ZERO_STRUCT(sfi);
2931         sfi.generic.level = RAW_SFILEINFO_SETATTR;
2932         sfi.generic.in.file.path        = fname;
2933         sfi.setattr.in.attrib           = FILE_ATTRIBUTE_HIDDEN;
2934         sfi.setattr.in.write_time       = 0;
2935
2936         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2937         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2938
2939         torture_wait_for_oplock_break(tctx);
2940         CHECK_VAL(break_info.count, 0);
2941
2942         smbcli_close(cli1->tree, fnum);
2943
2944 done:
2945         smb_raw_exit(cli1->session);
2946         smb_raw_exit(cli2->session);
2947         smbcli_deltree(cli1->tree, BASEDIR);
2948         return ret;
2949 }
2950
2951 /* Test how oplocks work on streams. */
2952 static bool test_raw_oplock_stream1(struct torture_context *tctx,
2953                                     struct smbcli_state *cli1,
2954                                     struct smbcli_state *cli2)
2955 {
2956         NTSTATUS status;
2957         union smb_open io;
2958         const char *fname_base = BASEDIR "\\test_stream1.txt";
2959         const char *stream = "Stream One:$DATA";
2960         const char *fname_stream, *fname_default_stream;
2961         const char *default_stream = "::$DATA";
2962         bool ret = true;
2963         int fnum = -1;
2964         int i;
2965         int stream_fnum = -1;
2966         uint32_t batch_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
2967             NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK | NTCREATEX_FLAGS_EXTENDED;
2968         uint32_t exclusive_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
2969             NTCREATEX_FLAGS_EXTENDED;
2970         /* Try some permutations of taking oplocks on streams. */
2971 #define NSTREAM_OPLOCK_RESULTS 8
2972         struct {
2973                 const char *fname;
2974                 bool open_base_file;
2975                 uint32_t oplock_req;
2976                 uint32_t oplock_granted;
2977         } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
2978                 /* Request oplock on stream without the base file open. */
2979                 {fname_stream, false, batch_req, NO_OPLOCK_RETURN},
2980                 {fname_default_stream, false, batch_req, NO_OPLOCK_RETURN},
2981                 {fname_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
2982                 {fname_default_stream, false,  exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
2983
2984                 /* Request oplock on stream with the base file open. */
2985                 {fname_stream, true, batch_req, NO_OPLOCK_RETURN},
2986                 {fname_default_stream, true, batch_req, NO_OPLOCK_RETURN},
2987                 {fname_stream, true, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
2988                 {fname_default_stream, true,  exclusive_req, LEVEL_II_OPLOCK_RETURN},
2989
2990         };
2991
2992
2993         /* Only passes against windows at the moment. */
2994         if (torture_setting_bool(tctx, "samba3", false) ||
2995             torture_setting_bool(tctx, "samba4", false)) {
2996                 torture_skip(tctx, "STREAM1 disabled against samba3+4\n");
2997         }
2998
2999         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
3000         fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
3001                                                default_stream);
3002
3003         if (!torture_setup_dir(cli1, BASEDIR)) {
3004                 return false;
3005         }
3006         smbcli_unlink(cli1->tree, fname_base);
3007
3008         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3009         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3010
3011         /* Setup generic open parameters. */
3012         io.generic.level = RAW_OPEN_NTCREATEX;
3013         io.ntcreatex.in.root_fid = 0;
3014         io.ntcreatex.in.access_mask = (SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|
3015             SEC_FILE_APPEND_DATA|SEC_STD_READ_CONTROL);
3016         io.ntcreatex.in.create_options = 0;
3017         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3018         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3019             NTCREATEX_SHARE_ACCESS_WRITE;
3020         io.ntcreatex.in.alloc_size = 0;
3021         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3022         io.ntcreatex.in.security_flags = 0;
3023
3024         /* Create the file with a stream */
3025         io.ntcreatex.in.fname = fname_stream;
3026         io.ntcreatex.in.flags = 0;
3027         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
3028         status = smb_raw_open(cli1->tree, tctx, &io);
3029         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3030         smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3031
3032         /* Change the disposition to open now that the file has been created. */
3033         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
3034
3035         for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
3036                 const char *fname = stream_oplock_results[i].fname;
3037                 bool open_base_file = stream_oplock_results[i].open_base_file;
3038                 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
3039                 uint32_t oplock_granted =
3040                     stream_oplock_results[i].oplock_granted;
3041                 int base_fnum = -1;
3042
3043                 if (open_base_file) {
3044                         torture_comment(tctx, "Opening base file: %s with "
3045                             "%d\n", fname_base, oplock_req);
3046                         io.ntcreatex.in.fname = fname_base;
3047                         io.ntcreatex.in.flags = batch_req;
3048                         status = smb_raw_open(cli2->tree, tctx, &io);
3049                         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3050                         CHECK_VAL(io.ntcreatex.out.oplock_level,
3051                             BATCH_OPLOCK_RETURN);
3052                         base_fnum = io.ntcreatex.out.file.fnum;
3053                 }
3054
3055                 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
3056                     fname, oplock_req);
3057                 io.ntcreatex.in.fname = fname;
3058                 io.ntcreatex.in.flags = oplock_req;
3059
3060                 /* Do the open with the desired oplock on the stream. */
3061                 status = smb_raw_open(cli1->tree, tctx, &io);
3062                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3063                 CHECK_VAL(io.ntcreatex.out.oplock_level, oplock_granted);
3064                 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3065
3066                 /* Cleanup the base file if it was opened. */
3067                 if (base_fnum != -1) {
3068                         smbcli_close(cli2->tree, base_fnum);
3069                 }
3070         }
3071
3072         /* Open the stream with an exclusive oplock. */
3073         torture_comment(tctx, "Opening stream: %s with %d\n",
3074             fname_stream, exclusive_req);
3075         io.ntcreatex.in.fname = fname_stream;
3076         io.ntcreatex.in.flags = exclusive_req;
3077         status = smb_raw_open(cli1->tree, tctx, &io);
3078         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3079         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
3080         stream_fnum = io.ntcreatex.out.file.fnum;
3081
3082         /* Open the base file and see if it contends. */
3083         ZERO_STRUCT(break_info);
3084         torture_comment(tctx, "Opening base file: %s with "
3085             "%d\n", fname_base, batch_req);
3086         io.ntcreatex.in.fname = fname_base;
3087         io.ntcreatex.in.flags = batch_req;
3088         status = smb_raw_open(cli2->tree, tctx, &io);
3089         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3090         CHECK_VAL(io.ntcreatex.out.oplock_level,
3091             BATCH_OPLOCK_RETURN);
3092         smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3093
3094         torture_wait_for_oplock_break(tctx);
3095         CHECK_VAL(break_info.count, 0);
3096         CHECK_VAL(break_info.failures, 0);
3097
3098         /* Open the stream again to see if it contends. */
3099         ZERO_STRUCT(break_info);
3100         torture_comment(tctx, "Opening stream again: %s with "
3101             "%d\n", fname_base, batch_req);
3102         io.ntcreatex.in.fname = fname_stream;
3103         io.ntcreatex.in.flags = exclusive_req;
3104         status = smb_raw_open(cli2->tree, tctx, &io);
3105         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3106         CHECK_VAL(io.ntcreatex.out.oplock_level,
3107             LEVEL_II_OPLOCK_RETURN);
3108         smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3109
3110         torture_wait_for_oplock_break(tctx);
3111         CHECK_VAL(break_info.count, 1);
3112         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3113         CHECK_VAL(break_info.failures, 0);
3114
3115         /* Close the stream. */
3116         if (stream_fnum != -1) {
3117                 smbcli_close(cli1->tree, stream_fnum);
3118         }
3119
3120  done:
3121         smbcli_close(cli1->tree, fnum);
3122         smb_raw_exit(cli1->session);
3123         smb_raw_exit(cli2->session);
3124         smbcli_deltree(cli1->tree, BASEDIR);
3125         return ret;
3126 }
3127
3128 static bool test_raw_oplock_doc(struct torture_context *tctx,
3129                                 struct smbcli_state *cli)
3130 {
3131         const char *fname = BASEDIR "\\test_oplock_doc.dat";
3132         NTSTATUS status;
3133         bool ret = true;
3134         union smb_open io;
3135         uint16_t fnum=0;
3136
3137         if (!torture_setup_dir(cli, BASEDIR)) {
3138                 return false;
3139         }
3140
3141         /* cleanup */
3142         smbcli_unlink(cli->tree, fname);
3143
3144         smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_given,
3145                               cli->tree);
3146
3147         /*
3148           base ntcreatex parms
3149         */
3150         io.generic.level = RAW_OPEN_NTCREATEX;
3151         io.ntcreatex.in.root_fid = 0;
3152         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3153         io.ntcreatex.in.alloc_size = 0;
3154         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3155         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3156         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3157         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3158         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3159         io.ntcreatex.in.security_flags = 0;
3160         io.ntcreatex.in.fname = fname;
3161
3162         torture_comment(tctx, "open a delete-on-close file with a batch "
3163                         "oplock\n");
3164         ZERO_STRUCT(break_info);
3165         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3166             NTCREATEX_FLAGS_REQUEST_OPLOCK |
3167             NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3168
3169         status = smb_raw_open(cli->tree, tctx, &io);
3170         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3171         fnum = io.ntcreatex.out.file.fnum;
3172         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3173
3174         smbcli_close(cli->tree, fnum);
3175
3176 done:
3177         smb_raw_exit(cli->session);
3178         smbcli_deltree(cli->tree, BASEDIR);
3179         return ret;
3180 }
3181
3182 /* Open a file with a batch oplock, then open it again from a second client
3183  * requesting no oplock. Having two open file handles should break our own
3184  * oplock during BRL acquisition.
3185  */
3186 static bool test_raw_oplock_brl1(struct torture_context *tctx,
3187                                  struct smbcli_state *cli1,
3188                                  struct smbcli_state *cli2)
3189 {
3190         const char *fname = BASEDIR "\\test_batch_brl.dat";
3191         /*int fname, f;*/
3192         bool ret = true;
3193         uint8_t buf[1000];
3194         bool correct = true;
3195         union smb_open io;
3196         NTSTATUS status;
3197         uint16_t fnum=0;
3198         uint16_t fnum2=0;
3199
3200         if (!torture_setup_dir(cli1, BASEDIR)) {
3201                 return false;
3202         }
3203
3204         /* cleanup */
3205         smbcli_unlink(cli1->tree, fname);
3206
3207         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3208                               cli1->tree);
3209
3210         /*
3211           base ntcreatex parms
3212         */
3213         io.generic.level = RAW_OPEN_NTCREATEX;
3214         io.ntcreatex.in.root_fid = 0;
3215         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3216                                       SEC_RIGHTS_FILE_WRITE;
3217         io.ntcreatex.in.alloc_size = 0;
3218         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3219         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3220                                        NTCREATEX_SHARE_ACCESS_WRITE;
3221         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3222         io.ntcreatex.in.create_options = 0;
3223         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3224         io.ntcreatex.in.security_flags = 0;
3225         io.ntcreatex.in.fname = fname;
3226
3227         /*
3228           with a batch oplock we get a break
3229         */
3230         torture_comment(tctx, "open with batch oplock\n");
3231         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3232                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3233                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3234
3235         status = smb_raw_open(cli1->tree, tctx, &io);
3236         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3237         fnum = io.ntcreatex.out.file.fnum;
3238         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3239         /* create a file with bogus data */
3240         memset(buf, 0, sizeof(buf));
3241
3242         if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3243                          sizeof(buf))
3244         {
3245                 torture_comment(tctx, "Failed to create file\n");
3246                 correct = false;
3247                 goto done;
3248         }
3249
3250         torture_comment(tctx, "a 2nd open should give a break\n");
3251         ZERO_STRUCT(break_info);
3252
3253         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3254         status = smb_raw_open(cli2->tree, tctx, &io);
3255         fnum2 = io.ntcreatex.out.file.fnum;
3256         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3257         CHECK_VAL(break_info.count, 1);
3258         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3259         CHECK_VAL(break_info.failures, 0);
3260         CHECK_VAL(break_info.fnum, fnum);
3261
3262         ZERO_STRUCT(break_info);
3263
3264         torture_comment(tctx, "a self BRL acquisition should break to none\n");
3265
3266         status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3267         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3268
3269         torture_wait_for_oplock_break(tctx);
3270         CHECK_VAL(break_info.count, 1);
3271         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3272         CHECK_VAL(break_info.fnum, fnum);
3273         CHECK_VAL(break_info.failures, 0);
3274
3275         /* expect no oplock break */
3276         ZERO_STRUCT(break_info);
3277         status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3278         CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3279
3280         torture_wait_for_oplock_break(tctx);
3281         CHECK_VAL(break_info.count, 0);
3282         CHECK_VAL(break_info.level, 0);
3283         CHECK_VAL(break_info.fnum, 0);
3284         CHECK_VAL(break_info.failures, 0);
3285
3286         smbcli_close(cli1->tree, fnum);
3287         smbcli_close(cli2->tree, fnum2);
3288
3289 done:
3290         smb_raw_exit(cli1->session);
3291         smb_raw_exit(cli2->session);
3292         smbcli_deltree(cli1->tree, BASEDIR);
3293         return ret;
3294
3295 }
3296
3297 /* Open a file with a batch oplock on one client and then acquire a brl.
3298  * We should not contend our own oplock.
3299  */
3300 static bool test_raw_oplock_brl2(struct torture_context *tctx, struct smbcli_state *cli1)
3301 {
3302         const char *fname = BASEDIR "\\test_batch_brl.dat";
3303         /*int fname, f;*/
3304         bool ret = true;
3305         uint8_t buf[1000];
3306         bool correct = true;
3307         union smb_open io;
3308         NTSTATUS status;
3309         uint16_t fnum=0;
3310
3311         if (!torture_setup_dir(cli1, BASEDIR)) {
3312                 return false;
3313         }
3314
3315         /* cleanup */
3316         smbcli_unlink(cli1->tree, fname);
3317
3318         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3319                               cli1->tree);
3320
3321         /*
3322           base ntcreatex parms
3323         */
3324         io.generic.level = RAW_OPEN_NTCREATEX;
3325         io.ntcreatex.in.root_fid = 0;
3326         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3327                                       SEC_RIGHTS_FILE_WRITE;
3328         io.ntcreatex.in.alloc_size = 0;
3329         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3330         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3331                                        NTCREATEX_SHARE_ACCESS_WRITE;
3332         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3333         io.ntcreatex.in.create_options = 0;
3334         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3335         io.ntcreatex.in.security_flags = 0;
3336         io.ntcreatex.in.fname = fname;
3337
3338         /*
3339           with a batch oplock we get a break
3340         */
3341         torture_comment(tctx, "open with batch oplock\n");
3342         ZERO_STRUCT(break_info);
3343         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3344                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3345                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3346
3347         status = smb_raw_open(cli1->tree, tctx, &io);
3348         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3349         fnum = io.ntcreatex.out.file.fnum;
3350         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3351
3352         /* create a file with bogus data */
3353         memset(buf, 0, sizeof(buf));
3354
3355         if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3356                          sizeof(buf))
3357         {
3358                 torture_comment(tctx, "Failed to create file\n");
3359                 correct = false;
3360                 goto done;
3361         }
3362
3363         torture_comment(tctx, "a self BRL acquisition should not break to "
3364                         "none\n");
3365
3366         status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3367         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3368
3369         status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3370         CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3371
3372         /* With one file handle open a BRL should not contend our oplock.
3373          * Thus, no oplock break will be received and the entire break_info
3374          * struct will be 0 */
3375         torture_wait_for_oplock_break(tctx);
3376         CHECK_VAL(break_info.fnum, 0);
3377         CHECK_VAL(break_info.count, 0);
3378         CHECK_VAL(break_info.level, 0);
3379         CHECK_VAL(break_info.failures, 0);
3380
3381         smbcli_close(cli1->tree, fnum);
3382
3383 done:
3384         smb_raw_exit(cli1->session);
3385         smbcli_deltree(cli1->tree, BASEDIR);
3386         return ret;
3387 }
3388
3389 /* Open a file with a batch oplock twice from one client and then acquire a
3390  * brl. BRL acquisition should break our own oplock.
3391  */
3392 static bool test_raw_oplock_brl3(struct torture_context *tctx,
3393                                  struct smbcli_state *cli1)
3394 {
3395         const char *fname = BASEDIR "\\test_batch_brl.dat";
3396         bool ret = true;
3397         uint8_t buf[1000];
3398         bool correct = true;
3399         union smb_open io;
3400         NTSTATUS status;
3401         uint16_t fnum=0;
3402         uint16_t fnum2=0;
3403
3404         if (!torture_setup_dir(cli1, BASEDIR)) {
3405                 return false;
3406         }
3407
3408         /* cleanup */
3409         smbcli_unlink(cli1->tree, fname);
3410
3411         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3412                               cli1->tree);
3413
3414         /*
3415           base ntcreatex parms
3416         */
3417         io.generic.level = RAW_OPEN_NTCREATEX;
3418         io.ntcreatex.in.root_fid = 0;
3419         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3420                                       SEC_RIGHTS_FILE_WRITE;
3421         io.ntcreatex.in.alloc_size = 0;
3422         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3423         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3424                                        NTCREATEX_SHARE_ACCESS_WRITE;
3425         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3426         io.ntcreatex.in.create_options = 0;
3427         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3428         io.ntcreatex.in.security_flags = 0;
3429         io.ntcreatex.in.fname = fname;
3430
3431         /*
3432           with a batch oplock we get a break
3433         */
3434         torture_comment(tctx, "open with batch oplock\n");
3435         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3436                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3437                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3438
3439         status = smb_raw_open(cli1->tree, tctx, &io);
3440         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3441         fnum = io.ntcreatex.out.file.fnum;
3442         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3443
3444         /* create a file with bogus data */
3445         memset(buf, 0, sizeof(buf));
3446
3447         if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3448                          sizeof(buf))
3449         {
3450                 torture_comment(tctx, "Failed to create file\n");
3451                 correct = false;
3452                 goto done;
3453         }
3454
3455         torture_comment(tctx, "a 2nd open should give a break\n");
3456         ZERO_STRUCT(break_info);
3457
3458         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3459         status = smb_raw_open(cli1->tree, tctx, &io);
3460         fnum2 = io.ntcreatex.out.file.fnum;
3461         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3462         CHECK_VAL(break_info.count, 1);
3463         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3464         CHECK_VAL(break_info.failures, 0);
3465         CHECK_VAL(break_info.fnum, fnum);
3466
3467         ZERO_STRUCT(break_info);
3468
3469         torture_comment(tctx, "a self BRL acquisition should break to none\n");
3470
3471         status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3472         CHECK_STATUS(tctx, status, NT_STATUS_OK);
3473
3474         torture_wait_for_oplock_break(tctx);
3475         CHECK_VAL(break_info.count, 1);
3476         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3477         CHECK_VAL(break_info.fnum, fnum);
3478         CHECK_VAL(break_info.failures, 0);
3479
3480         /* expect no oplock break */
3481         ZERO_STRUCT(break_info);
3482         status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3483         CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3484
3485         torture_wait_for_oplock_break(tctx);
3486         CHECK_VAL(break_info.count, 0);
3487         CHECK_VAL(break_info.level, 0);
3488         CHECK_VAL(break_info.fnum, 0);
3489         CHECK_VAL(break_info.failures, 0);
3490
3491         smbcli_close(cli1->tree, fnum);
3492         smbcli_close(cli1->tree, fnum2);
3493
3494 done:
3495         smb_raw_exit(cli1->session);
3496         smbcli_deltree(cli1->tree, BASEDIR);
3497         return ret;
3498 }
3499
3500 /*
3501    basic testing of oplocks
3502 */
3503 struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
3504 {
3505         struct torture_suite *suite = torture_suite_create(mem_ctx, "OPLOCK");
3506
3507         torture_suite_add_2smb_test(suite, "EXCLUSIVE1", test_raw_oplock_exclusive1);
3508         torture_suite_add_2smb_test(suite, "EXCLUSIVE2", test_raw_oplock_exclusive2);
3509         torture_suite_add_2smb_test(suite, "EXCLUSIVE3", test_raw_oplock_exclusive3);
3510         torture_suite_add_2smb_test(suite, "EXCLUSIVE4", test_raw_oplock_exclusive4);
3511         torture_suite_add_2smb_test(suite, "EXCLUSIVE5", test_raw_oplock_exclusive5);
3512         torture_suite_add_2smb_test(suite, "EXCLUSIVE6", test_raw_oplock_exclusive6);
3513         torture_suite_add_2smb_test(suite, "BATCH1", test_raw_oplock_batch1);
3514         torture_suite_add_2smb_test(suite, "BATCH2", test_raw_oplock_batch2);
3515         torture_suite_add_2smb_test(suite, "BATCH3", test_raw_oplock_batch3);
3516         torture_suite_add_2smb_test(suite, "BATCH4", test_raw_oplock_batch4);
3517         torture_suite_add_2smb_test(suite, "BATCH5", test_raw_oplock_batch5);
3518         torture_suite_add_2smb_test(suite, "BATCH6", test_raw_oplock_batch6);
3519         torture_suite_add_2smb_test(suite, "BATCH7", test_raw_oplock_batch7);
3520         torture_suite_add_2smb_test(suite, "BATCH8", test_raw_oplock_batch8);
3521         torture_suite_add_2smb_test(suite, "BATCH9", test_raw_oplock_batch9);
3522         torture_suite_add_2smb_test(suite, "BATCH10", test_raw_oplock_batch10);
3523         torture_suite_add_2smb_test(suite, "BATCH11", test_raw_oplock_batch11);
3524         torture_suite_add_2smb_test(suite, "BATCH12", test_raw_oplock_batch12);
3525         torture_suite_add_2smb_test(suite, "BATCH13", test_raw_oplock_batch13);
3526         torture_suite_add_2smb_test(suite, "BATCH14", test_raw_oplock_batch14);
3527         torture_suite_add_2smb_test(suite, "BATCH15", test_raw_oplock_batch15);
3528         torture_suite_add_2smb_test(suite, "BATCH16", test_raw_oplock_batch16);
3529         torture_suite_add_2smb_test(suite, "BATCH17", test_raw_oplock_batch17);
3530         torture_suite_add_2smb_test(suite, "BATCH18", test_raw_oplock_batch18);
3531         torture_suite_add_2smb_test(suite, "BATCH19", test_raw_oplock_batch19);
3532         torture_suite_add_2smb_test(suite, "BATCH20", test_raw_oplock_batch20);
3533         torture_suite_add_2smb_test(suite, "BATCH21", test_raw_oplock_batch21);
3534         torture_suite_add_2smb_test(suite, "BATCH22", test_raw_oplock_batch22);
3535         torture_suite_add_2smb_test(suite, "BATCH23", test_raw_oplock_batch23);
3536         torture_suite_add_2smb_test(suite, "BATCH24", test_raw_oplock_batch24);
3537         torture_suite_add_2smb_test(suite, "BATCH25", test_raw_oplock_batch25);
3538         torture_suite_add_2smb_test(suite, "STREAM1", test_raw_oplock_stream1);
3539         torture_suite_add_1smb_test(suite, "DOC1", test_raw_oplock_doc);
3540         torture_suite_add_2smb_test(suite, "BRL1", test_raw_oplock_brl1);
3541         torture_suite_add_1smb_test(suite, "BRL2", test_raw_oplock_brl2);
3542         torture_suite_add_1smb_test(suite, "BRL3", test_raw_oplock_brl3);
3543
3544         return suite;
3545 }
3546
3547 /*
3548    stress testing of oplocks
3549 */
3550 bool torture_bench_oplock(struct torture_context *torture)
3551 {
3552         struct smbcli_state **cli;
3553         bool ret = true;
3554         TALLOC_CTX *mem_ctx = talloc_new(torture);
3555         int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
3556         int i, count=0;
3557         int timelimit = torture_setting_int(torture, "timelimit", 10);
3558         union smb_open io;
3559         struct timeval tv;
3560
3561         cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
3562
3563         torture_comment(torture, "Opening %d connections\n", torture_nprocs);
3564         for (i=0;i<torture_nprocs;i++) {
3565                 if (!torture_open_connection_ev(&cli[i], i, torture, torture->ev)) {
3566                         return false;
3567                 }
3568                 talloc_steal(mem_ctx, cli[i]);
3569                 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close, 
3570                                       cli[i]->tree);
3571         }
3572
3573         if (!torture_setup_dir(cli[0], BASEDIR)) {
3574                 ret = false;
3575                 goto done;
3576         }
3577
3578         io.ntcreatex.level = RAW_OPEN_NTCREATEX;
3579         io.ntcreatex.in.root_fid = 0;
3580         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3581         io.ntcreatex.in.alloc_size = 0;
3582         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3583         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3584         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3585         io.ntcreatex.in.create_options = 0;
3586         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3587         io.ntcreatex.in.security_flags = 0;
3588         io.ntcreatex.in.fname = BASEDIR "\\test.dat";
3589         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
3590                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
3591                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3592
3593         tv = timeval_current(); 
3594
3595         /*
3596           we open the same file with SHARE_ACCESS_NONE from all the
3597           connections in a round robin fashion. Each open causes an
3598           oplock break on the previous connection, which is answered
3599           by the oplock_handler_close() to close the file.
3600
3601           This measures how fast we can pass on oplocks, and stresses
3602           the oplock handling code
3603         */
3604         torture_comment(torture, "Running for %d seconds\n", timelimit);
3605         while (timeval_elapsed(&tv) < timelimit) {
3606                 for (i=0;i<torture_nprocs;i++) {
3607                         NTSTATUS status;
3608
3609                         status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
3610                         CHECK_STATUS(torture, status, NT_STATUS_OK);
3611                         count++;
3612                 }
3613
3614                 if (torture_setting_bool(torture, "progress", true)) {
3615                         torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
3616                 }
3617         }
3618
3619         torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
3620
3621         smb_raw_exit(cli[torture_nprocs-1]->session);
3622         
3623 done:
3624         smb_raw_exit(cli[0]->session);
3625         smbcli_deltree(cli[0]->tree, BASEDIR);
3626         talloc_free(mem_ctx);
3627         return ret;
3628 }
3629
3630
3631 static struct hold_oplock_info {
3632         const char *fname;
3633         bool close_on_break;
3634         uint32_t share_access;
3635         uint16_t fnum;
3636 } hold_info[] = {
3637         { BASEDIR "\\notshared_close", true,  
3638           NTCREATEX_SHARE_ACCESS_NONE, },
3639         { BASEDIR "\\notshared_noclose", false, 
3640           NTCREATEX_SHARE_ACCESS_NONE, },
3641         { BASEDIR "\\shared_close", true,  
3642           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3643         { BASEDIR "\\shared_noclose", false,  
3644           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3645 };
3646
3647 static bool oplock_handler_hold(struct smbcli_transport *transport, 
3648                                 uint16_t tid, uint16_t fnum, uint8_t level, 
3649                                 void *private_data)
3650 {
3651         struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
3652         struct hold_oplock_info *info;
3653         int i;
3654
3655         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3656                 if (hold_info[i].fnum == fnum) break;
3657         }
3658
3659         if (i == ARRAY_SIZE(hold_info)) {
3660                 printf("oplock break for unknown fnum %u\n", fnum);
3661                 return false;
3662         }
3663
3664         info = &hold_info[i];
3665
3666         if (info->close_on_break) {
3667                 printf("oplock break on %s - closing\n",
3668                        info->fname);
3669                 oplock_handler_close(transport, tid, fnum, level, private_data);
3670                 return true;
3671         }
3672
3673         printf("oplock break on %s - acking break\n", info->fname);
3674
3675         return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
3676 }
3677
3678
3679 /* 
3680    used for manual testing of oplocks - especially interaction with
3681    other filesystems (such as NFS and local access)
3682 */
3683 bool torture_hold_oplock(struct torture_context *torture, 
3684                          struct smbcli_state *cli)
3685 {
3686         struct tevent_context *ev = 
3687                 (struct tevent_context *)cli->transport->socket->event.ctx;
3688         int i;
3689
3690         printf("Setting up open files with oplocks in %s\n", BASEDIR);
3691
3692         if (!torture_setup_dir(cli, BASEDIR)) {
3693                 return false;
3694         }
3695
3696         smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
3697
3698         /* setup the files */
3699         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3700                 union smb_open io;
3701                 NTSTATUS status;
3702                 char c = 1;
3703
3704                 io.generic.level = RAW_OPEN_NTCREATEX;
3705                 io.ntcreatex.in.root_fid = 0;
3706                 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3707                 io.ntcreatex.in.alloc_size = 0;
3708                 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3709                 io.ntcreatex.in.share_access = hold_info[i].share_access;
3710                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3711                 io.ntcreatex.in.create_options = 0;
3712                 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3713                 io.ntcreatex.in.security_flags = 0;
3714                 io.ntcreatex.in.fname = hold_info[i].fname;
3715                 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
3716                         NTCREATEX_FLAGS_REQUEST_OPLOCK |
3717                         NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3718                 printf("opening %s\n", hold_info[i].fname);
3719
3720                 status = smb_raw_open(cli->tree, cli, &io);
3721                 if (!NT_STATUS_IS_OK(status)) {
3722                         printf("Failed to open %s - %s\n", 
3723                                hold_info[i].fname, nt_errstr(status));
3724                         return false;
3725                 }
3726
3727                 if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
3728                         printf("Oplock not granted for %s - expected %d but got %d\n", 
3729                                hold_info[i].fname, BATCH_OPLOCK_RETURN, 
3730                                 io.ntcreatex.out.oplock_level);
3731                         return false;
3732                 }
3733                 hold_info[i].fnum = io.ntcreatex.out.file.fnum;
3734
3735                 /* make the file non-zero size */
3736                 if (smbcli_write(cli->tree, hold_info[i].fnum, 0, &c, 0, 1) != 1) {
3737                         printf("Failed to write to file\n");
3738                         return false;
3739                 }
3740         }
3741
3742         printf("Waiting for oplock events\n");
3743         event_loop_wait(ev);
3744
3745         return true;
3746 }