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