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