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