source: trunk/server/source4/torture/raw/oplock.c

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

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