Merge branch 'v4-0-test' of git://git.samba.org/samba into 4-0-local
[gd/samba-autobuild/.git] / source4 / torture / raw / oplock.c
1 /* 
2    Unix SMB/CIFS implementation.
3    basic raw test suite for oplocks
4    Copyright (C) Andrew Tridgell 2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "torture/torture.h"
22 #include "librpc/gen_ndr/security.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/libcli.h"
25 #include "torture/util.h"
26 #include "lib/events/events.h"
27 #include "param/param.h"
28 #include "lib/cmdline/popt_common.h"
29 #include "libcli/resolve/resolve.h"
30
31 #define CHECK_VAL(v, correct) do { \
32         if ((v) != (correct)) { \
33                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
34                                 __location__, #v, (int)v, (int)correct); \
35                 ret = false; \
36         }} while (0)
37
38 #define CHECK_RANGE(v, min, max) do { \
39         if ((v) < (min) || (v) > (max)) { \
40                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got %d - should be between %d and %d\n", \
41                                 __location__, #v, (int)v, (int)min, (int)max); \
42                 ret = false; \
43         }} while (0)
44
45 #define CHECK_STRMATCH(v, correct) do { \
46         if (!v || strstr((v),(correct)) == NULL) { \
47                 torture_result(tctx, TORTURE_FAIL,  "(%s): wrong value for %s got '%s' - should be '%s'\n", \
48                                 __location__, #v, v?v:"NULL", correct); \
49                 ret = false; \
50         } \
51 } while (0)
52
53 #define CHECK_STATUS(tctx, status, correct) do { \
54         if (!NT_STATUS_EQUAL(status, correct)) { \
55                 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
56                        nt_errstr(status), nt_errstr(correct)); \
57                 ret = false; \
58                 goto done; \
59         }} while (0)
60
61
62 static struct {
63         int fnum;
64         uint8_t level;
65         int count;
66         int failures;
67 } break_info;
68
69 #define BASEDIR "\\test_oplock"
70
71 /*
72   a handler function for oplock break requests. Ack it as a break to level II if possible
73 */
74 static bool oplock_handler_ack_to_given(struct smbcli_transport *transport,
75                                         uint16_t tid, uint16_t fnum,
76                                         uint8_t level, void *private)
77 {
78         struct smbcli_tree *tree = (struct smbcli_tree *)private;
79         const char *name;
80
81         break_info.fnum = fnum;
82         break_info.level = level;
83         break_info.count++;
84
85         switch (level) {
86         case OPLOCK_BREAK_TO_LEVEL_II:
87                 name = "level II";
88                 break;
89         case OPLOCK_BREAK_TO_NONE:
90                 name = "none";
91                 break;
92         default:
93                 name = "unknown";
94                 break_info.failures++;
95         }
96         printf("Acking to %s [0x%02X] in oplock handler\n",
97                 name, level);
98
99         return smbcli_oplock_ack(tree, fnum, level);
100 }
101
102 /*
103   a handler function for oplock break requests. Ack it as a break to none
104 */
105 static bool oplock_handler_ack_to_none(struct smbcli_transport *transport, 
106                                        uint16_t tid, uint16_t fnum, 
107                                        uint8_t level, void *private)
108 {
109         struct smbcli_tree *tree = (struct smbcli_tree *)private;
110         break_info.fnum = fnum;
111         break_info.level = level;
112         break_info.count++;
113
114         printf("Acking to none in oplock handler\n");
115
116         return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
117 }
118
119 /*
120   a handler function for oplock break requests. Let it timeout
121 */
122 static bool oplock_handler_timeout(struct smbcli_transport *transport,
123                                    uint16_t tid, uint16_t fnum,
124                                    uint8_t level, void *private)
125 {
126         break_info.fnum = fnum;
127         break_info.level = level;
128         break_info.count++;
129
130         printf("Let oplock break timeout\n");
131         return true;
132 }
133
134 static void oplock_handler_close_recv(struct smbcli_request *req)
135 {
136         NTSTATUS status;
137         status = smbcli_request_simple_recv(req);
138         if (!NT_STATUS_IS_OK(status)) {
139                 printf("close failed in oplock_handler_close\n");
140                 break_info.failures++;
141         }
142 }
143
144 /*
145   a handler function for oplock break requests - close the file
146 */
147 static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t tid, 
148                                  uint16_t fnum, uint8_t level, void *private)
149 {
150         union smb_close io;
151         struct smbcli_tree *tree = (struct smbcli_tree *)private;
152         struct smbcli_request *req;
153
154         break_info.fnum = fnum;
155         break_info.level = level;
156         break_info.count++;
157
158         io.close.level = RAW_CLOSE_CLOSE;
159         io.close.in.file.fnum = fnum;
160         io.close.in.write_time = 0;
161         req = smb_raw_close_send(tree, &io);
162         if (req == NULL) {
163                 printf("failed to send close in oplock_handler_close\n");
164                 return false;
165         }
166
167         req->async.fn = oplock_handler_close_recv;
168         req->async.private = NULL;
169
170         return true;
171 }
172
173 static bool open_connection_no_level2_oplocks(struct torture_context *tctx,
174                                               struct smbcli_state **c)
175 {
176         NTSTATUS status;
177
178         struct smbcli_options options;
179
180         lp_smbcli_options(tctx->lp_ctx, &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, cmdline_credentials,
189                                         lp_resolve_context(tctx->lp_ctx),
190                                         tctx->ev, &options);
191         if (!NT_STATUS_IS_OK(status)) {
192                 printf("Failed to open connection - %s\n", nt_errstr(status));
193                 return false;
194         }
195
196         return true;
197 }
198
199 static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
200 {
201         const char *fname = BASEDIR "\\test_exclusive1.dat";
202         NTSTATUS status;
203         bool ret = true;
204         union smb_open io;
205         union smb_unlink unl;
206         uint16_t fnum=0;
207
208         if (!torture_setup_dir(cli1, BASEDIR)) {
209                 return false;
210         }
211
212         /* cleanup */
213         smbcli_unlink(cli1->tree, fname);
214
215         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
216
217         /*
218           base ntcreatex parms
219         */
220         io.generic.level = RAW_OPEN_NTCREATEX;
221         io.ntcreatex.in.root_fid = 0;
222         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
223         io.ntcreatex.in.alloc_size = 0;
224         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
225         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
226         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
227         io.ntcreatex.in.create_options = 0;
228         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
229         io.ntcreatex.in.security_flags = 0;
230         io.ntcreatex.in.fname = fname;
231
232         torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n");
233         ZERO_STRUCT(break_info);
234         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
235
236         status = smb_raw_open(cli1->tree, tctx, &io);
237         CHECK_STATUS(tctx, status, NT_STATUS_OK);
238         fnum = io.ntcreatex.out.file.fnum;
239         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
240
241         torture_comment(tctx, "a 2nd open should not cause a break\n");
242         status = smb_raw_open(cli2->tree, tctx, &io);
243         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
244         CHECK_VAL(break_info.count, 0);
245         CHECK_VAL(break_info.failures, 0);
246
247         torture_comment(tctx, "unlink it - should also be no break\n");
248         unl.unlink.in.pattern = fname;
249         unl.unlink.in.attrib = 0;
250         status = smb_raw_unlink(cli2->tree, &unl);
251         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
252         CHECK_VAL(break_info.count, 0);
253         CHECK_VAL(break_info.failures, 0);
254
255         smbcli_close(cli1->tree, fnum);
256
257 done:
258         smb_raw_exit(cli1->session);
259         smb_raw_exit(cli2->session);
260         smbcli_deltree(cli1->tree, BASEDIR);
261         return ret;
262 }
263
264 static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
265 {
266         const char *fname = BASEDIR "\\test_exclusive2.dat";
267         NTSTATUS status;
268         bool ret = true;
269         union smb_open io;
270         union smb_unlink unl;
271         uint16_t fnum=0, fnum2=0;
272
273         if (!torture_setup_dir(cli1, BASEDIR)) {
274                 return false;
275         }
276
277         /* cleanup */
278         smbcli_unlink(cli1->tree, fname);
279
280         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
281
282         /*
283           base ntcreatex parms
284         */
285         io.generic.level = RAW_OPEN_NTCREATEX;
286         io.ntcreatex.in.root_fid = 0;
287         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
288         io.ntcreatex.in.alloc_size = 0;
289         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
290         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
291         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
292         io.ntcreatex.in.create_options = 0;
293         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
294         io.ntcreatex.in.security_flags = 0;
295         io.ntcreatex.in.fname = fname;
296
297         torture_comment(tctx, "open a file with an exclusive oplock (share mode: all)\n");
298         ZERO_STRUCT(break_info);
299         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
300         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
301                 NTCREATEX_SHARE_ACCESS_WRITE|
302                 NTCREATEX_SHARE_ACCESS_DELETE;
303
304         status = smb_raw_open(cli1->tree, tctx, &io);
305         CHECK_STATUS(tctx, status, NT_STATUS_OK);
306         fnum = io.ntcreatex.out.file.fnum;
307         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
308
309         torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
310         status = smb_raw_open(cli2->tree, tctx, &io);
311         CHECK_STATUS(tctx, status, NT_STATUS_OK);
312         fnum2 = io.ntcreatex.out.file.fnum;
313         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
314         CHECK_VAL(break_info.count, 1);
315         CHECK_VAL(break_info.fnum, fnum);
316         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
317         CHECK_VAL(break_info.failures, 0);
318         ZERO_STRUCT(break_info);
319
320         /* now we have 2 level II oplocks... */
321         torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
322         unl.unlink.in.pattern = fname;
323         unl.unlink.in.attrib = 0;
324         status = smb_raw_unlink(cli2->tree, &unl);
325         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
326         CHECK_VAL(break_info.count, 0);
327         CHECK_VAL(break_info.failures, 0);
328
329         torture_comment(tctx, "close 1st handle\n");
330         smbcli_close(cli1->tree, fnum);
331
332         torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
333         unl.unlink.in.pattern = fname;
334         unl.unlink.in.attrib = 0;
335         status = smb_raw_unlink(cli2->tree, &unl);
336         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
337         CHECK_VAL(break_info.count, 0);
338         CHECK_VAL(break_info.failures, 0);
339
340         torture_comment(tctx, "close 1st handle\n");
341         smbcli_close(cli2->tree, fnum2);
342
343         torture_comment(tctx, "unlink it\n");
344         unl.unlink.in.pattern = fname;
345         unl.unlink.in.attrib = 0;
346         status = smb_raw_unlink(cli2->tree, &unl);
347         CHECK_STATUS(tctx, status, NT_STATUS_OK);
348         CHECK_VAL(break_info.count, 0);
349         CHECK_VAL(break_info.failures, 0);
350
351 done:
352         smb_raw_exit(cli1->session);
353         smb_raw_exit(cli2->session);
354         smbcli_deltree(cli1->tree, BASEDIR);
355         return ret;
356 }
357
358 static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
359 {
360         const char *fname = BASEDIR "\\test_exclusive3.dat";
361         NTSTATUS status;
362         bool ret = true;
363         union smb_open io;
364         union smb_setfileinfo sfi;
365         uint16_t fnum=0;
366         bool s3 = torture_setting_bool(tctx, "samba3", false);
367
368         if (!torture_setup_dir(cli1, BASEDIR)) {
369                 return false;
370         }
371
372         /* cleanup */
373         smbcli_unlink(cli1->tree, fname);
374
375         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
376
377         /*
378           base ntcreatex parms
379         */
380         io.generic.level = RAW_OPEN_NTCREATEX;
381         io.ntcreatex.in.root_fid = 0;
382         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
383         io.ntcreatex.in.alloc_size = 0;
384         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
385         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
386         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
387         io.ntcreatex.in.create_options = 0;
388         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
389         io.ntcreatex.in.security_flags = 0;
390         io.ntcreatex.in.fname = fname;
391
392         torture_comment(tctx, "open a file with an exclusive oplock (share mode: %s)\n",
393                         s3?"all":"none");
394         ZERO_STRUCT(break_info);
395         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
396         if (s3) {
397                 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
398                         NTCREATEX_SHARE_ACCESS_WRITE|
399                         NTCREATEX_SHARE_ACCESS_DELETE;
400         }
401
402         status = smb_raw_open(cli1->tree, tctx, &io);
403         CHECK_STATUS(tctx, status, NT_STATUS_OK);
404         fnum = io.ntcreatex.out.file.fnum;
405         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
406
407         torture_comment(tctx, "setpathinfo EOF should trigger a break to none\n");
408         ZERO_STRUCT(sfi);
409         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
410         sfi.generic.in.file.path = fname;
411         sfi.end_of_file_info.in.size = 100;
412
413         status = smb_raw_setpathinfo(cli2->tree, &sfi);
414
415         CHECK_STATUS(tctx, status, NT_STATUS_OK);
416         CHECK_VAL(break_info.count, 1);
417         CHECK_VAL(break_info.failures, 0);
418         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
419
420         smbcli_close(cli1->tree, fnum);
421
422 done:
423         smb_raw_exit(cli1->session);
424         smb_raw_exit(cli2->session);
425         smbcli_deltree(cli1->tree, BASEDIR);
426         return ret;
427 }
428
429 static bool test_raw_oplock_exclusive4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
430 {
431         const char *fname = BASEDIR "\\test_exclusive4.dat";
432         NTSTATUS status;
433         bool ret = true;
434         union smb_open io;
435         uint16_t fnum=0, fnum2=0;
436
437         if (!torture_setup_dir(cli1, BASEDIR)) {
438                 return false;
439         }
440
441         /* cleanup */
442         smbcli_unlink(cli1->tree, fname);
443
444         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
445
446         /*
447           base ntcreatex parms
448         */
449         io.generic.level = RAW_OPEN_NTCREATEX;
450         io.ntcreatex.in.root_fid = 0;
451         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
452         io.ntcreatex.in.alloc_size = 0;
453         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
454         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
455         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
456         io.ntcreatex.in.create_options = 0;
457         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
458         io.ntcreatex.in.security_flags = 0;
459         io.ntcreatex.in.fname = fname;
460
461         torture_comment(tctx, "open with exclusive oplock\n");
462         ZERO_STRUCT(break_info);
463         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
464
465         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
466         status = smb_raw_open(cli1->tree, tctx, &io);
467         CHECK_STATUS(tctx, status, NT_STATUS_OK);
468         fnum = io.ntcreatex.out.file.fnum;
469         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
470
471         ZERO_STRUCT(break_info);
472         torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
473
474         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
475         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
476         status = smb_raw_open(cli2->tree, tctx, &io);
477         CHECK_STATUS(tctx, status, NT_STATUS_OK);
478         fnum2 = io.ntcreatex.out.file.fnum;
479         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
480         CHECK_VAL(break_info.count, 0);
481         CHECK_VAL(break_info.failures, 0);
482
483         smbcli_close(cli1->tree, fnum);
484         smbcli_close(cli2->tree, fnum2);
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_exclusive5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
494 {
495         const char *fname = BASEDIR "\\test_exclusive5.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         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
510
511         /*
512           base ntcreatex parms
513         */
514         io.generic.level = RAW_OPEN_NTCREATEX;
515         io.ntcreatex.in.root_fid = 0;
516         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
517         io.ntcreatex.in.alloc_size = 0;
518         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
519         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
520         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
521         io.ntcreatex.in.create_options = 0;
522         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
523         io.ntcreatex.in.security_flags = 0;
524         io.ntcreatex.in.fname = fname;
525
526         torture_comment(tctx, "open with exclusive oplock\n");
527         ZERO_STRUCT(break_info);
528         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
529
530
531         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
532         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
533                 NTCREATEX_SHARE_ACCESS_WRITE|
534                 NTCREATEX_SHARE_ACCESS_DELETE;
535         status = smb_raw_open(cli1->tree, tctx, &io);
536         CHECK_STATUS(tctx, status, NT_STATUS_OK);
537         fnum = io.ntcreatex.out.file.fnum;
538         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
539
540         ZERO_STRUCT(break_info);
541
542         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
543
544         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
545         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
546         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
547         status = smb_raw_open(cli2->tree, tctx, &io);
548         CHECK_STATUS(tctx, status, NT_STATUS_OK);
549         fnum2 = io.ntcreatex.out.file.fnum;
550         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
551         CHECK_VAL(break_info.count, 1);
552         CHECK_VAL(break_info.failures, 0);
553
554         smbcli_close(cli1->tree, fnum);
555         smbcli_close(cli2->tree, fnum2);
556
557 done:
558         smb_raw_exit(cli1->session);
559         smb_raw_exit(cli2->session);
560         smbcli_deltree(cli1->tree, BASEDIR);
561         return ret;
562 }
563
564 static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
565 {
566         const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
567         const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
568         NTSTATUS status;
569         bool ret = true;
570         union smb_open io;
571         union smb_rename rn;
572         uint16_t fnum=0;
573         bool s3 = torture_setting_bool(tctx, "samba3", false);
574
575         if (!torture_setup_dir(cli1, BASEDIR)) {
576                 return false;
577         }
578
579         /* cleanup */
580         smbcli_unlink(cli1->tree, fname1);
581         smbcli_unlink(cli1->tree, fname2);
582
583         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
584
585         /*
586           base ntcreatex parms
587         */
588         io.generic.level = RAW_OPEN_NTCREATEX;
589         io.ntcreatex.in.root_fid = 0;
590         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
591         io.ntcreatex.in.alloc_size = 0;
592         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
593         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
594         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
595         io.ntcreatex.in.create_options = 0;
596         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
597         io.ntcreatex.in.security_flags = 0;
598         io.ntcreatex.in.fname = fname1;
599
600         /* we should use no share mode, when samba3 passes this */
601         torture_comment(tctx, "open a file with an exclusive oplock (share mode: %s)\n",
602                         s3?"all":"none");
603         ZERO_STRUCT(break_info);
604         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
605         if (s3) {
606                 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
607                         NTCREATEX_SHARE_ACCESS_WRITE|
608                         NTCREATEX_SHARE_ACCESS_DELETE;
609         }
610
611         status = smb_raw_open(cli1->tree, tctx, &io);
612         CHECK_STATUS(tctx, status, NT_STATUS_OK);
613         fnum = io.ntcreatex.out.file.fnum;
614         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
615
616         torture_comment(tctx, "rename should not generate a break but get a sharing violation\n");
617         ZERO_STRUCT(rn);
618         rn.generic.level = RAW_RENAME_RENAME;
619         rn.rename.in.pattern1 = fname1;
620         rn.rename.in.pattern2 = fname2;
621         rn.rename.in.attrib = 0;
622
623         printf("trying rename while first file open\n");
624         status = smb_raw_rename(cli2->tree, &rn);
625
626         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
627         CHECK_VAL(break_info.count, 0);
628         CHECK_VAL(break_info.failures, 0);
629
630         smbcli_close(cli1->tree, fnum);
631
632 done:
633         smb_raw_exit(cli1->session);
634         smb_raw_exit(cli2->session);
635         smbcli_deltree(cli1->tree, BASEDIR);
636         return ret;
637 }
638
639 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
640 {
641         const char *fname = BASEDIR "\\test_batch1.dat";
642         NTSTATUS status;
643         bool ret = true;
644         union smb_open io;
645         union smb_unlink unl;
646         uint16_t fnum=0;
647         char c = 0;
648
649         if (!torture_setup_dir(cli1, BASEDIR)) {
650                 return false;
651         }
652
653         /* cleanup */
654         smbcli_unlink(cli1->tree, fname);
655
656         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
657
658         /*
659           base ntcreatex parms
660         */
661         io.generic.level = RAW_OPEN_NTCREATEX;
662         io.ntcreatex.in.root_fid = 0;
663         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
664         io.ntcreatex.in.alloc_size = 0;
665         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
666         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
667         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
668         io.ntcreatex.in.create_options = 0;
669         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
670         io.ntcreatex.in.security_flags = 0;
671         io.ntcreatex.in.fname = fname;
672
673         /*
674           with a batch oplock we get a break
675         */
676         torture_comment(tctx, "open with batch oplock\n");
677         ZERO_STRUCT(break_info);
678         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
679                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
680                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
681         status = smb_raw_open(cli1->tree, tctx, &io);
682         CHECK_STATUS(tctx, status, NT_STATUS_OK);
683         fnum = io.ntcreatex.out.file.fnum;
684         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
685
686         torture_comment(tctx, "unlink should generate a break\n");
687         unl.unlink.in.pattern = fname;
688         unl.unlink.in.attrib = 0;
689         status = smb_raw_unlink(cli2->tree, &unl);
690         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
691
692         CHECK_VAL(break_info.count, 1);
693         CHECK_VAL(break_info.fnum, fnum);
694         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
695         CHECK_VAL(break_info.failures, 0);
696
697         torture_comment(tctx, "2nd unlink should not generate a break\n");
698         ZERO_STRUCT(break_info);
699         status = smb_raw_unlink(cli2->tree, &unl);
700         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
701
702         CHECK_VAL(break_info.count, 0);
703
704         torture_comment(tctx, "writing should generate a self break to none\n");
705         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
706         msleep(100);
707         smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
708
709         CHECK_VAL(break_info.count, 1);
710         CHECK_VAL(break_info.fnum, fnum);
711         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
712         CHECK_VAL(break_info.failures, 0);
713
714         smbcli_close(cli1->tree, fnum);
715
716 done:
717         smb_raw_exit(cli1->session);
718         smb_raw_exit(cli2->session);
719         smbcli_deltree(cli1->tree, BASEDIR);
720         return ret;
721 }
722
723 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
724 {
725         const char *fname = BASEDIR "\\test_batch2.dat";
726         NTSTATUS status;
727         bool ret = true;
728         union smb_open io;
729         union smb_unlink unl;
730         uint16_t fnum=0;
731         char c = 0;
732
733         if (!torture_setup_dir(cli1, BASEDIR)) {
734                 return false;
735         }
736
737         /* cleanup */
738         smbcli_unlink(cli1->tree, fname);
739
740         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
741
742         /*
743           base ntcreatex parms
744         */
745         io.generic.level = RAW_OPEN_NTCREATEX;
746         io.ntcreatex.in.root_fid = 0;
747         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
748         io.ntcreatex.in.alloc_size = 0;
749         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
750         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
751         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
752         io.ntcreatex.in.create_options = 0;
753         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
754         io.ntcreatex.in.security_flags = 0;
755         io.ntcreatex.in.fname = fname;
756
757         torture_comment(tctx, "open with batch oplock\n");
758         ZERO_STRUCT(break_info);
759         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
760                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
761                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
762         status = smb_raw_open(cli1->tree, tctx, &io);
763         CHECK_STATUS(tctx, status, NT_STATUS_OK);
764         fnum = io.ntcreatex.out.file.fnum;
765         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
766
767         torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
768         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
769         unl.unlink.in.pattern = fname;
770         unl.unlink.in.attrib = 0;
771         status = smb_raw_unlink(cli2->tree, &unl);
772         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
773
774         CHECK_VAL(break_info.count, 1);
775         CHECK_VAL(break_info.fnum, fnum);
776         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
777         CHECK_VAL(break_info.failures, 0);
778
779         torture_comment(tctx, "2nd unlink should not generate a break\n");
780         ZERO_STRUCT(break_info);
781         status = smb_raw_unlink(cli2->tree, &unl);
782         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
783
784         CHECK_VAL(break_info.count, 0);
785
786         torture_comment(tctx, "writing should not generate a break\n");
787         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
788         msleep(100);
789         smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
790
791         CHECK_VAL(break_info.count, 0);
792
793         smbcli_close(cli1->tree, fnum);
794
795 done:
796         smb_raw_exit(cli1->session);
797         smb_raw_exit(cli2->session);
798         smbcli_deltree(cli1->tree, BASEDIR);
799         return ret;
800 }
801
802 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
803 {
804         const char *fname = BASEDIR "\\test_batch3.dat";
805         NTSTATUS status;
806         bool ret = true;
807         union smb_open io;
808         union smb_unlink unl;
809         uint16_t fnum=0;
810
811         if (!torture_setup_dir(cli1, BASEDIR)) {
812                 return false;
813         }
814
815         /* cleanup */
816         smbcli_unlink(cli1->tree, fname);
817
818         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
819
820         /*
821           base ntcreatex parms
822         */
823         io.generic.level = RAW_OPEN_NTCREATEX;
824         io.ntcreatex.in.root_fid = 0;
825         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
826         io.ntcreatex.in.alloc_size = 0;
827         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
828         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
829         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
830         io.ntcreatex.in.create_options = 0;
831         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
832         io.ntcreatex.in.security_flags = 0;
833         io.ntcreatex.in.fname = fname;
834
835         torture_comment(tctx, "if we close on break then the unlink can succeed\n");
836         ZERO_STRUCT(break_info);
837         smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
838         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
839                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
840                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
841         status = smb_raw_open(cli1->tree, tctx, &io);
842         CHECK_STATUS(tctx, status, NT_STATUS_OK);
843         fnum = io.ntcreatex.out.file.fnum;
844         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
845
846         unl.unlink.in.pattern = fname;
847         unl.unlink.in.attrib = 0;
848         ZERO_STRUCT(break_info);
849         status = smb_raw_unlink(cli2->tree, &unl);
850         CHECK_STATUS(tctx, status, NT_STATUS_OK);
851
852         CHECK_VAL(break_info.count, 1);
853         CHECK_VAL(break_info.fnum, fnum);
854         CHECK_VAL(break_info.level, 1);
855         CHECK_VAL(break_info.failures, 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_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
867 {
868         const char *fname = BASEDIR "\\test_batch4.dat";
869         NTSTATUS status;
870         bool ret = true;
871         union smb_open io;
872         union smb_read rd;
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 = 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, "a self read should not cause a break\n");
900         ZERO_STRUCT(break_info);
901         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
902
903         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
904                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
905                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
906         status = smb_raw_open(cli1->tree, tctx, &io);
907         CHECK_STATUS(tctx, status, NT_STATUS_OK);
908         fnum = io.ntcreatex.out.file.fnum;
909         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
910
911         rd.read.level = RAW_READ_READ;
912         rd.read.in.file.fnum = fnum;
913         rd.read.in.count = 1;
914         rd.read.in.offset = 0;
915         rd.read.in.remaining = 0;
916         status = smb_raw_read(cli1->tree, &rd);
917         CHECK_STATUS(tctx, status, NT_STATUS_OK);
918         CHECK_VAL(break_info.count, 0);
919         CHECK_VAL(break_info.failures, 0);
920
921         smbcli_close(cli1->tree, fnum);
922
923 done:
924         smb_raw_exit(cli1->session);
925         smb_raw_exit(cli2->session);
926         smbcli_deltree(cli1->tree, BASEDIR);
927         return ret;
928 }
929
930 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
931 {
932         const char *fname = BASEDIR "\\test_batch5.dat";
933         NTSTATUS status;
934         bool ret = true;
935         union smb_open io;
936         uint16_t fnum=0;
937
938         if (!torture_setup_dir(cli1, BASEDIR)) {
939                 return false;
940         }
941
942         /* cleanup */
943         smbcli_unlink(cli1->tree, fname);
944
945         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
946
947         /*
948           base ntcreatex parms
949         */
950         io.generic.level = RAW_OPEN_NTCREATEX;
951         io.ntcreatex.in.root_fid = 0;
952         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
953         io.ntcreatex.in.alloc_size = 0;
954         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
955         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
956         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
957         io.ntcreatex.in.create_options = 0;
958         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
959         io.ntcreatex.in.security_flags = 0;
960         io.ntcreatex.in.fname = fname;
961
962         torture_comment(tctx, "a 2nd open should give a break\n");
963         ZERO_STRUCT(break_info);
964         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
965
966         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
967                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
968                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
969         status = smb_raw_open(cli1->tree, tctx, &io);
970         CHECK_STATUS(tctx, status, NT_STATUS_OK);
971         fnum = io.ntcreatex.out.file.fnum;
972         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
973
974         ZERO_STRUCT(break_info);
975
976         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
977         status = smb_raw_open(cli2->tree, tctx, &io);
978         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
979
980         CHECK_VAL(break_info.count, 1);
981         CHECK_VAL(break_info.fnum, fnum);
982         CHECK_VAL(break_info.level, 1);
983         CHECK_VAL(break_info.failures, 0);
984
985         smbcli_close(cli1->tree, fnum);
986
987 done:
988         smb_raw_exit(cli1->session);
989         smb_raw_exit(cli2->session);
990         smbcli_deltree(cli1->tree, BASEDIR);
991         return ret;
992 }
993
994 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
995 {
996         const char *fname = BASEDIR "\\test_batch6.dat";
997         NTSTATUS status;
998         bool ret = true;
999         union smb_open io;
1000         uint16_t fnum=0, fnum2=0;
1001         char c = 0;
1002
1003         if (!torture_setup_dir(cli1, BASEDIR)) {
1004                 return false;
1005         }
1006
1007         /* cleanup */
1008         smbcli_unlink(cli1->tree, fname);
1009
1010         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1011
1012         /*
1013           base ntcreatex parms
1014         */
1015         io.generic.level = RAW_OPEN_NTCREATEX;
1016         io.ntcreatex.in.root_fid = 0;
1017         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1018         io.ntcreatex.in.alloc_size = 0;
1019         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1020         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1021         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1022         io.ntcreatex.in.create_options = 0;
1023         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1024         io.ntcreatex.in.security_flags = 0;
1025         io.ntcreatex.in.fname = fname;
1026
1027         torture_comment(tctx, "a 2nd open should give a break to level II if the first open allowed shared read\n");
1028         ZERO_STRUCT(break_info);
1029         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1030         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1031
1032         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
1033         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
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         status = smb_raw_open(cli2->tree, tctx, &io);
1045         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1046         fnum2 = io.ntcreatex.out.file.fnum;
1047         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1048
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         ZERO_STRUCT(break_info);
1054
1055         torture_comment(tctx, "write should trigger a break to none on both\n");
1056         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1057         msleep(100);
1058         smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
1059
1060         CHECK_VAL(break_info.count, 2);
1061         CHECK_VAL(break_info.level, 0);
1062         CHECK_VAL(break_info.failures, 0);
1063
1064         smbcli_close(cli1->tree, fnum);
1065         smbcli_close(cli2->tree, fnum2);
1066
1067
1068 done:
1069         smb_raw_exit(cli1->session);
1070         smb_raw_exit(cli2->session);
1071         smbcli_deltree(cli1->tree, BASEDIR);
1072         return ret;
1073 }
1074
1075 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1076 {
1077         const char *fname = BASEDIR "\\test_batch7.dat";
1078         NTSTATUS status;
1079         bool ret = true;
1080         union smb_open io;
1081         uint16_t fnum=0, fnum2=0;
1082
1083         if (!torture_setup_dir(cli1, BASEDIR)) {
1084                 return false;
1085         }
1086
1087         /* cleanup */
1088         smbcli_unlink(cli1->tree, fname);
1089
1090         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1091
1092         /*
1093           base ntcreatex parms
1094         */
1095         io.generic.level = RAW_OPEN_NTCREATEX;
1096         io.ntcreatex.in.root_fid = 0;
1097         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1098         io.ntcreatex.in.alloc_size = 0;
1099         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1100         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1101         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1102         io.ntcreatex.in.create_options = 0;
1103         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1104         io.ntcreatex.in.security_flags = 0;
1105         io.ntcreatex.in.fname = fname;
1106
1107         torture_comment(tctx, "a 2nd open should get an oplock when we close instead of ack\n");
1108         ZERO_STRUCT(break_info);
1109         smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1110
1111         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1112         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1113         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1114                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1115                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1116         status = smb_raw_open(cli1->tree, tctx, &io);
1117         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1118         fnum2 = io.ntcreatex.out.file.fnum;
1119         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1120
1121         ZERO_STRUCT(break_info);
1122
1123         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1124                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1125                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1126         status = smb_raw_open(cli2->tree, tctx, &io);
1127         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1128         fnum = io.ntcreatex.out.file.fnum;
1129         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1130
1131         CHECK_VAL(break_info.count, 1);
1132         CHECK_VAL(break_info.fnum, fnum2);
1133         CHECK_VAL(break_info.level, 1);
1134         CHECK_VAL(break_info.failures, 0);
1135         
1136         smbcli_close(cli2->tree, fnum);
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_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1146 {
1147         const char *fname = BASEDIR "\\test_batch8.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 = 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, "open with batch oplock\n");
1178         ZERO_STRUCT(break_info);
1179         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1180
1181         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1182                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1183                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1184         status = smb_raw_open(cli1->tree, tctx, &io);
1185         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1186         fnum = io.ntcreatex.out.file.fnum;
1187         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1188
1189         ZERO_STRUCT(break_info);
1190         torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
1191
1192         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1193                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1194                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1195         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1196         status = smb_raw_open(cli2->tree, tctx, &io);
1197         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1198         fnum2 = io.ntcreatex.out.file.fnum;
1199         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1200         CHECK_VAL(break_info.count, 0);
1201         CHECK_VAL(break_info.failures, 0);
1202
1203         smbcli_close(cli1->tree, fnum);
1204         smbcli_close(cli2->tree, fnum2);
1205
1206 done:
1207         smb_raw_exit(cli1->session);
1208         smb_raw_exit(cli2->session);
1209         smbcli_deltree(cli1->tree, BASEDIR);
1210         return ret;
1211 }
1212
1213 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1214 {
1215         const char *fname = BASEDIR "\\test_batch9.dat";
1216         NTSTATUS status;
1217         bool ret = true;
1218         union smb_open io;
1219         uint16_t fnum=0, fnum2=0;
1220         char c = 0;
1221
1222         if (!torture_setup_dir(cli1, BASEDIR)) {
1223                 return false;
1224         }
1225
1226         /* cleanup */
1227         smbcli_unlink(cli1->tree, fname);
1228
1229         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1230
1231         /*
1232           base ntcreatex parms
1233         */
1234         io.generic.level = RAW_OPEN_NTCREATEX;
1235         io.ntcreatex.in.root_fid = 0;
1236         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1237         io.ntcreatex.in.alloc_size = 0;
1238         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1239         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1240         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1241         io.ntcreatex.in.create_options = 0;
1242         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1243         io.ntcreatex.in.security_flags = 0;
1244         io.ntcreatex.in.fname = fname;
1245
1246         torture_comment(tctx, "open with attributes only can create file\n");
1247
1248         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1249                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1250                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1251         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1252         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1253         status = smb_raw_open(cli1->tree, tctx, &io);
1254         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1255         fnum = io.ntcreatex.out.file.fnum;
1256         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1257
1258         torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
1259
1260         ZERO_STRUCT(break_info);
1261         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
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_RIGHTS_FILE_ALL;
1267         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1268         status = smb_raw_open(cli2->tree, tctx, &io);
1269         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1270         fnum2 = io.ntcreatex.out.file.fnum;
1271         CHECK_VAL(break_info.count, 1);
1272         CHECK_VAL(break_info.fnum, fnum);
1273         CHECK_VAL(break_info.failures, 0);
1274         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1275         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1276         smbcli_close(cli2->tree, fnum2);
1277
1278         torture_comment(tctx, "third oplocked open should grant level2 without break\n");
1279         ZERO_STRUCT(break_info);
1280         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1281         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1282         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1283                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1284                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1285         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1286         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1287         status = smb_raw_open(cli2->tree, tctx, &io);
1288         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1289         fnum2 = io.ntcreatex.out.file.fnum;
1290         CHECK_VAL(break_info.count, 0);
1291         CHECK_VAL(break_info.failures, 0);
1292         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1293
1294         ZERO_STRUCT(break_info);
1295
1296         torture_comment(tctx, "write should trigger a break to none on both\n");
1297         smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
1298
1299         /* Now the oplock break request comes in. But right now we can't
1300          * answer it. Do another write */
1301
1302         msleep(100);
1303         smbcli_write(cli2->tree, fnum2, 0, &c, 1, 1);
1304
1305         CHECK_VAL(break_info.count, 2);
1306         CHECK_VAL(break_info.level, 0);
1307         CHECK_VAL(break_info.failures, 0);
1308
1309         smbcli_close(cli1->tree, fnum);
1310         smbcli_close(cli2->tree, fnum2);
1311
1312 done:
1313         smb_raw_exit(cli1->session);
1314         smb_raw_exit(cli2->session);
1315         smbcli_deltree(cli1->tree, BASEDIR);
1316         return ret;
1317 }
1318
1319 static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1320 {
1321         const char *fname = BASEDIR "\\test_batch10.dat";
1322         NTSTATUS status;
1323         bool ret = true;
1324         union smb_open io;
1325         uint16_t fnum=0, fnum2=0;
1326
1327         if (!torture_setup_dir(cli1, BASEDIR)) {
1328                 return false;
1329         }
1330
1331         /* cleanup */
1332         smbcli_unlink(cli1->tree, fname);
1333
1334         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1335
1336         /*
1337           base ntcreatex parms
1338         */
1339         io.generic.level = RAW_OPEN_NTCREATEX;
1340         io.ntcreatex.in.root_fid = 0;
1341         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1342         io.ntcreatex.in.alloc_size = 0;
1343         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1344         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1345         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1346         io.ntcreatex.in.create_options = 0;
1347         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1348         io.ntcreatex.in.security_flags = 0;
1349         io.ntcreatex.in.fname = fname;
1350
1351         torture_comment(tctx, "Open with oplock after a non-oplock open should grant level2\n");
1352         ZERO_STRUCT(break_info);
1353         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1354         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1355         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1356                 NTCREATEX_SHARE_ACCESS_WRITE|
1357                 NTCREATEX_SHARE_ACCESS_DELETE;
1358         status = smb_raw_open(cli1->tree, tctx, &io);
1359         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1360         fnum = io.ntcreatex.out.file.fnum;
1361         CHECK_VAL(break_info.count, 0);
1362         CHECK_VAL(break_info.failures, 0);
1363         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1364
1365         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1366
1367         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1368                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1369                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1370         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1371         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1372                 NTCREATEX_SHARE_ACCESS_WRITE|
1373                 NTCREATEX_SHARE_ACCESS_DELETE;
1374         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1375         status = smb_raw_open(cli2->tree, tctx, &io);
1376         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1377         fnum2 = io.ntcreatex.out.file.fnum;
1378         CHECK_VAL(break_info.count, 0);
1379         CHECK_VAL(break_info.failures, 0);
1380         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1381
1382         torture_comment(tctx, "write should trigger a break to none\n");
1383         {
1384                 union smb_write wr;
1385                 wr.write.level = RAW_WRITE_WRITE;
1386                 wr.write.in.file.fnum = fnum;
1387                 wr.write.in.count = 1;
1388                 wr.write.in.offset = 0;
1389                 wr.write.in.remaining = 0;
1390                 wr.write.in.data = (const uint8_t *)"x";
1391                 status = smb_raw_write(cli1->tree, &wr);
1392                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1393         }
1394
1395         /* Now the oplock break request comes in. But right now we can't
1396          * answer it. Do another write */
1397
1398         msleep(100);
1399         
1400         {
1401                 union smb_write wr;
1402                 wr.write.level = RAW_WRITE_WRITE;
1403                 wr.write.in.file.fnum = fnum;
1404                 wr.write.in.count = 1;
1405                 wr.write.in.offset = 0;
1406                 wr.write.in.remaining = 0;
1407                 wr.write.in.data = (const uint8_t *)"x";
1408                 status = smb_raw_write(cli1->tree, &wr);
1409                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1410         }
1411
1412         CHECK_VAL(break_info.count, 1);
1413         CHECK_VAL(break_info.fnum, fnum2);
1414         CHECK_VAL(break_info.level, 0);
1415         CHECK_VAL(break_info.failures, 0);
1416
1417         smbcli_close(cli1->tree, fnum);
1418         smbcli_close(cli2->tree, fnum2);
1419
1420 done:
1421         smb_raw_exit(cli1->session);
1422         smb_raw_exit(cli2->session);
1423         smbcli_deltree(cli1->tree, BASEDIR);
1424         return ret;
1425 }
1426
1427 static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1428 {
1429         const char *fname = BASEDIR "\\test_batch11.dat";
1430         NTSTATUS status;
1431         bool ret = true;
1432         union smb_open io;
1433         union smb_setfileinfo sfi;
1434         uint16_t fnum=0;
1435
1436         if (!torture_setup_dir(cli1, BASEDIR)) {
1437                 return false;
1438         }
1439
1440         /* cleanup */
1441         smbcli_unlink(cli1->tree, fname);
1442
1443         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1444
1445         /*
1446           base ntcreatex parms
1447         */
1448         io.generic.level = RAW_OPEN_NTCREATEX;
1449         io.ntcreatex.in.root_fid = 0;
1450         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1451         io.ntcreatex.in.alloc_size = 0;
1452         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1453         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1454         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1455         io.ntcreatex.in.create_options = 0;
1456         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1457         io.ntcreatex.in.security_flags = 0;
1458         io.ntcreatex.in.fname = fname;
1459
1460         /* Test if a set-eof on pathname breaks an exclusive oplock. */
1461         torture_comment(tctx, "Test if setpathinfo set EOF breaks oplocks.\n");
1462
1463         ZERO_STRUCT(break_info);
1464         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1465
1466         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1467                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1468                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1469         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1470         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1471                 NTCREATEX_SHARE_ACCESS_WRITE|
1472                 NTCREATEX_SHARE_ACCESS_DELETE;
1473         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1474         status = smb_raw_open(cli1->tree, tctx, &io);
1475         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1476         fnum = io.ntcreatex.out.file.fnum;
1477         CHECK_VAL(break_info.count, 0);
1478         CHECK_VAL(break_info.failures, 0);
1479         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1480         
1481         ZERO_STRUCT(sfi);
1482         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1483         sfi.generic.in.file.path = fname;
1484         sfi.end_of_file_info.in.size = 100;
1485
1486         status = smb_raw_setpathinfo(cli2->tree, &sfi);
1487
1488         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1489         CHECK_VAL(break_info.count, 1);
1490         CHECK_VAL(break_info.failures, 0);
1491         CHECK_VAL(break_info.level, 0);
1492
1493         smbcli_close(cli1->tree, fnum);
1494
1495 done:
1496         smb_raw_exit(cli1->session);
1497         smb_raw_exit(cli2->session);
1498         smbcli_deltree(cli1->tree, BASEDIR);
1499         return ret;
1500 }
1501
1502 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1503 {
1504         const char *fname = BASEDIR "\\test_batch12.dat";
1505         NTSTATUS status;
1506         bool ret = true;
1507         union smb_open io;
1508         union smb_setfileinfo sfi;
1509         uint16_t fnum=0;
1510
1511         if (!torture_setup_dir(cli1, BASEDIR)) {
1512                 return false;
1513         }
1514
1515         /* cleanup */
1516         smbcli_unlink(cli1->tree, fname);
1517
1518         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1519
1520         /*
1521           base ntcreatex parms
1522         */
1523         io.generic.level = RAW_OPEN_NTCREATEX;
1524         io.ntcreatex.in.root_fid = 0;
1525         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1526         io.ntcreatex.in.alloc_size = 0;
1527         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1528         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1529         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1530         io.ntcreatex.in.create_options = 0;
1531         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1532         io.ntcreatex.in.security_flags = 0;
1533         io.ntcreatex.in.fname = fname;
1534
1535         /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1536         torture_comment(tctx, "Test if setpathinfo allocation size breaks oplocks.\n");
1537
1538         ZERO_STRUCT(break_info);
1539         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1540
1541         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1542                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1543                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1544         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1545         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1546                 NTCREATEX_SHARE_ACCESS_WRITE|
1547                 NTCREATEX_SHARE_ACCESS_DELETE;
1548         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1549         status = smb_raw_open(cli1->tree, tctx, &io);
1550         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1551         fnum = io.ntcreatex.out.file.fnum;
1552         CHECK_VAL(break_info.count, 0);
1553         CHECK_VAL(break_info.failures, 0);
1554         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1555         
1556         ZERO_STRUCT(sfi);
1557         sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
1558         sfi.generic.in.file.path = fname;
1559         sfi.allocation_info.in.alloc_size = 65536 * 8;
1560
1561         status = smb_raw_setpathinfo(cli2->tree, &sfi);
1562
1563         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1564         CHECK_VAL(break_info.count, 1);
1565         CHECK_VAL(break_info.failures, 0);
1566         CHECK_VAL(break_info.level, 0);
1567
1568         smbcli_close(cli1->tree, fnum);
1569
1570 done:
1571         smb_raw_exit(cli1->session);
1572         smb_raw_exit(cli2->session);
1573         smbcli_deltree(cli1->tree, BASEDIR);
1574         return ret;
1575 }
1576
1577 static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1578 {
1579         const char *fname = BASEDIR "\\test_batch13.dat";
1580         NTSTATUS status;
1581         bool ret = true;
1582         union smb_open io;
1583         uint16_t fnum=0, fnum2=0;
1584
1585         if (!torture_setup_dir(cli1, BASEDIR)) {
1586                 return false;
1587         }
1588
1589         /* cleanup */
1590         smbcli_unlink(cli1->tree, fname);
1591
1592         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1593         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
1594
1595         /*
1596           base ntcreatex parms
1597         */
1598         io.generic.level = RAW_OPEN_NTCREATEX;
1599         io.ntcreatex.in.root_fid = 0;
1600         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1601         io.ntcreatex.in.alloc_size = 0;
1602         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1603         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1604         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1605         io.ntcreatex.in.create_options = 0;
1606         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1607         io.ntcreatex.in.security_flags = 0;
1608         io.ntcreatex.in.fname = fname;
1609
1610         torture_comment(tctx, "open with batch oplock\n");
1611         ZERO_STRUCT(break_info);
1612         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1613
1614
1615         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1616                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1617                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1618         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1619                 NTCREATEX_SHARE_ACCESS_WRITE|
1620                 NTCREATEX_SHARE_ACCESS_DELETE;
1621         status = smb_raw_open(cli1->tree, tctx, &io);
1622         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1623         fnum = io.ntcreatex.out.file.fnum;
1624         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1625
1626         ZERO_STRUCT(break_info);
1627
1628         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1629
1630         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1631                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1632                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1633         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1634         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1635                 NTCREATEX_SHARE_ACCESS_WRITE|
1636                 NTCREATEX_SHARE_ACCESS_DELETE;
1637         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1638         status = smb_raw_open(cli2->tree, tctx, &io);
1639         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1640         fnum2 = io.ntcreatex.out.file.fnum;
1641         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1642         CHECK_VAL(break_info.count, 1);
1643         CHECK_VAL(break_info.failures, 0);
1644
1645         smbcli_close(cli1->tree, fnum);
1646         smbcli_close(cli2->tree, fnum2);
1647
1648 done:
1649         smb_raw_exit(cli1->session);
1650         smb_raw_exit(cli2->session);
1651         smbcli_deltree(cli1->tree, BASEDIR);
1652         return ret;
1653 }
1654
1655 static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1656 {
1657         const char *fname = BASEDIR "\\test_batch14.dat";
1658         NTSTATUS status;
1659         bool ret = true;
1660         union smb_open io;
1661         uint16_t fnum=0, fnum2=0;
1662
1663         if (!torture_setup_dir(cli1, BASEDIR)) {
1664                 return false;
1665         }
1666
1667         /* cleanup */
1668         smbcli_unlink(cli1->tree, fname);
1669
1670         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1671
1672         /*
1673           base ntcreatex parms
1674         */
1675         io.generic.level = RAW_OPEN_NTCREATEX;
1676         io.ntcreatex.in.root_fid = 0;
1677         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1678         io.ntcreatex.in.alloc_size = 0;
1679         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1680         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1681         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1682         io.ntcreatex.in.create_options = 0;
1683         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1684         io.ntcreatex.in.security_flags = 0;
1685         io.ntcreatex.in.fname = fname;
1686
1687         torture_comment(tctx, "open with batch oplock\n");
1688         ZERO_STRUCT(break_info);
1689         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1690
1691         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1692                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1693                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1694         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1695                 NTCREATEX_SHARE_ACCESS_WRITE|
1696                 NTCREATEX_SHARE_ACCESS_DELETE;
1697         status = smb_raw_open(cli1->tree, tctx, &io);
1698         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1699         fnum = io.ntcreatex.out.file.fnum;
1700         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1701
1702         ZERO_STRUCT(break_info);
1703
1704         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
1705
1706         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1707                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1708                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1709         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1710         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1711                 NTCREATEX_SHARE_ACCESS_WRITE|
1712                 NTCREATEX_SHARE_ACCESS_DELETE;
1713         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1714         status = smb_raw_open(cli2->tree, tctx, &io);
1715         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1716         fnum2 = io.ntcreatex.out.file.fnum;
1717         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1718         CHECK_VAL(break_info.count, 1);
1719         CHECK_VAL(break_info.failures, 0);
1720
1721         smbcli_close(cli1->tree, fnum);
1722         smbcli_close(cli2->tree, fnum2);
1723 done:
1724         smb_raw_exit(cli1->session);
1725         smb_raw_exit(cli2->session);
1726         smbcli_deltree(cli1->tree, BASEDIR);
1727         return ret;
1728 }
1729
1730 static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1731 {
1732         const char *fname = BASEDIR "\\test_batch15.dat";
1733         NTSTATUS status;
1734         bool ret = true;
1735         union smb_open io;
1736         union smb_fileinfo qfi;
1737         uint16_t fnum=0;
1738
1739         if (!torture_setup_dir(cli1, BASEDIR)) {
1740                 return false;
1741         }
1742
1743         /* cleanup */
1744         smbcli_unlink(cli1->tree, fname);
1745
1746         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1747
1748         /*
1749           base ntcreatex parms
1750         */
1751         io.generic.level = RAW_OPEN_NTCREATEX;
1752         io.ntcreatex.in.root_fid = 0;
1753         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1754         io.ntcreatex.in.alloc_size = 0;
1755         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1756         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1757         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1758         io.ntcreatex.in.create_options = 0;
1759         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1760         io.ntcreatex.in.security_flags = 0;
1761         io.ntcreatex.in.fname = fname;
1762
1763         /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
1764         torture_comment(tctx, "Test if qpathinfo all info breaks a batch oplock (should not).\n");
1765
1766         ZERO_STRUCT(break_info);
1767         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1768
1769         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1770                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1771                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1772         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1773         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1774                 NTCREATEX_SHARE_ACCESS_WRITE|
1775                 NTCREATEX_SHARE_ACCESS_DELETE;
1776         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1777         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1778         status = smb_raw_open(cli1->tree, tctx, &io);
1779         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1780         fnum = io.ntcreatex.out.file.fnum;
1781         CHECK_VAL(break_info.count, 0);
1782         CHECK_VAL(break_info.failures, 0);
1783         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1784
1785         ZERO_STRUCT(qfi);
1786         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1787         qfi.generic.in.file.path = fname;
1788
1789         status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
1790
1791         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1792         CHECK_VAL(break_info.count, 0);
1793
1794         smbcli_close(cli1->tree, fnum);
1795
1796 done:
1797         smb_raw_exit(cli1->session);
1798         smb_raw_exit(cli2->session);
1799         smbcli_deltree(cli1->tree, BASEDIR);
1800         return ret;
1801 }
1802
1803 static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1804 {
1805         const char *fname = BASEDIR "\\test_batch16.dat";
1806         NTSTATUS status;
1807         bool ret = true;
1808         union smb_open io;
1809         uint16_t fnum=0, fnum2=0;
1810
1811         if (!torture_setup_dir(cli1, BASEDIR)) {
1812                 return false;
1813         }
1814
1815         /* cleanup */
1816         smbcli_unlink(cli1->tree, fname);
1817
1818         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1819         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
1820
1821         /*
1822           base ntcreatex parms
1823         */
1824         io.generic.level = RAW_OPEN_NTCREATEX;
1825         io.ntcreatex.in.root_fid = 0;
1826         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1827         io.ntcreatex.in.alloc_size = 0;
1828         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1829         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1830         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1831         io.ntcreatex.in.create_options = 0;
1832         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1833         io.ntcreatex.in.security_flags = 0;
1834         io.ntcreatex.in.fname = fname;
1835
1836         torture_comment(tctx, "open with batch oplock\n");
1837         ZERO_STRUCT(break_info);
1838         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1839
1840
1841         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1842                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1843                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1844         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1845                 NTCREATEX_SHARE_ACCESS_WRITE|
1846                 NTCREATEX_SHARE_ACCESS_DELETE;
1847         status = smb_raw_open(cli1->tree, tctx, &io);
1848         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1849         fnum = io.ntcreatex.out.file.fnum;
1850         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1851
1852         ZERO_STRUCT(break_info);
1853
1854         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
1855
1856         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1857                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1858                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1859         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1860         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1861                 NTCREATEX_SHARE_ACCESS_WRITE|
1862                 NTCREATEX_SHARE_ACCESS_DELETE;
1863         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1864         status = smb_raw_open(cli2->tree, tctx, &io);
1865         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1866         fnum2 = io.ntcreatex.out.file.fnum;
1867         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1868         CHECK_VAL(break_info.count, 1);
1869         CHECK_VAL(break_info.failures, 0);
1870
1871         smbcli_close(cli1->tree, fnum);
1872         smbcli_close(cli2->tree, fnum2);
1873
1874 done:
1875         smb_raw_exit(cli1->session);
1876         smb_raw_exit(cli2->session);
1877         smbcli_deltree(cli1->tree, BASEDIR);
1878         return ret;
1879 }
1880
1881 static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1882 {
1883         const char *fname1 = BASEDIR "\\test_batch17_1.dat";
1884         const char *fname2 = BASEDIR "\\test_batch17_2.dat";
1885         NTSTATUS status;
1886         bool ret = true;
1887         union smb_open io;
1888         union smb_rename rn;
1889         uint16_t fnum=0;
1890         bool s3 = torture_setting_bool(tctx, "samba3", false);
1891
1892         if (!torture_setup_dir(cli1, BASEDIR)) {
1893                 return false;
1894         }
1895
1896         /* cleanup */
1897         smbcli_unlink(cli1->tree, fname1);
1898         smbcli_unlink(cli1->tree, fname2);
1899
1900         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1901
1902         /*
1903           base ntcreatex parms
1904         */
1905         io.generic.level = RAW_OPEN_NTCREATEX;
1906         io.ntcreatex.in.root_fid = 0;
1907         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1908         io.ntcreatex.in.alloc_size = 0;
1909         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1910         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1911         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1912         io.ntcreatex.in.create_options = 0;
1913         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1914         io.ntcreatex.in.security_flags = 0;
1915         io.ntcreatex.in.fname = fname1;
1916
1917         /* we should use no share mode, when samba3 passes this */
1918         torture_comment(tctx, "open a file with an batch oplock (share mode: %s)\n",
1919                         s3?"all":"none");
1920         ZERO_STRUCT(break_info);
1921         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1922                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1923                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1924         if (s3) {
1925                 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1926                         NTCREATEX_SHARE_ACCESS_WRITE|
1927                         NTCREATEX_SHARE_ACCESS_DELETE;
1928         }
1929
1930         status = smb_raw_open(cli1->tree, tctx, &io);
1931         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1932         fnum = io.ntcreatex.out.file.fnum;
1933         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1934
1935         torture_comment(tctx, "rename should trigger a break\n");
1936         ZERO_STRUCT(rn);
1937         rn.generic.level = RAW_RENAME_RENAME;
1938         rn.rename.in.pattern1 = fname1;
1939         rn.rename.in.pattern2 = fname2;
1940         rn.rename.in.attrib = 0;
1941
1942         printf("trying rename while first file open\n");
1943         status = smb_raw_rename(cli2->tree, &rn);
1944
1945         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1946         CHECK_VAL(break_info.count, 1);
1947         CHECK_VAL(break_info.failures, 0);
1948         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1949
1950         smbcli_close(cli1->tree, fnum);
1951
1952 done:
1953         smb_raw_exit(cli1->session);
1954         smb_raw_exit(cli2->session);
1955         smbcli_deltree(cli1->tree, BASEDIR);
1956         return ret;
1957 }
1958
1959 static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1960 {
1961         const char *fname1 = BASEDIR "\\test_batch18_1.dat";
1962         const char *fname2 = BASEDIR "\\test_batch18_2.dat";
1963         NTSTATUS status;
1964         bool ret = true;
1965         union smb_open io;
1966         union smb_rename rn;
1967         uint16_t fnum=0;
1968         bool s3 = torture_setting_bool(tctx, "samba3", false);
1969
1970         if (!torture_setup_dir(cli1, BASEDIR)) {
1971                 return false;
1972         }
1973
1974         /* cleanup */
1975         smbcli_unlink(cli1->tree, fname1);
1976         smbcli_unlink(cli1->tree, fname2);
1977
1978         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1979
1980         /*
1981           base ntcreatex parms
1982         */
1983         io.generic.level = RAW_OPEN_NTCREATEX;
1984         io.ntcreatex.in.root_fid = 0;
1985         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1986         io.ntcreatex.in.alloc_size = 0;
1987         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1988         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1989         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1990         io.ntcreatex.in.create_options = 0;
1991         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1992         io.ntcreatex.in.security_flags = 0;
1993         io.ntcreatex.in.fname = fname1;
1994
1995         /* we should use no share mode, when samba3 passes this */
1996         torture_comment(tctx, "open a file with an batch oplock (share mode: %s)\n",
1997                         s3?"all":"none");
1998         ZERO_STRUCT(break_info);
1999         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2000                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2001                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2002         if (s3) {
2003                 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2004                         NTCREATEX_SHARE_ACCESS_WRITE|
2005                         NTCREATEX_SHARE_ACCESS_DELETE;
2006         }
2007
2008         status = smb_raw_open(cli1->tree, tctx, &io);
2009         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2010         fnum = io.ntcreatex.out.file.fnum;
2011         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2012
2013         torture_comment(tctx, "ntrename should trigger a break\n");
2014         ZERO_STRUCT(rn);
2015         rn.generic.level = RAW_RENAME_NTRENAME;
2016         rn.ntrename.in.attrib   = 0;
2017         rn.ntrename.in.flags    = RENAME_FLAG_RENAME;
2018         rn.ntrename.in.old_name = fname1;
2019         rn.ntrename.in.new_name = fname2;
2020         printf("trying rename while first file open\n");
2021         status = smb_raw_rename(cli2->tree, &rn);
2022
2023         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2024         CHECK_VAL(break_info.count, 1);
2025         CHECK_VAL(break_info.failures, 0);
2026         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2027
2028         smbcli_close(cli1->tree, fnum);
2029
2030 done:
2031         smb_raw_exit(cli1->session);
2032         smb_raw_exit(cli2->session);
2033         smbcli_deltree(cli1->tree, BASEDIR);
2034         return ret;
2035 }
2036
2037 static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2038 {
2039         const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2040         const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2041         const char *fname3 = BASEDIR "\\test_batch19_3.dat";
2042         NTSTATUS status;
2043         bool ret = true;
2044         union smb_open io;
2045         union smb_fileinfo qfi;
2046         union smb_setfileinfo sfi;
2047         uint16_t fnum=0;
2048
2049         if (torture_setting_bool(tctx, "samba3", false)) {
2050                 torture_skip(tctx, "BACHT19 disabled against samba3\n");
2051         }
2052
2053         if (!torture_setup_dir(cli1, BASEDIR)) {
2054                 return false;
2055         }
2056
2057         /* cleanup */
2058         smbcli_unlink(cli1->tree, fname1);
2059         smbcli_unlink(cli1->tree, fname2);
2060         smbcli_unlink(cli1->tree, fname3);
2061
2062         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2063
2064         /*
2065           base ntcreatex parms
2066         */
2067         io.generic.level = RAW_OPEN_NTCREATEX;
2068         io.ntcreatex.in.root_fid = 0;
2069         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2070         io.ntcreatex.in.alloc_size = 0;
2071         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2072         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2073         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2074         io.ntcreatex.in.create_options = 0;
2075         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2076         io.ntcreatex.in.security_flags = 0;
2077         io.ntcreatex.in.fname = fname1;
2078
2079         torture_comment(tctx, "open a file with an batch oplock (share mode: none)\n");
2080         ZERO_STRUCT(break_info);
2081         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2082                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2083                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2084         status = smb_raw_open(cli1->tree, tctx, &io);
2085         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2086         fnum = io.ntcreatex.out.file.fnum;
2087         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2088
2089         torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2090         ZERO_STRUCT(sfi);
2091         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2092         sfi.generic.in.file.path = fname1;
2093         sfi.rename_information.in.overwrite     = 0;
2094         sfi.rename_information.in.root_fid      = 0;
2095         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2096
2097         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2098
2099         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2100         CHECK_VAL(break_info.count, 0);
2101
2102         ZERO_STRUCT(qfi);
2103         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2104         qfi.generic.in.file.fnum = fnum;
2105
2106         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2107         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2108         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2109
2110         torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2111         ZERO_STRUCT(sfi);
2112         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2113         sfi.generic.in.file.fnum = fnum;
2114         sfi.rename_information.in.overwrite     = 0;
2115         sfi.rename_information.in.root_fid      = 0;
2116         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2117
2118         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2119         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2120         CHECK_VAL(break_info.count, 0);
2121
2122         ZERO_STRUCT(qfi);
2123         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2124         qfi.generic.in.file.fnum = fnum;
2125
2126         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2127         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2128         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2129
2130         smbcli_close(cli1->tree, fnum);
2131
2132 done:
2133         smb_raw_exit(cli1->session);
2134         smb_raw_exit(cli2->session);
2135         smbcli_deltree(cli1->tree, BASEDIR);
2136         return ret;
2137 }
2138
2139 static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2140 {
2141         const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2142         const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2143         const char *fname3 = BASEDIR "\\test_batch20_3.dat";
2144         NTSTATUS status;
2145         bool ret = true;
2146         union smb_open io;
2147         union smb_fileinfo qfi;
2148         union smb_setfileinfo sfi;
2149         uint16_t fnum=0,fnum2=0;
2150
2151         if (torture_setting_bool(tctx, "samba3", false)) {
2152                 torture_skip(tctx, "BACHT20 disabled against samba3\n");
2153         }
2154
2155         if (!torture_setup_dir(cli1, BASEDIR)) {
2156                 return false;
2157         }
2158
2159         /* cleanup */
2160         smbcli_unlink(cli1->tree, fname1);
2161         smbcli_unlink(cli1->tree, fname2);
2162         smbcli_unlink(cli1->tree, fname3);
2163
2164         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2165
2166         /*
2167           base ntcreatex parms
2168         */
2169         io.generic.level = RAW_OPEN_NTCREATEX;
2170         io.ntcreatex.in.root_fid = 0;
2171         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2172         io.ntcreatex.in.alloc_size = 0;
2173         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2174         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2175         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2176         io.ntcreatex.in.create_options = 0;
2177         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2178         io.ntcreatex.in.security_flags = 0;
2179         io.ntcreatex.in.fname = fname1;
2180
2181         torture_comment(tctx, "open a file with an batch oplock (share mode: all)\n");
2182         ZERO_STRUCT(break_info);
2183         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2184                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2185                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2186         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2187                 NTCREATEX_SHARE_ACCESS_WRITE|
2188                 NTCREATEX_SHARE_ACCESS_DELETE;
2189         status = smb_raw_open(cli1->tree, tctx, &io);
2190         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2191         fnum = io.ntcreatex.out.file.fnum;
2192         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2193
2194         torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2195         ZERO_STRUCT(sfi);
2196         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2197         sfi.generic.in.file.path = fname1;
2198         sfi.rename_information.in.overwrite     = 0;
2199         sfi.rename_information.in.root_fid      = 0;
2200         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2201
2202         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2203
2204         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2205         CHECK_VAL(break_info.count, 0);
2206
2207         ZERO_STRUCT(qfi);
2208         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2209         qfi.generic.in.file.fnum = fnum;
2210
2211         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2212         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2213         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2214
2215         /* we should use no share mode, when samba3 passes this */
2216         torture_comment(tctx, "open a file with the new name an batch oplock (share mode: all)\n");
2217         ZERO_STRUCT(break_info);
2218         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2219                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2220                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2221         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2222                 NTCREATEX_SHARE_ACCESS_WRITE|
2223                 NTCREATEX_SHARE_ACCESS_DELETE;
2224         io.ntcreatex.in.fname = fname2;
2225         status = smb_raw_open(cli2->tree, tctx, &io);
2226         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2227         fnum2 = io.ntcreatex.out.file.fnum;
2228         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2229         CHECK_VAL(break_info.count, 1);
2230         CHECK_VAL(break_info.failures, 0);
2231         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2232
2233         torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2234         ZERO_STRUCT(sfi);
2235         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2236         sfi.generic.in.file.fnum = fnum;
2237         sfi.rename_information.in.overwrite     = 0;
2238         sfi.rename_information.in.root_fid      = 0;
2239         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2240
2241         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2242         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2243         CHECK_VAL(break_info.count, 1);
2244         CHECK_VAL(break_info.failures, 0);
2245         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2246
2247         ZERO_STRUCT(qfi);
2248         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2249         qfi.generic.in.file.fnum = fnum;
2250
2251         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2252         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2253         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2254
2255         ZERO_STRUCT(qfi);
2256         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2257         qfi.generic.in.file.fnum = fnum2;
2258
2259         status = smb_raw_fileinfo(cli2->tree, tctx, &qfi);
2260         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2261         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2262
2263         smbcli_close(cli1->tree, fnum);
2264
2265 done:
2266         smb_raw_exit(cli1->session);
2267         smb_raw_exit(cli2->session);
2268         smbcli_deltree(cli1->tree, BASEDIR);
2269         return ret;
2270 }
2271
2272 static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2273 {
2274         const char *fname = BASEDIR "\\test_batch21.dat";
2275         NTSTATUS status;
2276         bool ret = true;
2277         union smb_open io;
2278         struct smb_echo e;
2279         uint16_t fnum=0;
2280         char c = 0;
2281         ssize_t wr;
2282
2283         if (!torture_setup_dir(cli1, BASEDIR)) {
2284                 return false;
2285         }
2286
2287         /* cleanup */
2288         smbcli_unlink(cli1->tree, fname);
2289
2290         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2291
2292         /*
2293           base ntcreatex parms
2294         */
2295         io.generic.level = RAW_OPEN_NTCREATEX;
2296         io.ntcreatex.in.root_fid = 0;
2297         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2298         io.ntcreatex.in.alloc_size = 0;
2299         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2300         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2301         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2302         io.ntcreatex.in.create_options = 0;
2303         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2304         io.ntcreatex.in.security_flags = 0;
2305         io.ntcreatex.in.fname = fname;
2306
2307         /*
2308           with a batch oplock we get a break
2309         */
2310         torture_comment(tctx, "open with batch oplock\n");
2311         ZERO_STRUCT(break_info);
2312         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2313                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2314                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2315         status = smb_raw_open(cli1->tree, tctx, &io);
2316         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2317         fnum = io.ntcreatex.out.file.fnum;
2318         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2319
2320         torture_comment(tctx, "writing should not generate a break\n");
2321         wr = smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
2322         CHECK_VAL(wr, 1);
2323         CHECK_STATUS(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_OK);
2324
2325         ZERO_STRUCT(e);
2326         e.in.repeat_count = 1;
2327         status = smb_raw_echo(cli1->transport, &e);
2328         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2329
2330         CHECK_VAL(break_info.count, 0);
2331
2332         smbcli_close(cli1->tree, fnum);
2333
2334 done:
2335         smb_raw_exit(cli1->session);
2336         smb_raw_exit(cli2->session);
2337         smbcli_deltree(cli1->tree, BASEDIR);
2338         return ret;
2339 }
2340
2341 static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2342 {
2343         const char *fname = BASEDIR "\\test_batch22.dat";
2344         NTSTATUS status;
2345         bool ret = true;
2346         union smb_open io;
2347         uint16_t fnum=0, fnum2=0;
2348         struct timeval tv;
2349         int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2350         int te;
2351
2352         if (torture_setting_bool(tctx, "samba3", false)) {
2353                 torture_skip(tctx, "BACHT22 disabled against samba3\n");
2354         }
2355
2356         if (!torture_setup_dir(cli1, BASEDIR)) {
2357                 return false;
2358         }
2359
2360         /* cleanup */
2361         smbcli_unlink(cli1->tree, fname);
2362
2363         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2364
2365         /*
2366           base ntcreatex parms
2367         */
2368         io.generic.level = RAW_OPEN_NTCREATEX;
2369         io.ntcreatex.in.root_fid = 0;
2370         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2371         io.ntcreatex.in.alloc_size = 0;
2372         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2373         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2374         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2375         io.ntcreatex.in.create_options = 0;
2376         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2377         io.ntcreatex.in.security_flags = 0;
2378         io.ntcreatex.in.fname = fname;
2379
2380         /*
2381           with a batch oplock we get a break
2382         */
2383         torture_comment(tctx, "open with batch oplock\n");
2384         ZERO_STRUCT(break_info);
2385         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2386                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2387                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2388         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2389                 NTCREATEX_SHARE_ACCESS_WRITE|
2390                 NTCREATEX_SHARE_ACCESS_DELETE;
2391         status = smb_raw_open(cli1->tree, tctx, &io);
2392         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2393         fnum = io.ntcreatex.out.file.fnum;
2394         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2395
2396         torture_comment(tctx, "a 2nd open shoud not succeed after the oplock break timeout\n");
2397         tv = timeval_current();
2398         smbcli_oplock_handler(cli1->transport, oplock_handler_timeout, cli1->tree);
2399         status = smb_raw_open(cli1->tree, tctx, &io);
2400         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2401         te = (int)timeval_elapsed(&tv);
2402         CHECK_RANGE(te, timeout - 1, timeout + 15);
2403
2404         CHECK_VAL(break_info.count, 1);
2405         CHECK_VAL(break_info.fnum, fnum);
2406         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2407         CHECK_VAL(break_info.failures, 0);
2408         ZERO_STRUCT(break_info);
2409
2410         torture_comment(tctx, "a 2nd open shoud succeed after the oplock release without break\n");
2411         tv = timeval_current();
2412         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2413         status = smb_raw_open(cli1->tree, tctx, &io);
2414         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2415         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2416         te = (int)timeval_elapsed(&tv);
2417         /* it should come in without delay */
2418         CHECK_RANGE(te+1, 0, timeout);
2419         fnum2 = io.ntcreatex.out.file.fnum;
2420
2421         CHECK_VAL(break_info.count, 0);
2422
2423         smbcli_close(cli1->tree, fnum);
2424         smbcli_close(cli1->tree, fnum2);
2425
2426 done:
2427         smb_raw_exit(cli1->session);
2428         smb_raw_exit(cli2->session);
2429         smbcli_deltree(cli1->tree, BASEDIR);
2430         return ret;
2431 }
2432
2433 static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2434 {
2435         const char *fname = BASEDIR "\\test_batch23.dat";
2436         NTSTATUS status;
2437         bool ret = true;
2438         union smb_open io;
2439         uint16_t fnum=0, fnum2=0,fnum3=0;
2440         struct smbcli_state *cli3 = NULL;
2441
2442         if (torture_setting_bool(tctx, "samba3", false)) {
2443                 torture_skip(tctx, "BACHT23 disabled against samba3\n");
2444         }
2445
2446         if (!torture_setup_dir(cli1, BASEDIR)) {
2447                 return false;
2448         }
2449
2450         /* cleanup */
2451         smbcli_unlink(cli1->tree, fname);
2452
2453         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2454
2455         ret = open_connection_no_level2_oplocks(tctx, &cli3);
2456         CHECK_VAL(ret, true);
2457
2458         /*
2459           base ntcreatex parms
2460         */
2461         io.generic.level = RAW_OPEN_NTCREATEX;
2462         io.ntcreatex.in.root_fid = 0;
2463         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2464         io.ntcreatex.in.alloc_size = 0;
2465         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2466         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2467         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2468         io.ntcreatex.in.create_options = 0;
2469         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2470         io.ntcreatex.in.security_flags = 0;
2471         io.ntcreatex.in.fname = fname;
2472
2473         torture_comment(tctx, "a open and ask for a batch oplock\n");
2474         ZERO_STRUCT(break_info);
2475         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2476         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2477         smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
2478
2479         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
2480         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2481         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2482                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2483                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2484         status = smb_raw_open(cli1->tree, tctx, &io);
2485         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2486         fnum = io.ntcreatex.out.file.fnum;
2487         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2488
2489         ZERO_STRUCT(break_info);
2490
2491         torture_comment(tctx, "a 2nd open without level2 oplock support should generate a break to level2\n");
2492         status = smb_raw_open(cli3->tree, tctx, &io);
2493         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2494         fnum3 = io.ntcreatex.out.file.fnum;
2495         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
2496
2497         CHECK_VAL(break_info.count, 1);
2498         CHECK_VAL(break_info.fnum, fnum);
2499         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2500         CHECK_VAL(break_info.failures, 0);
2501
2502         ZERO_STRUCT(break_info);
2503
2504         torture_comment(tctx, "a 3rd open with level2 oplock support should not generate a break\n");
2505         status = smb_raw_open(cli2->tree, tctx, &io);
2506         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2507         fnum2 = io.ntcreatex.out.file.fnum;
2508         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2509
2510         CHECK_VAL(break_info.count, 0);
2511
2512         smbcli_close(cli1->tree, fnum);
2513         smbcli_close(cli2->tree, fnum2);
2514         smbcli_close(cli3->tree, fnum3);
2515
2516 done:
2517         smb_raw_exit(cli1->session);
2518         smb_raw_exit(cli2->session);
2519         smb_raw_exit(cli3->session);
2520         smbcli_deltree(cli1->tree, BASEDIR);
2521         return ret;
2522 }
2523
2524 static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2525 {
2526         const char *fname = BASEDIR "\\test_batch24.dat";
2527         NTSTATUS status;
2528         bool ret = true;
2529         union smb_open io;
2530         uint16_t fnum2=0,fnum3=0;
2531         struct smbcli_state *cli3 = NULL;
2532
2533         if (!torture_setup_dir(cli1, BASEDIR)) {
2534                 return false;
2535         }
2536
2537         /* cleanup */
2538         smbcli_unlink(cli1->tree, fname);
2539
2540         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2541
2542         ret = open_connection_no_level2_oplocks(tctx, &cli3);
2543         CHECK_VAL(ret, true);
2544
2545         /*
2546           base ntcreatex parms
2547         */
2548         io.generic.level = RAW_OPEN_NTCREATEX;
2549         io.ntcreatex.in.root_fid = 0;
2550         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2551         io.ntcreatex.in.alloc_size = 0;
2552         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2553         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2554         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2555         io.ntcreatex.in.create_options = 0;
2556         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2557         io.ntcreatex.in.security_flags = 0;
2558         io.ntcreatex.in.fname = fname;
2559
2560         torture_comment(tctx, "a open without level support and ask for a batch oplock\n");
2561         ZERO_STRUCT(break_info);
2562         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2563         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2564         smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
2565
2566         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
2567         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2568         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2569                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2570                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2571         status = smb_raw_open(cli3->tree, tctx, &io);
2572         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2573         fnum3 = io.ntcreatex.out.file.fnum;
2574         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2575
2576         ZERO_STRUCT(break_info);
2577
2578         torture_comment(tctx, "a 2nd open with level2 oplock support should generate a break to none\n");
2579         status = smb_raw_open(cli2->tree, tctx, &io);
2580         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2581         fnum2 = io.ntcreatex.out.file.fnum;
2582         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2583
2584         CHECK_VAL(break_info.count, 1);
2585         CHECK_VAL(break_info.fnum, fnum3);
2586         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2587         CHECK_VAL(break_info.failures, 0);
2588
2589         smbcli_close(cli3->tree, fnum3);
2590         smbcli_close(cli2->tree, fnum2);
2591
2592 done:
2593         smb_raw_exit(cli1->session);
2594         smb_raw_exit(cli2->session);
2595         smb_raw_exit(cli3->session);
2596         smbcli_deltree(cli1->tree, BASEDIR);
2597         return ret;
2598 }
2599
2600 /* 
2601    basic testing of oplocks
2602 */
2603 struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
2604 {
2605         struct torture_suite *suite = torture_suite_create(mem_ctx, "OPLOCK");
2606
2607         torture_suite_add_2smb_test(suite, "EXCLUSIVE1", test_raw_oplock_exclusive1);
2608         torture_suite_add_2smb_test(suite, "EXCLUSIVE2", test_raw_oplock_exclusive2);
2609         torture_suite_add_2smb_test(suite, "EXCLUSIVE3", test_raw_oplock_exclusive3);
2610         torture_suite_add_2smb_test(suite, "EXCLUSIVE4", test_raw_oplock_exclusive4);
2611         torture_suite_add_2smb_test(suite, "EXCLUSIVE5", test_raw_oplock_exclusive5);
2612         torture_suite_add_2smb_test(suite, "EXCLUSIVE6", test_raw_oplock_exclusive6);
2613         torture_suite_add_2smb_test(suite, "BATCH1", test_raw_oplock_batch1);
2614         torture_suite_add_2smb_test(suite, "BATCH2", test_raw_oplock_batch2);
2615         torture_suite_add_2smb_test(suite, "BATCH3", test_raw_oplock_batch3);
2616         torture_suite_add_2smb_test(suite, "BATCH4", test_raw_oplock_batch4);
2617         torture_suite_add_2smb_test(suite, "BATCH5", test_raw_oplock_batch5);
2618         torture_suite_add_2smb_test(suite, "BATCH6", test_raw_oplock_batch6);
2619         torture_suite_add_2smb_test(suite, "BATCH7", test_raw_oplock_batch7);
2620         torture_suite_add_2smb_test(suite, "BATCH8", test_raw_oplock_batch8);
2621         torture_suite_add_2smb_test(suite, "BATCH9", test_raw_oplock_batch9);
2622         torture_suite_add_2smb_test(suite, "BATCH10", test_raw_oplock_batch10);
2623         torture_suite_add_2smb_test(suite, "BATCH11", test_raw_oplock_batch11);
2624         torture_suite_add_2smb_test(suite, "BATCH12", test_raw_oplock_batch12);
2625         torture_suite_add_2smb_test(suite, "BATCH13", test_raw_oplock_batch13);
2626         torture_suite_add_2smb_test(suite, "BATCH14", test_raw_oplock_batch14);
2627         torture_suite_add_2smb_test(suite, "BATCH15", test_raw_oplock_batch15);
2628         torture_suite_add_2smb_test(suite, "BATCH16", test_raw_oplock_batch16);
2629         torture_suite_add_2smb_test(suite, "BATCH17", test_raw_oplock_batch17);
2630         torture_suite_add_2smb_test(suite, "BATCH18", test_raw_oplock_batch18);
2631         torture_suite_add_2smb_test(suite, "BATCH19", test_raw_oplock_batch19);
2632         torture_suite_add_2smb_test(suite, "BATCH20", test_raw_oplock_batch20);
2633         torture_suite_add_2smb_test(suite, "BATCH21", test_raw_oplock_batch21);
2634         torture_suite_add_2smb_test(suite, "BATCH22", test_raw_oplock_batch22);
2635         torture_suite_add_2smb_test(suite, "BATCH23", test_raw_oplock_batch23);
2636         torture_suite_add_2smb_test(suite, "BATCH24", test_raw_oplock_batch24);
2637
2638         return suite;
2639 }
2640
2641 /* 
2642    stress testing of oplocks
2643 */
2644 bool torture_bench_oplock(struct torture_context *torture)
2645 {
2646         struct smbcli_state **cli;
2647         bool ret = true;
2648         TALLOC_CTX *mem_ctx = talloc_new(torture);
2649         int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
2650         int i, count=0;
2651         int timelimit = torture_setting_int(torture, "timelimit", 10);
2652         union smb_open io;
2653         struct timeval tv;
2654         struct event_context *ev = event_context_find(mem_ctx);
2655
2656         cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
2657
2658         torture_comment(torture, "Opening %d connections\n", torture_nprocs);
2659         for (i=0;i<torture_nprocs;i++) {
2660                 if (!torture_open_connection_ev(&cli[i], i, torture, ev)) {
2661                         return false;
2662                 }
2663                 talloc_steal(mem_ctx, cli[i]);
2664                 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close, 
2665                                       cli[i]->tree);
2666         }
2667
2668         if (!torture_setup_dir(cli[0], BASEDIR)) {
2669                 ret = false;
2670                 goto done;
2671         }
2672
2673         io.ntcreatex.level = RAW_OPEN_NTCREATEX;
2674         io.ntcreatex.in.root_fid = 0;
2675         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2676         io.ntcreatex.in.alloc_size = 0;
2677         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2678         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2679         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2680         io.ntcreatex.in.create_options = 0;
2681         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2682         io.ntcreatex.in.security_flags = 0;
2683         io.ntcreatex.in.fname = BASEDIR "\\test.dat";
2684         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
2685                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
2686                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2687
2688         tv = timeval_current(); 
2689
2690         /*
2691           we open the same file with SHARE_ACCESS_NONE from all the
2692           connections in a round robin fashion. Each open causes an
2693           oplock break on the previous connection, which is answered
2694           by the oplock_handler_close() to close the file.
2695
2696           This measures how fast we can pass on oplocks, and stresses
2697           the oplock handling code
2698         */
2699         torture_comment(torture, "Running for %d seconds\n", timelimit);
2700         while (timeval_elapsed(&tv) < timelimit) {
2701                 for (i=0;i<torture_nprocs;i++) {
2702                         NTSTATUS status;
2703
2704                         status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
2705                         CHECK_STATUS(torture, status, NT_STATUS_OK);
2706                         count++;
2707                 }
2708
2709                 if (torture_setting_bool(torture, "progress", true)) {
2710                         torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
2711                 }
2712         }
2713
2714         torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
2715
2716         smb_raw_exit(cli[torture_nprocs-1]->session);
2717         
2718 done:
2719         smb_raw_exit(cli[0]->session);
2720         smbcli_deltree(cli[0]->tree, BASEDIR);
2721         talloc_free(mem_ctx);
2722         return ret;
2723 }
2724
2725
2726 static struct hold_oplock_info {
2727         const char *fname;
2728         bool close_on_break;
2729         uint32_t share_access;
2730         uint16_t fnum;
2731 } hold_info[] = {
2732         { BASEDIR "\\notshared_close", true,  
2733           NTCREATEX_SHARE_ACCESS_NONE, },
2734         { BASEDIR "\\notshared_noclose", false, 
2735           NTCREATEX_SHARE_ACCESS_NONE, },
2736         { BASEDIR "\\shared_close", true,  
2737           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
2738         { BASEDIR "\\shared_noclose", false,  
2739           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
2740 };
2741
2742 static bool oplock_handler_hold(struct smbcli_transport *transport, 
2743                                 uint16_t tid, uint16_t fnum, uint8_t level, 
2744                                 void *private)
2745 {
2746         struct smbcli_tree *tree = (struct smbcli_tree *)private;
2747         struct hold_oplock_info *info;
2748         int i;
2749
2750         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
2751                 if (hold_info[i].fnum == fnum) break;
2752         }
2753
2754         if (i == ARRAY_SIZE(hold_info)) {
2755                 printf("oplock break for unknown fnum %u\n", fnum);
2756                 return false;
2757         }
2758
2759         info = &hold_info[i];
2760
2761         if (info->close_on_break) {
2762                 printf("oplock break on %s - closing\n",
2763                        info->fname);
2764                 oplock_handler_close(transport, tid, fnum, level, private);
2765                 return true;
2766         }
2767
2768         printf("oplock break on %s - acking break\n", info->fname);
2769
2770         return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
2771 }
2772
2773
2774 /* 
2775    used for manual testing of oplocks - especially interaction with
2776    other filesystems (such as NFS and local access)
2777 */
2778 bool torture_hold_oplock(struct torture_context *torture, 
2779                          struct smbcli_state *cli)
2780 {
2781         struct event_context *ev = 
2782                 (struct event_context *)cli->transport->socket->event.ctx;
2783         int i;
2784
2785         printf("Setting up open files with oplocks in %s\n", BASEDIR);
2786
2787         if (!torture_setup_dir(cli, BASEDIR)) {
2788                 return false;
2789         }
2790
2791         smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
2792
2793         /* setup the files */
2794         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
2795                 union smb_open io;
2796                 NTSTATUS status;
2797                 char c = 1;
2798
2799                 io.generic.level = RAW_OPEN_NTCREATEX;
2800                 io.ntcreatex.in.root_fid = 0;
2801                 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2802                 io.ntcreatex.in.alloc_size = 0;
2803                 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2804                 io.ntcreatex.in.share_access = hold_info[i].share_access;
2805                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2806                 io.ntcreatex.in.create_options = 0;
2807                 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2808                 io.ntcreatex.in.security_flags = 0;
2809                 io.ntcreatex.in.fname = hold_info[i].fname;
2810                 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
2811                         NTCREATEX_FLAGS_REQUEST_OPLOCK |
2812                         NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2813                 printf("opening %s\n", hold_info[i].fname);
2814
2815                 status = smb_raw_open(cli->tree, cli, &io);
2816                 if (!NT_STATUS_IS_OK(status)) {
2817                         printf("Failed to open %s - %s\n", 
2818                                hold_info[i].fname, nt_errstr(status));
2819                         return false;
2820                 }
2821
2822                 if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
2823                         printf("Oplock not granted for %s - expected %d but got %d\n", 
2824                                hold_info[i].fname, BATCH_OPLOCK_RETURN, 
2825                                 io.ntcreatex.out.oplock_level);
2826                         return false;
2827                 }
2828                 hold_info[i].fnum = io.ntcreatex.out.file.fnum;
2829
2830                 /* make the file non-zero size */
2831                 if (smbcli_write(cli->tree, hold_info[i].fnum, 0, &c, 0, 1) != 1) {
2832                         printf("Failed to write to file\n");
2833                         return false;
2834                 }
2835         }
2836
2837         printf("Waiting for oplock events\n");
2838         event_loop_wait(ev);
2839
2840         return true;
2841 }