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