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