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