r25554: Convert last instances of BOOL, True and False to the standard types.
[samba.git] / source4 / torture / raw / oplock.c
1 /* 
2    Unix SMB/CIFS implementation.
3    basic raw test suite for oplocks
4    Copyright (C) Andrew Tridgell 2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "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_comment(tctx, "(%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_STATUS(tctx, status, correct) do { \
36         if (!NT_STATUS_EQUAL(status, correct)) { \
37                 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
38                        nt_errstr(status), nt_errstr(correct)); \
39                 ret = false; \
40                 goto done; \
41         }} while (0)
42
43
44 static struct {
45         int fnum;
46         uint8_t level;
47         int count;
48         int failures;
49 } break_info;
50
51 #define BASEDIR "\\test_oplock"
52
53 /*
54   a handler function for oplock break requests. Ack it as a break to level II if possible
55 */
56 static bool oplock_handler_ack_to_levelII(struct smbcli_transport *transport, 
57                                           uint16_t tid, uint16_t fnum, 
58                                           uint8_t level, void *private)
59 {
60         struct smbcli_tree *tree = (struct smbcli_tree *)private;
61         break_info.fnum = fnum;
62         break_info.level = level;
63         break_info.count++;
64
65         printf("Acking to level II in oplock handler\n");
66
67         return smbcli_oplock_ack(tree, fnum, level);
68 }
69
70 /*
71   a handler function for oplock break requests. Ack it as a break to none
72 */
73 static bool oplock_handler_ack_to_none(struct smbcli_transport *transport, 
74                                        uint16_t tid, uint16_t fnum, 
75                                        uint8_t level, void *private)
76 {
77         struct smbcli_tree *tree = (struct smbcli_tree *)private;
78         break_info.fnum = fnum;
79         break_info.level = level;
80         break_info.count++;
81
82         printf("Acking to none in oplock handler\n");
83
84         return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
85 }
86
87 static void oplock_handler_close_recv(struct smbcli_request *req)
88 {
89         NTSTATUS status;
90         status = smbcli_request_simple_recv(req);
91         if (!NT_STATUS_IS_OK(status)) {
92                 printf("close failed in oplock_handler_close\n");
93                 break_info.failures++;
94         }
95 }
96
97 /*
98   a handler function for oplock break requests - close the file
99 */
100 static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t tid, 
101                                  uint16_t fnum, uint8_t level, void *private)
102 {
103         union smb_close io;
104         struct smbcli_tree *tree = (struct smbcli_tree *)private;
105         struct smbcli_request *req;
106
107         break_info.fnum = fnum;
108         break_info.level = level;
109         break_info.count++;
110
111         io.close.level = RAW_CLOSE_CLOSE;
112         io.close.in.file.fnum = fnum;
113         io.close.in.write_time = 0;
114         req = smb_raw_close_send(tree, &io);
115         if (req == NULL) {
116                 printf("failed to send close in oplock_handler_close\n");
117                 return false;
118         }
119
120         req->async.fn = oplock_handler_close_recv;
121         req->async.private = NULL;
122
123         return true;
124 }
125
126 static bool test_raw_oplock_normal(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
127 {
128         const char *fname = BASEDIR "\\test_normal.dat";
129         NTSTATUS status;
130         bool ret = true;
131         union smb_open io;
132         union smb_unlink unl;
133         uint16_t fnum=0;
134
135         if (!torture_setup_dir(cli1, BASEDIR)) {
136                 return false;
137         }
138
139         /* cleanup */
140         smbcli_unlink(cli1->tree, fname);
141
142         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
143
144         /*
145           base ntcreatex parms
146         */
147         io.generic.level = RAW_OPEN_NTCREATEX;
148         io.ntcreatex.in.root_fid = 0;
149         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
150         io.ntcreatex.in.alloc_size = 0;
151         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
152         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
153         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
154         io.ntcreatex.in.create_options = 0;
155         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
156         io.ntcreatex.in.security_flags = 0;
157         io.ntcreatex.in.fname = fname;
158
159         torture_comment(tctx, "open a file with a normal oplock\n");
160         ZERO_STRUCT(break_info);
161         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
162
163         status = smb_raw_open(cli1->tree, tctx, &io);
164         CHECK_STATUS(tctx, status, NT_STATUS_OK);
165         fnum = io.ntcreatex.out.file.fnum;
166         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
167
168         torture_comment(tctx, "a 2nd open should not cause a break\n");
169         status = smb_raw_open(cli2->tree, tctx, &io);
170         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
171         CHECK_VAL(break_info.count, 0);
172         CHECK_VAL(break_info.failures, 0);
173
174         torture_comment(tctx, "unlink it - should also be no break\n");
175         unl.unlink.in.pattern = fname;
176         unl.unlink.in.attrib = 0;
177         status = smb_raw_unlink(cli2->tree, &unl);
178         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
179         CHECK_VAL(break_info.count, 0);
180         CHECK_VAL(break_info.failures, 0);
181
182         smbcli_close(cli1->tree, fnum);
183
184 done:
185         smb_raw_exit(cli1->session);
186         smb_raw_exit(cli2->session);
187         smbcli_deltree(cli1->tree, BASEDIR);
188         return ret;
189 }
190
191 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
192 {
193         const char *fname = BASEDIR "\\test_batch1.dat";
194         NTSTATUS status;
195         bool ret = true;
196         union smb_open io;
197         union smb_unlink unl;
198         uint16_t fnum=0;
199         char c = 0;
200
201         if (!torture_setup_dir(cli1, BASEDIR)) {
202                 return false;
203         }
204
205         /* cleanup */
206         smbcli_unlink(cli1->tree, fname);
207
208         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
209
210         /*
211           base ntcreatex parms
212         */
213         io.generic.level = RAW_OPEN_NTCREATEX;
214         io.ntcreatex.in.root_fid = 0;
215         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
216         io.ntcreatex.in.alloc_size = 0;
217         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
218         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
219         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
220         io.ntcreatex.in.create_options = 0;
221         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
222         io.ntcreatex.in.security_flags = 0;
223         io.ntcreatex.in.fname = fname;
224
225         /*
226           with a batch oplock we get a break
227         */
228         torture_comment(tctx, "open with batch oplock\n");
229         ZERO_STRUCT(break_info);
230         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
231                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
232                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
233         status = smb_raw_open(cli1->tree, tctx, &io);
234         CHECK_STATUS(tctx, status, NT_STATUS_OK);
235         fnum = io.ntcreatex.out.file.fnum;
236         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
237
238         torture_comment(tctx, "unlink should generate a break\n");
239         unl.unlink.in.pattern = fname;
240         unl.unlink.in.attrib = 0;
241         status = smb_raw_unlink(cli2->tree, &unl);
242         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
243
244         CHECK_VAL(break_info.count, 1);
245         CHECK_VAL(break_info.fnum, fnum);
246         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
247         CHECK_VAL(break_info.failures, 0);
248
249         torture_comment(tctx, "2nd unlink should not generate a break\n");
250         ZERO_STRUCT(break_info);
251         status = smb_raw_unlink(cli2->tree, &unl);
252         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
253
254         CHECK_VAL(break_info.count, 0);
255
256         torture_comment(tctx, "writing should generate a self break to none\n");
257         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
258         msleep(100);
259         smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
260
261         CHECK_VAL(break_info.count, 1);
262         CHECK_VAL(break_info.fnum, fnum);
263         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
264         CHECK_VAL(break_info.failures, 0);
265
266         smbcli_close(cli1->tree, fnum);
267
268 done:
269         smb_raw_exit(cli1->session);
270         smb_raw_exit(cli2->session);
271         smbcli_deltree(cli1->tree, BASEDIR);
272         return ret;
273 }
274
275 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
276 {
277         const char *fname = BASEDIR "\\test_batch2.dat";
278         NTSTATUS status;
279         bool ret = true;
280         union smb_open io;
281         union smb_unlink unl;
282         uint16_t fnum=0;
283         char c = 0;
284
285         if (!torture_setup_dir(cli1, BASEDIR)) {
286                 return false;
287         }
288
289         /* cleanup */
290         smbcli_unlink(cli1->tree, fname);
291
292         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
293
294         /*
295           base ntcreatex parms
296         */
297         io.generic.level = RAW_OPEN_NTCREATEX;
298         io.ntcreatex.in.root_fid = 0;
299         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
300         io.ntcreatex.in.alloc_size = 0;
301         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
302         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
303         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
304         io.ntcreatex.in.create_options = 0;
305         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
306         io.ntcreatex.in.security_flags = 0;
307         io.ntcreatex.in.fname = fname;
308
309         torture_comment(tctx, "open with batch oplock\n");
310         ZERO_STRUCT(break_info);
311         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
312                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
313                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
314         status = smb_raw_open(cli1->tree, tctx, &io);
315         CHECK_STATUS(tctx, status, NT_STATUS_OK);
316         fnum = io.ntcreatex.out.file.fnum;
317         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
318
319         torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
320         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
321         unl.unlink.in.pattern = fname;
322         unl.unlink.in.attrib = 0;
323         status = smb_raw_unlink(cli2->tree, &unl);
324         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
325
326         CHECK_VAL(break_info.count, 1);
327         CHECK_VAL(break_info.fnum, fnum);
328         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
329         CHECK_VAL(break_info.failures, 0);
330
331         torture_comment(tctx, "2nd unlink should not generate a break\n");
332         ZERO_STRUCT(break_info);
333         status = smb_raw_unlink(cli2->tree, &unl);
334         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
335
336         CHECK_VAL(break_info.count, 0);
337
338         torture_comment(tctx, "writing should not generate a break\n");
339         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
340         msleep(100);
341         smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
342
343         CHECK_VAL(break_info.count, 0);
344
345         smbcli_close(cli1->tree, fnum);
346
347 done:
348         smb_raw_exit(cli1->session);
349         smb_raw_exit(cli2->session);
350         smbcli_deltree(cli1->tree, BASEDIR);
351         return ret;
352 }
353
354 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
355 {
356         const char *fname = BASEDIR "\\test_batch3.dat";
357         NTSTATUS status;
358         bool ret = true;
359         union smb_open io;
360         union smb_unlink unl;
361         uint16_t fnum=0;
362
363         if (!torture_setup_dir(cli1, BASEDIR)) {
364                 return false;
365         }
366
367         /* cleanup */
368         smbcli_unlink(cli1->tree, fname);
369
370         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
371
372         /*
373           base ntcreatex parms
374         */
375         io.generic.level = RAW_OPEN_NTCREATEX;
376         io.ntcreatex.in.root_fid = 0;
377         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
378         io.ntcreatex.in.alloc_size = 0;
379         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
380         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
381         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
382         io.ntcreatex.in.create_options = 0;
383         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
384         io.ntcreatex.in.security_flags = 0;
385         io.ntcreatex.in.fname = fname;
386
387         torture_comment(tctx, "if we close on break then the unlink can succeed\n");
388         ZERO_STRUCT(break_info);
389         smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
390         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
391                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
392                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
393         status = smb_raw_open(cli1->tree, tctx, &io);
394         CHECK_STATUS(tctx, status, NT_STATUS_OK);
395         fnum = io.ntcreatex.out.file.fnum;
396         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
397
398         unl.unlink.in.pattern = fname;
399         unl.unlink.in.attrib = 0;
400         ZERO_STRUCT(break_info);
401         status = smb_raw_unlink(cli2->tree, &unl);
402         CHECK_STATUS(tctx, status, NT_STATUS_OK);
403
404         CHECK_VAL(break_info.count, 1);
405         CHECK_VAL(break_info.fnum, fnum);
406         CHECK_VAL(break_info.level, 1);
407         CHECK_VAL(break_info.failures, 0);
408
409         smbcli_close(cli1->tree, fnum);
410
411 done:
412         smb_raw_exit(cli1->session);
413         smb_raw_exit(cli2->session);
414         smbcli_deltree(cli1->tree, BASEDIR);
415         return ret;
416 }
417
418 static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
419 {
420         const char *fname = BASEDIR "\\test_batch4.dat";
421         NTSTATUS status;
422         bool ret = true;
423         union smb_open io;
424         union smb_read rd;
425         uint16_t fnum=0;
426
427         if (!torture_setup_dir(cli1, BASEDIR)) {
428                 return false;
429         }
430
431         /* cleanup */
432         smbcli_unlink(cli1->tree, fname);
433
434         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
435
436         /*
437           base ntcreatex parms
438         */
439         io.generic.level = RAW_OPEN_NTCREATEX;
440         io.ntcreatex.in.root_fid = 0;
441         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
442         io.ntcreatex.in.alloc_size = 0;
443         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
444         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
445         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
446         io.ntcreatex.in.create_options = 0;
447         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
448         io.ntcreatex.in.security_flags = 0;
449         io.ntcreatex.in.fname = fname;
450
451         torture_comment(tctx, "a self read should not cause a break\n");
452         ZERO_STRUCT(break_info);
453         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
454
455         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
456                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
457                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
458         status = smb_raw_open(cli1->tree, tctx, &io);
459         CHECK_STATUS(tctx, status, NT_STATUS_OK);
460         fnum = io.ntcreatex.out.file.fnum;
461         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
462
463         rd.read.level = RAW_READ_READ;
464         rd.read.in.file.fnum = fnum;
465         rd.read.in.count = 1;
466         rd.read.in.offset = 0;
467         rd.read.in.remaining = 0;
468         status = smb_raw_read(cli1->tree, &rd);
469         CHECK_STATUS(tctx, status, NT_STATUS_OK);
470         CHECK_VAL(break_info.count, 0);
471         CHECK_VAL(break_info.failures, 0);
472
473         smbcli_close(cli1->tree, fnum);
474
475 done:
476         smb_raw_exit(cli1->session);
477         smb_raw_exit(cli2->session);
478         smbcli_deltree(cli1->tree, BASEDIR);
479         return ret;
480 }
481
482 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
483 {
484         const char *fname = BASEDIR "\\test_batch5.dat";
485         NTSTATUS status;
486         bool ret = true;
487         union smb_open io;
488         uint16_t fnum=0;
489
490         if (!torture_setup_dir(cli1, BASEDIR)) {
491                 return false;
492         }
493
494         /* cleanup */
495         smbcli_unlink(cli1->tree, fname);
496
497         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
498
499         /*
500           base ntcreatex parms
501         */
502         io.generic.level = RAW_OPEN_NTCREATEX;
503         io.ntcreatex.in.root_fid = 0;
504         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
505         io.ntcreatex.in.alloc_size = 0;
506         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
507         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
508         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
509         io.ntcreatex.in.create_options = 0;
510         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
511         io.ntcreatex.in.security_flags = 0;
512         io.ntcreatex.in.fname = fname;
513
514         torture_comment(tctx, "a 2nd open should give a break\n");
515         ZERO_STRUCT(break_info);
516         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
517
518         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
519                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
520                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
521         status = smb_raw_open(cli1->tree, tctx, &io);
522         CHECK_STATUS(tctx, status, NT_STATUS_OK);
523         fnum = io.ntcreatex.out.file.fnum;
524         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
525
526         ZERO_STRUCT(break_info);
527
528         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
529         status = smb_raw_open(cli2->tree, tctx, &io);
530         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
531
532         CHECK_VAL(break_info.count, 1);
533         CHECK_VAL(break_info.fnum, fnum);
534         CHECK_VAL(break_info.level, 1);
535         CHECK_VAL(break_info.failures, 0);
536
537         smbcli_close(cli1->tree, fnum);
538
539 done:
540         smb_raw_exit(cli1->session);
541         smb_raw_exit(cli2->session);
542         smbcli_deltree(cli1->tree, BASEDIR);
543         return ret;
544 }
545
546 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
547 {
548         const char *fname = BASEDIR "\\test_batch6.dat";
549         NTSTATUS status;
550         bool ret = true;
551         union smb_open io;
552         uint16_t fnum=0, fnum2=0;
553         char c = 0;
554
555         if (!torture_setup_dir(cli1, BASEDIR)) {
556                 return false;
557         }
558
559         /* cleanup */
560         smbcli_unlink(cli1->tree, fname);
561
562         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
563
564         /*
565           base ntcreatex parms
566         */
567         io.generic.level = RAW_OPEN_NTCREATEX;
568         io.ntcreatex.in.root_fid = 0;
569         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
570         io.ntcreatex.in.alloc_size = 0;
571         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
572         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
573         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
574         io.ntcreatex.in.create_options = 0;
575         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
576         io.ntcreatex.in.security_flags = 0;
577         io.ntcreatex.in.fname = fname;
578
579         torture_comment(tctx, "a 2nd open should give a break to level II if the first open allowed shared read\n");
580         ZERO_STRUCT(break_info);
581         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
582         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, cli2->tree);
583
584         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
585         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
586         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
587                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
588                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
589         status = smb_raw_open(cli1->tree, tctx, &io);
590         CHECK_STATUS(tctx, status, NT_STATUS_OK);
591         fnum = io.ntcreatex.out.file.fnum;
592         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
593
594         ZERO_STRUCT(break_info);
595
596         status = smb_raw_open(cli2->tree, tctx, &io);
597         CHECK_STATUS(tctx, status, NT_STATUS_OK);
598         fnum2 = io.ntcreatex.out.file.fnum;
599         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
600
601         CHECK_VAL(break_info.count, 1);
602         CHECK_VAL(break_info.fnum, fnum);
603         CHECK_VAL(break_info.level, 1);
604         CHECK_VAL(break_info.failures, 0);
605         ZERO_STRUCT(break_info);
606
607         torture_comment(tctx, "write should trigger a break to none on both\n");
608         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
609         msleep(100);
610         smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
611
612         CHECK_VAL(break_info.count, 2);
613         CHECK_VAL(break_info.level, 0);
614         CHECK_VAL(break_info.failures, 0);
615
616         smbcli_close(cli1->tree, fnum);
617         smbcli_close(cli2->tree, fnum2);
618
619
620 done:
621         smb_raw_exit(cli1->session);
622         smb_raw_exit(cli2->session);
623         smbcli_deltree(cli1->tree, BASEDIR);
624         return ret;
625 }
626
627 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
628 {
629         const char *fname = BASEDIR "\\test_batch7.dat";
630         NTSTATUS status;
631         bool ret = true;
632         union smb_open io;
633         uint16_t fnum=0, fnum2=0;
634
635         if (!torture_setup_dir(cli1, BASEDIR)) {
636                 return false;
637         }
638
639         /* cleanup */
640         smbcli_unlink(cli1->tree, fname);
641
642         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
643
644         /*
645           base ntcreatex parms
646         */
647         io.generic.level = RAW_OPEN_NTCREATEX;
648         io.ntcreatex.in.root_fid = 0;
649         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
650         io.ntcreatex.in.alloc_size = 0;
651         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
652         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
653         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
654         io.ntcreatex.in.create_options = 0;
655         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
656         io.ntcreatex.in.security_flags = 0;
657         io.ntcreatex.in.fname = fname;
658
659         torture_comment(tctx, "a 2nd open should get an oplock when we close instead of ack\n");
660         ZERO_STRUCT(break_info);
661         smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
662
663         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
664         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
665         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
666                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
667                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
668         status = smb_raw_open(cli1->tree, tctx, &io);
669         CHECK_STATUS(tctx, status, NT_STATUS_OK);
670         fnum2 = io.ntcreatex.out.file.fnum;
671         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
672
673         ZERO_STRUCT(break_info);
674
675         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
676                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
677                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
678         status = smb_raw_open(cli2->tree, tctx, &io);
679         CHECK_STATUS(tctx, status, NT_STATUS_OK);
680         fnum = io.ntcreatex.out.file.fnum;
681         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
682
683         CHECK_VAL(break_info.count, 1);
684         CHECK_VAL(break_info.fnum, fnum2);
685         CHECK_VAL(break_info.level, 1);
686         CHECK_VAL(break_info.failures, 0);
687         
688         smbcli_close(cli2->tree, fnum);
689
690 done:
691         smb_raw_exit(cli1->session);
692         smb_raw_exit(cli2->session);
693         smbcli_deltree(cli1->tree, BASEDIR);
694         return ret;
695 }
696
697 static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
698 {
699         const char *fname = BASEDIR "\\test_batch8.dat";
700         NTSTATUS status;
701         bool ret = true;
702         union smb_open io;
703         uint16_t fnum=0, fnum2=0;
704
705         if (!torture_setup_dir(cli1, BASEDIR)) {
706                 return false;
707         }
708
709         /* cleanup */
710         smbcli_unlink(cli1->tree, fname);
711
712         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
713
714         /*
715           base ntcreatex parms
716         */
717         io.generic.level = RAW_OPEN_NTCREATEX;
718         io.ntcreatex.in.root_fid = 0;
719         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
720         io.ntcreatex.in.alloc_size = 0;
721         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
722         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
723         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
724         io.ntcreatex.in.create_options = 0;
725         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
726         io.ntcreatex.in.security_flags = 0;
727         io.ntcreatex.in.fname = fname;
728
729         torture_comment(tctx, "open with batch oplock\n");
730         ZERO_STRUCT(break_info);
731         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
732
733         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
734                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
735                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
736         status = smb_raw_open(cli1->tree, tctx, &io);
737         CHECK_STATUS(tctx, status, NT_STATUS_OK);
738         fnum = io.ntcreatex.out.file.fnum;
739         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
740
741         ZERO_STRUCT(break_info);
742         torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
743
744         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
745                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
746                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
747         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
748         status = smb_raw_open(cli2->tree, tctx, &io);
749         CHECK_STATUS(tctx, status, NT_STATUS_OK);
750         fnum2 = io.ntcreatex.out.file.fnum;
751         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
752         CHECK_VAL(break_info.count, 0);
753         CHECK_VAL(break_info.failures, 0);
754
755         smbcli_close(cli1->tree, fnum);
756         smbcli_close(cli2->tree, fnum2);
757
758 done:
759         smb_raw_exit(cli1->session);
760         smb_raw_exit(cli2->session);
761         smbcli_deltree(cli1->tree, BASEDIR);
762         return ret;
763 }
764
765 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
766 {
767         const char *fname = BASEDIR "\\test_batch9.dat";
768         NTSTATUS status;
769         bool ret = true;
770         union smb_open io;
771         uint16_t fnum=0, fnum2=0;
772         char c = 0;
773
774         if (!torture_setup_dir(cli1, BASEDIR)) {
775                 return false;
776         }
777
778         /* cleanup */
779         smbcli_unlink(cli1->tree, fname);
780
781         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
782
783         /*
784           base ntcreatex parms
785         */
786         io.generic.level = RAW_OPEN_NTCREATEX;
787         io.ntcreatex.in.root_fid = 0;
788         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
789         io.ntcreatex.in.alloc_size = 0;
790         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
791         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
792         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
793         io.ntcreatex.in.create_options = 0;
794         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
795         io.ntcreatex.in.security_flags = 0;
796         io.ntcreatex.in.fname = fname;
797
798         torture_comment(tctx, "open with attributes only can create file\n");
799
800         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
801                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
802                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
803         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
804         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
805         status = smb_raw_open(cli1->tree, tctx, &io);
806         CHECK_STATUS(tctx, status, NT_STATUS_OK);
807         fnum = io.ntcreatex.out.file.fnum;
808         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
809
810         torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
811
812         ZERO_STRUCT(break_info);
813         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
814
815         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
816                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
817                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
818         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
819         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
820         status = smb_raw_open(cli2->tree, tctx, &io);
821         CHECK_STATUS(tctx, status, NT_STATUS_OK);
822         fnum2 = io.ntcreatex.out.file.fnum;
823         CHECK_VAL(break_info.count, 1);
824         CHECK_VAL(break_info.fnum, fnum);
825         CHECK_VAL(break_info.failures, 0);
826         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
827         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
828         smbcli_close(cli2->tree, fnum2);
829
830         torture_comment(tctx, "third oplocked open should grant level2 without break\n");
831         ZERO_STRUCT(break_info);
832         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
833         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, cli2->tree);
834         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
835                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
836                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
837         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
838         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
839         status = smb_raw_open(cli2->tree, tctx, &io);
840         CHECK_STATUS(tctx, status, NT_STATUS_OK);
841         fnum2 = io.ntcreatex.out.file.fnum;
842         CHECK_VAL(break_info.count, 0);
843         CHECK_VAL(break_info.failures, 0);
844         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
845
846         ZERO_STRUCT(break_info);
847
848         torture_comment(tctx, "write should trigger a break to none on both\n");
849         smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
850
851         /* Now the oplock break request comes in. But right now we can't
852          * answer it. Do another write */
853
854         msleep(100);
855         smbcli_write(cli2->tree, fnum2, 0, &c, 1, 1);
856
857         CHECK_VAL(break_info.count, 2);
858         CHECK_VAL(break_info.level, 0);
859         CHECK_VAL(break_info.failures, 0);
860
861         smbcli_close(cli1->tree, fnum);
862         smbcli_close(cli2->tree, fnum2);
863
864 done:
865         smb_raw_exit(cli1->session);
866         smb_raw_exit(cli2->session);
867         smbcli_deltree(cli1->tree, BASEDIR);
868         return ret;
869 }
870
871 static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
872 {
873         const char *fname = BASEDIR "\\test_batch10.dat";
874         NTSTATUS status;
875         bool ret = true;
876         union smb_open io;
877         uint16_t fnum=0, fnum2=0;
878
879         if (!torture_setup_dir(cli1, BASEDIR)) {
880                 return false;
881         }
882
883         /* cleanup */
884         smbcli_unlink(cli1->tree, fname);
885
886         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
887
888         /*
889           base ntcreatex parms
890         */
891         io.generic.level = RAW_OPEN_NTCREATEX;
892         io.ntcreatex.in.root_fid = 0;
893         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
894         io.ntcreatex.in.alloc_size = 0;
895         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
896         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
897         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
898         io.ntcreatex.in.create_options = 0;
899         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
900         io.ntcreatex.in.security_flags = 0;
901         io.ntcreatex.in.fname = fname;
902
903         torture_comment(tctx, "Open with oplock after a non-oplock open should grant level2\n");
904         ZERO_STRUCT(break_info);
905         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
906         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
907         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
908                 NTCREATEX_SHARE_ACCESS_WRITE|
909                 NTCREATEX_SHARE_ACCESS_DELETE;
910         status = smb_raw_open(cli1->tree, tctx, &io);
911         CHECK_STATUS(tctx, status, NT_STATUS_OK);
912         fnum = io.ntcreatex.out.file.fnum;
913         CHECK_VAL(break_info.count, 0);
914         CHECK_VAL(break_info.failures, 0);
915         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
916
917         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, cli1->tree);
918
919         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
920                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
921                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
922         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
923         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
924                 NTCREATEX_SHARE_ACCESS_WRITE|
925                 NTCREATEX_SHARE_ACCESS_DELETE;
926         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
927         status = smb_raw_open(cli2->tree, tctx, &io);
928         CHECK_STATUS(tctx, status, NT_STATUS_OK);
929         fnum2 = io.ntcreatex.out.file.fnum;
930         CHECK_VAL(break_info.count, 0);
931         CHECK_VAL(break_info.failures, 0);
932         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
933
934         torture_comment(tctx, "write should trigger a break to none\n");
935         {
936                 union smb_write wr;
937                 wr.write.level = RAW_WRITE_WRITE;
938                 wr.write.in.file.fnum = fnum;
939                 wr.write.in.count = 1;
940                 wr.write.in.offset = 0;
941                 wr.write.in.remaining = 0;
942                 wr.write.in.data = (const uint8_t *)"x";
943                 status = smb_raw_write(cli1->tree, &wr);
944                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
945         }
946
947         /* Now the oplock break request comes in. But right now we can't
948          * answer it. Do another write */
949
950         msleep(100);
951         
952         {
953                 union smb_write wr;
954                 wr.write.level = RAW_WRITE_WRITE;
955                 wr.write.in.file.fnum = fnum;
956                 wr.write.in.count = 1;
957                 wr.write.in.offset = 0;
958                 wr.write.in.remaining = 0;
959                 wr.write.in.data = (const uint8_t *)"x";
960                 status = smb_raw_write(cli1->tree, &wr);
961                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
962         }
963
964         CHECK_VAL(break_info.count, 1);
965         CHECK_VAL(break_info.fnum, fnum2);
966         CHECK_VAL(break_info.level, 0);
967         CHECK_VAL(break_info.failures, 0);
968
969         smbcli_close(cli1->tree, fnum);
970         smbcli_close(cli2->tree, fnum2);
971
972 done:
973         smb_raw_exit(cli1->session);
974         smb_raw_exit(cli2->session);
975         smbcli_deltree(cli1->tree, BASEDIR);
976         return ret;
977 }
978
979 static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
980 {
981         const char *fname = BASEDIR "\\test_batch11.dat";
982         NTSTATUS status;
983         bool ret = true;
984         union smb_open io;
985         union smb_setfileinfo sfi;
986         uint16_t fnum=0;
987
988         if (!torture_setup_dir(cli1, BASEDIR)) {
989                 return false;
990         }
991
992         /* cleanup */
993         smbcli_unlink(cli1->tree, fname);
994
995         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
996
997         /*
998           base ntcreatex parms
999         */
1000         io.generic.level = RAW_OPEN_NTCREATEX;
1001         io.ntcreatex.in.root_fid = 0;
1002         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1003         io.ntcreatex.in.alloc_size = 0;
1004         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1005         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1006         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1007         io.ntcreatex.in.create_options = 0;
1008         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1009         io.ntcreatex.in.security_flags = 0;
1010         io.ntcreatex.in.fname = fname;
1011
1012         /* Test if a set-eof on pathname breaks an exclusive oplock. */
1013         torture_comment(tctx, "Test if setpathinfo set EOF breaks oplocks.\n");
1014
1015         ZERO_STRUCT(break_info);
1016         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1017
1018         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1019                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1020                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1021         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1022         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1023                 NTCREATEX_SHARE_ACCESS_WRITE|
1024                 NTCREATEX_SHARE_ACCESS_DELETE;
1025         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1026         status = smb_raw_open(cli1->tree, tctx, &io);
1027         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1028         fnum = io.ntcreatex.out.file.fnum;
1029         CHECK_VAL(break_info.count, 0);
1030         CHECK_VAL(break_info.failures, 0);
1031         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1032         
1033         ZERO_STRUCT(sfi);
1034         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1035         sfi.generic.in.file.path = fname;
1036         sfi.end_of_file_info.in.size = 100;
1037
1038         status = smb_raw_setpathinfo(cli2->tree, &sfi);
1039
1040         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1041         CHECK_VAL(break_info.count, 1);
1042         CHECK_VAL(break_info.failures, 0);
1043         CHECK_VAL(break_info.level, 0);
1044
1045         smbcli_close(cli1->tree, fnum);
1046
1047 done:
1048         smb_raw_exit(cli1->session);
1049         smb_raw_exit(cli2->session);
1050         smbcli_deltree(cli1->tree, BASEDIR);
1051         return ret;
1052 }
1053
1054 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1055 {
1056         const char *fname = BASEDIR "\\test_batch12.dat";
1057         NTSTATUS status;
1058         bool ret = true;
1059         union smb_open io;
1060         union smb_setfileinfo sfi;
1061         uint16_t fnum=0, fnum2=0;
1062
1063         if (!torture_setup_dir(cli1, BASEDIR)) {
1064                 return false;
1065         }
1066
1067         /* cleanup */
1068         smbcli_unlink(cli1->tree, fname);
1069
1070         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1071
1072         /*
1073           base ntcreatex parms
1074         */
1075         io.generic.level = RAW_OPEN_NTCREATEX;
1076         io.ntcreatex.in.root_fid = 0;
1077         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1078         io.ntcreatex.in.alloc_size = 0;
1079         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1080         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1081         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1082         io.ntcreatex.in.create_options = 0;
1083         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1084         io.ntcreatex.in.security_flags = 0;
1085         io.ntcreatex.in.fname = fname;
1086
1087         /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1088         torture_comment(tctx, "Test if setpathinfo allocation size breaks oplocks.\n");
1089
1090         ZERO_STRUCT(break_info);
1091         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1092
1093         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1094                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1095                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1096         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1097         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1098                 NTCREATEX_SHARE_ACCESS_WRITE|
1099                 NTCREATEX_SHARE_ACCESS_DELETE;
1100         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1101         status = smb_raw_open(cli1->tree, tctx, &io);
1102         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1103         fnum = io.ntcreatex.out.file.fnum;
1104         CHECK_VAL(break_info.count, 0);
1105         CHECK_VAL(break_info.failures, 0);
1106         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1107         
1108         ZERO_STRUCT(sfi);
1109         sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
1110         sfi.generic.in.file.path = fname;
1111         sfi.allocation_info.in.alloc_size = 65536 * 8;
1112
1113         status = smb_raw_setpathinfo(cli2->tree, &sfi);
1114
1115         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1116         CHECK_VAL(break_info.count, 1);
1117         CHECK_VAL(break_info.failures, 0);
1118         CHECK_VAL(break_info.level, 0);
1119
1120         smbcli_close(cli1->tree, fnum);
1121         smbcli_close(cli2->tree, fnum2);
1122
1123 done:
1124         smb_raw_exit(cli1->session);
1125         smb_raw_exit(cli2->session);
1126         smbcli_deltree(cli1->tree, BASEDIR);
1127         return ret;
1128 }
1129
1130 static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1131 {
1132         const char *fname = BASEDIR "\\test_batch13.dat";
1133         NTSTATUS status;
1134         bool ret = true;
1135         union smb_open io;
1136         uint16_t fnum=0, fnum2=0;
1137
1138         if (!torture_setup_dir(cli1, BASEDIR)) {
1139                 return false;
1140         }
1141
1142         /* cleanup */
1143         smbcli_unlink(cli1->tree, fname);
1144
1145         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1146         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, cli1->tree);
1147
1148         /*
1149           base ntcreatex parms
1150         */
1151         io.generic.level = RAW_OPEN_NTCREATEX;
1152         io.ntcreatex.in.root_fid = 0;
1153         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1154         io.ntcreatex.in.alloc_size = 0;
1155         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1156         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1157         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1158         io.ntcreatex.in.create_options = 0;
1159         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1160         io.ntcreatex.in.security_flags = 0;
1161         io.ntcreatex.in.fname = fname;
1162
1163         torture_comment(tctx, "open with batch oplock\n");
1164         ZERO_STRUCT(break_info);
1165         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1166
1167
1168         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1169                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1170                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1171         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1172                 NTCREATEX_SHARE_ACCESS_WRITE|
1173                 NTCREATEX_SHARE_ACCESS_DELETE;
1174         status = smb_raw_open(cli1->tree, tctx, &io);
1175         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1176         fnum = io.ntcreatex.out.file.fnum;
1177         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1178
1179         ZERO_STRUCT(break_info);
1180
1181         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1182
1183         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1184                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1185                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1186         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1187         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1188                 NTCREATEX_SHARE_ACCESS_WRITE|
1189                 NTCREATEX_SHARE_ACCESS_DELETE;
1190         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1191         status = smb_raw_open(cli2->tree, tctx, &io);
1192         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1193         fnum2 = io.ntcreatex.out.file.fnum;
1194         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1195         CHECK_VAL(break_info.count, 1);
1196         CHECK_VAL(break_info.failures, 0);
1197
1198         smbcli_close(cli1->tree, fnum);
1199         smbcli_close(cli2->tree, fnum2);
1200
1201 done:
1202         smb_raw_exit(cli1->session);
1203         smb_raw_exit(cli2->session);
1204         smbcli_deltree(cli1->tree, BASEDIR);
1205         return ret;
1206 }
1207
1208 static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1209 {
1210         const char *fname = BASEDIR "\\test_batch14.dat";
1211         NTSTATUS status;
1212         bool ret = true;
1213         union smb_open io;
1214         uint16_t fnum=0, fnum2=0;
1215
1216         if (!torture_setup_dir(cli1, BASEDIR)) {
1217                 return false;
1218         }
1219
1220         /* cleanup */
1221         smbcli_unlink(cli1->tree, fname);
1222
1223         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1224
1225         /*
1226           base ntcreatex parms
1227         */
1228         io.generic.level = RAW_OPEN_NTCREATEX;
1229         io.ntcreatex.in.root_fid = 0;
1230         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1231         io.ntcreatex.in.alloc_size = 0;
1232         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1233         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1234         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1235         io.ntcreatex.in.create_options = 0;
1236         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1237         io.ntcreatex.in.security_flags = 0;
1238         io.ntcreatex.in.fname = fname;
1239
1240         torture_comment(tctx, "open with batch oplock\n");
1241         ZERO_STRUCT(break_info);
1242         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1243
1244         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1245                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1246                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1247         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1248                 NTCREATEX_SHARE_ACCESS_WRITE|
1249                 NTCREATEX_SHARE_ACCESS_DELETE;
1250         status = smb_raw_open(cli1->tree, tctx, &io);
1251         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1252         fnum = io.ntcreatex.out.file.fnum;
1253         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1254
1255         ZERO_STRUCT(break_info);
1256
1257         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
1258
1259         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1260                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1261                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1262         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1263         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1264                 NTCREATEX_SHARE_ACCESS_WRITE|
1265                 NTCREATEX_SHARE_ACCESS_DELETE;
1266         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1267         status = smb_raw_open(cli2->tree, tctx, &io);
1268         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1269         fnum2 = io.ntcreatex.out.file.fnum;
1270         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1271         CHECK_VAL(break_info.count, 1);
1272         CHECK_VAL(break_info.failures, 0);
1273
1274         smbcli_close(cli1->tree, fnum);
1275         smbcli_close(cli2->tree, fnum2);
1276 done:
1277         smb_raw_exit(cli1->session);
1278         smb_raw_exit(cli2->session);
1279         smbcli_deltree(cli1->tree, BASEDIR);
1280         return ret;
1281 }
1282
1283 /* 
1284    basic testing of oplocks
1285 */
1286 struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
1287 {
1288         struct torture_suite *suite = torture_suite_create(mem_ctx, "OPLOCK");
1289
1290         torture_suite_add_2smb_test(suite, "NORMAL", test_raw_oplock_normal);
1291         torture_suite_add_2smb_test(suite, "BATCH1", test_raw_oplock_batch1);
1292         torture_suite_add_2smb_test(suite, "BATCH2", test_raw_oplock_batch2);
1293         torture_suite_add_2smb_test(suite, "BATCH3", test_raw_oplock_batch3);
1294         torture_suite_add_2smb_test(suite, "BATCH4", test_raw_oplock_batch4);
1295         torture_suite_add_2smb_test(suite, "BATCH5", test_raw_oplock_batch5);
1296         torture_suite_add_2smb_test(suite, "BATCH6", test_raw_oplock_batch6);
1297         torture_suite_add_2smb_test(suite, "BATCH7", test_raw_oplock_batch7);
1298         torture_suite_add_2smb_test(suite, "BATCH8", test_raw_oplock_batch8);
1299         torture_suite_add_2smb_test(suite, "BATCH9", test_raw_oplock_batch9);
1300         torture_suite_add_2smb_test(suite, "BATCH10", test_raw_oplock_batch10);
1301         torture_suite_add_2smb_test(suite, "BATCH11", test_raw_oplock_batch11);
1302         torture_suite_add_2smb_test(suite, "BATCH12", test_raw_oplock_batch12);
1303         torture_suite_add_2smb_test(suite, "BATCH13", test_raw_oplock_batch13);
1304         torture_suite_add_2smb_test(suite, "BATCH14", test_raw_oplock_batch14);
1305
1306         return suite;
1307 }
1308
1309 /* 
1310    stress testing of oplocks
1311 */
1312 bool torture_bench_oplock(struct torture_context *torture)
1313 {
1314         struct smbcli_state **cli;
1315         bool ret = true;
1316         TALLOC_CTX *mem_ctx = talloc_new(torture);
1317         int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
1318         int i, count=0;
1319         int timelimit = torture_setting_int(torture, "timelimit", 10);
1320         union smb_open io;
1321         struct timeval tv;
1322         struct event_context *ev = event_context_find(mem_ctx);
1323
1324         cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
1325
1326         torture_comment(torture, "Opening %d connections\n", torture_nprocs);
1327         for (i=0;i<torture_nprocs;i++) {
1328                 if (!torture_open_connection_ev(&cli[i], i, ev)) {
1329                         return false;
1330                 }
1331                 talloc_steal(mem_ctx, cli[i]);
1332                 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close, 
1333                                       cli[i]->tree);
1334         }
1335
1336         if (!torture_setup_dir(cli[0], BASEDIR)) {
1337                 ret = false;
1338                 goto done;
1339         }
1340
1341         io.ntcreatex.level = RAW_OPEN_NTCREATEX;
1342         io.ntcreatex.in.root_fid = 0;
1343         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1344         io.ntcreatex.in.alloc_size = 0;
1345         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1346         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1347         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1348         io.ntcreatex.in.create_options = 0;
1349         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1350         io.ntcreatex.in.security_flags = 0;
1351         io.ntcreatex.in.fname = BASEDIR "\\test.dat";
1352         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1353                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1354                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1355
1356         tv = timeval_current(); 
1357
1358         /*
1359           we open the same file with SHARE_ACCESS_NONE from all the
1360           connections in a round robin fashion. Each open causes an
1361           oplock break on the previous connection, which is answered
1362           by the oplock_handler_close() to close the file.
1363
1364           This measures how fast we can pass on oplocks, and stresses
1365           the oplock handling code
1366         */
1367         torture_comment(torture, "Running for %d seconds\n", timelimit);
1368         while (timeval_elapsed(&tv) < timelimit) {
1369                 for (i=0;i<torture_nprocs;i++) {
1370                         NTSTATUS status;
1371
1372                         status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
1373                         CHECK_STATUS(torture, status, NT_STATUS_OK);
1374                         count++;
1375                 }
1376
1377                 if (torture_setting_bool(torture, "progress", true)) {
1378                         torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
1379                 }
1380         }
1381
1382         torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
1383
1384         smb_raw_exit(cli[torture_nprocs-1]->session);
1385         
1386 done:
1387         smb_raw_exit(cli[0]->session);
1388         smbcli_deltree(cli[0]->tree, BASEDIR);
1389         talloc_free(mem_ctx);
1390         return ret;
1391 }
1392
1393
1394 static struct hold_oplock_info {
1395         const char *fname;
1396         bool close_on_break;
1397         uint32_t share_access;
1398         uint16_t fnum;
1399 } hold_info[] = {
1400         { BASEDIR "\\notshared_close", true,  
1401           NTCREATEX_SHARE_ACCESS_NONE, },
1402         { BASEDIR "\\notshared_noclose", false, 
1403           NTCREATEX_SHARE_ACCESS_NONE, },
1404         { BASEDIR "\\shared_close", true,  
1405           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
1406         { BASEDIR "\\shared_noclose", false,  
1407           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
1408 };
1409
1410 static bool oplock_handler_hold(struct smbcli_transport *transport, 
1411                                 uint16_t tid, uint16_t fnum, uint8_t level, 
1412                                 void *private)
1413 {
1414         struct smbcli_tree *tree = (struct smbcli_tree *)private;
1415         struct hold_oplock_info *info;
1416         int i;
1417
1418         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
1419                 if (hold_info[i].fnum == fnum) break;
1420         }
1421
1422         if (i == ARRAY_SIZE(hold_info)) {
1423                 printf("oplock break for unknown fnum %u\n", fnum);
1424                 return false;
1425         }
1426
1427         info = &hold_info[i];
1428
1429         if (info->close_on_break) {
1430                 printf("oplock break on %s - closing\n",
1431                        info->fname);
1432                 oplock_handler_close(transport, tid, fnum, level, private);
1433                 return true;
1434         }
1435
1436         printf("oplock break on %s - acking break\n", info->fname);
1437
1438         return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
1439 }
1440
1441
1442 /* 
1443    used for manual testing of oplocks - especially interaction with
1444    other filesystems (such as NFS and local access)
1445 */
1446 bool torture_hold_oplock(struct torture_context *torture, 
1447                          struct smbcli_state *cli)
1448 {
1449         struct event_context *ev = 
1450                 (struct event_context *)cli->transport->socket->event.ctx;
1451         int i;
1452
1453         printf("Setting up open files with oplocks in %s\n", BASEDIR);
1454
1455         if (!torture_setup_dir(cli, BASEDIR)) {
1456                 return false;
1457         }
1458
1459         smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
1460
1461         /* setup the files */
1462         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
1463                 union smb_open io;
1464                 NTSTATUS status;
1465
1466                 io.generic.level = RAW_OPEN_NTCREATEX;
1467                 io.ntcreatex.in.root_fid = 0;
1468                 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1469                 io.ntcreatex.in.alloc_size = 0;
1470                 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1471                 io.ntcreatex.in.share_access = hold_info[i].share_access;
1472                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1473                 io.ntcreatex.in.create_options = 0;
1474                 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1475                 io.ntcreatex.in.security_flags = 0;
1476                 io.ntcreatex.in.fname = hold_info[i].fname;
1477                 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1478                         NTCREATEX_FLAGS_REQUEST_OPLOCK |
1479                         NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1480                 printf("opening %s\n", hold_info[i].fname);
1481
1482                 status = smb_raw_open(cli->tree, cli, &io);
1483                 if (!NT_STATUS_IS_OK(status)) {
1484                         printf("Failed to open %s - %s\n", 
1485                                hold_info[i].fname, nt_errstr(status));
1486                         return false;
1487                 }
1488
1489                 if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
1490                         printf("Oplock not granted for %s - expected %d but got %d\n", 
1491                                hold_info[i].fname, BATCH_OPLOCK_RETURN, 
1492                                 io.ntcreatex.out.oplock_level);
1493                         return false;
1494                 }
1495                 hold_info[i].fnum = io.ntcreatex.out.file.fnum;
1496         }
1497
1498         printf("Waiting for oplock events\n");
1499         event_loop_wait(ev);
1500
1501         return true;
1502 }