libcli: Make cli_smb2_close_fnum async
[Samba.git] / source4 / torture / smb2 / lease.c
blob045f9943a4c252c7f73372302800522e707c9dd7
1 /*
2 Unix SMB/CIFS implementation.
4 test suite for SMB2 leases
6 Copyright (C) Zachary Loafman 2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include <tevent.h>
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "torture/torture.h"
27 #include "torture/smb2/proto.h"
28 #include "libcli/smb/smbXcli_base.h"
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)
37 #define CHECK_STATUS(status, correct) do { \
38 if (!NT_STATUS_EQUAL(status, correct)) { \
39 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
40 nt_errstr(status), nt_errstr(correct)); \
41 ret = false; \
42 goto done; \
43 }} while (0)
45 #define CHECK_CREATED(__io, __created, __attribute) \
46 do { \
47 CHECK_VAL((__io)->out.create_action, NTCREATEX_ACTION_ ## __created); \
48 CHECK_VAL((__io)->out.alloc_size, 0); \
49 CHECK_VAL((__io)->out.size, 0); \
50 CHECK_VAL((__io)->out.file_attr, (__attribute)); \
51 CHECK_VAL((__io)->out.reserved2, 0); \
52 } while(0)
54 #define CHECK_LEASE(__io, __state, __oplevel, __key) \
55 do { \
56 if (__oplevel) { \
57 CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); \
58 CHECK_VAL((__io)->out.lease_response.lease_key.data[0], (__key)); \
59 CHECK_VAL((__io)->out.lease_response.lease_key.data[1], ~(__key)); \
60 CHECK_VAL((__io)->out.lease_response.lease_state, smb2_util_lease_state(__state)); \
61 } else { \
62 CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); \
63 CHECK_VAL((__io)->out.lease_response.lease_key.data[0], 0); \
64 CHECK_VAL((__io)->out.lease_response.lease_key.data[1], 0); \
65 CHECK_VAL((__io)->out.lease_response.lease_state, 0); \
66 } \
68 CHECK_VAL((__io)->out.lease_response.lease_flags, 0); \
69 CHECK_VAL((__io)->out.lease_response.lease_duration, 0); \
70 } while(0)
72 #define CHECK_LEASE_V2(__io, __state, __oplevel, __key, __flags) \
73 do { \
74 if (__oplevel) { \
75 CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); \
76 CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[0], (__key)); \
77 CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[1], ~(__key)); \
78 CHECK_VAL((__io)->out.lease_response_v2.lease_state, smb2_util_lease_state(__state)); \
79 } else { \
80 CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); \
81 CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[0], 0); \
82 CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[1], 0); \
83 CHECK_VAL((__io)->out.lease_response_v2.lease_state, 0); \
84 } \
86 CHECK_VAL((__io)->out.lease_response_v2.lease_flags, __flags); \
87 CHECK_VAL((__io)->out.lease_response_v2.lease_duration, 0); \
88 } while(0)
90 static const uint64_t LEASE1 = 0xBADC0FFEE0DDF00Dull;
91 static const uint64_t LEASE2 = 0xDEADBEEFFEEDBEADull;
92 static const uint64_t LEASE3 = 0xDAD0FFEDD00DF00Dull;
93 static const uint64_t LEASE4 = 0xBAD0FFEDD00DF00Dull;
95 #define NREQUEST_RESULTS 8
96 static const char *request_results[NREQUEST_RESULTS][2] = {
97 { "", "" },
98 { "R", "R" },
99 { "H", "" },
100 { "W", "" },
101 { "RH", "RH" },
102 { "RW", "RW" },
103 { "HW", "" },
104 { "RHW", "RHW" },
107 static bool test_lease_request(struct torture_context *tctx,
108 struct smb2_tree *tree)
110 TALLOC_CTX *mem_ctx = talloc_new(tctx);
111 struct smb2_create io;
112 struct smb2_lease ls;
113 struct smb2_handle h1, h2;
114 NTSTATUS status;
115 const char *fname = "lease.dat";
116 const char *fname2 = "lease2.dat";
117 const char *sname = "lease.dat:stream";
118 const char *dname = "lease.dir";
119 bool ret = true;
120 int i;
121 uint32_t caps;
123 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
124 if (!(caps & SMB2_CAP_LEASING)) {
125 torture_skip(tctx, "leases are not supported");
128 smb2_util_unlink(tree, fname);
129 smb2_util_unlink(tree, fname2);
130 smb2_util_rmdir(tree, dname);
132 /* Win7 is happy to grant RHW leases on files. */
133 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
134 status = smb2_create(tree, mem_ctx, &io);
135 CHECK_STATUS(status, NT_STATUS_OK);
136 h1 = io.out.file.handle;
137 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
138 CHECK_LEASE(&io, "RHW", true, LEASE1);
140 /* But will reject leases on directories. */
141 smb2_lease_create(&io, &ls, true, dname, LEASE2, smb2_util_lease_state("RHW"));
142 status = smb2_create(tree, mem_ctx, &io);
143 CHECK_STATUS(status, NT_STATUS_OK);
144 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_DIRECTORY);
145 CHECK_LEASE(&io, "", false, 0);
146 smb2_util_close(tree, io.out.file.handle);
148 /* Also rejects multiple files leased under the same key. */
149 smb2_lease_create(&io, &ls, true, fname2, LEASE1, smb2_util_lease_state("RHW"));
150 status = smb2_create(tree, mem_ctx, &io);
151 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
153 /* And grants leases on streams (with separate leasekey). */
154 smb2_lease_create(&io, &ls, false, sname, LEASE2, smb2_util_lease_state("RHW"));
155 status = smb2_create(tree, mem_ctx, &io);
156 h2 = io.out.file.handle;
157 CHECK_STATUS(status, NT_STATUS_OK);
158 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
159 CHECK_LEASE(&io, "RHW", true, LEASE2);
160 smb2_util_close(tree, h2);
162 smb2_util_close(tree, h1);
164 /* Now see what combos are actually granted. */
165 for (i = 0; i < NREQUEST_RESULTS; i++) {
166 torture_comment(tctx, "Requesting lease type %s(%x),"
167 " expecting %s(%x)\n",
168 request_results[i][0], smb2_util_lease_state(request_results[i][0]),
169 request_results[i][1], smb2_util_lease_state(request_results[i][1]));
170 smb2_lease_create(&io, &ls, false, fname, LEASE1,
171 smb2_util_lease_state(request_results[i][0]));
172 status = smb2_create(tree, mem_ctx, &io);
173 h2 = io.out.file.handle;
174 CHECK_STATUS(status, NT_STATUS_OK);
175 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
176 CHECK_LEASE(&io, request_results[i][1], true, LEASE1);
177 smb2_util_close(tree, io.out.file.handle);
180 done:
181 smb2_util_close(tree, h1);
182 smb2_util_close(tree, h2);
184 smb2_util_unlink(tree, fname);
185 smb2_util_unlink(tree, fname2);
186 smb2_util_rmdir(tree, dname);
188 talloc_free(mem_ctx);
190 return ret;
193 static bool test_lease_upgrade(struct torture_context *tctx,
194 struct smb2_tree *tree)
196 TALLOC_CTX *mem_ctx = talloc_new(tctx);
197 struct smb2_create io;
198 struct smb2_lease ls;
199 struct smb2_handle h, hnew;
200 NTSTATUS status;
201 const char *fname = "lease.dat";
202 bool ret = true;
203 uint32_t caps;
205 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
206 if (!(caps & SMB2_CAP_LEASING)) {
207 torture_skip(tctx, "leases are not supported");
210 smb2_util_unlink(tree, fname);
212 /* Grab a RH lease. */
213 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RH"));
214 status = smb2_create(tree, mem_ctx, &io);
215 CHECK_STATUS(status, NT_STATUS_OK);
216 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
217 CHECK_LEASE(&io, "RH", true, LEASE1);
218 h = io.out.file.handle;
220 /* Upgrades (sidegrades?) to RW leave us with an RH. */
221 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RW"));
222 status = smb2_create(tree, mem_ctx, &io);
223 CHECK_STATUS(status, NT_STATUS_OK);
224 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
225 CHECK_LEASE(&io, "RH", true, LEASE1);
226 hnew = io.out.file.handle;
228 smb2_util_close(tree, hnew);
230 /* Upgrade to RHW lease. */
231 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
232 status = smb2_create(tree, mem_ctx, &io);
233 CHECK_STATUS(status, NT_STATUS_OK);
234 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
235 CHECK_LEASE(&io, "RHW", true, LEASE1);
236 hnew = io.out.file.handle;
238 smb2_util_close(tree, h);
239 h = hnew;
241 /* Attempt to downgrade - original lease state is maintained. */
242 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RH"));
243 status = smb2_create(tree, mem_ctx, &io);
244 CHECK_STATUS(status, NT_STATUS_OK);
245 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
246 CHECK_LEASE(&io, "RHW", true, LEASE1);
247 hnew = io.out.file.handle;
249 smb2_util_close(tree, hnew);
251 done:
252 smb2_util_close(tree, h);
253 smb2_util_close(tree, hnew);
255 smb2_util_unlink(tree, fname);
257 talloc_free(mem_ctx);
259 return ret;
263 * upgrade2 test.
264 * full matrix of lease upgrade combinations
265 * (non-contended case)
267 * The summary of the behaviour is this:
268 * -------------------------------------
269 * An uncontended lease upgrade results in a change
270 * if and only if the requested lease state is
271 * - valid, and
272 * - strictly a superset of the lease state already held.
274 * In that case the resulting lease state is the one
275 * requested in the upgrade.
277 struct lease_upgrade2_test {
278 const char *initial;
279 const char *upgrade_to;
280 const char *expected;
283 #define NUM_LEASE_TYPES 5
284 #define NUM_UPGRADE_TESTS ( NUM_LEASE_TYPES * NUM_LEASE_TYPES )
285 struct lease_upgrade2_test lease_upgrade2_tests[NUM_UPGRADE_TESTS] = {
286 { "", "", "" },
287 { "", "R", "R" },
288 { "", "RH", "RH" },
289 { "", "RW", "RW" },
290 { "", "RWH", "RWH" },
292 { "R", "", "R" },
293 { "R", "R", "R" },
294 { "R", "RH", "RH" },
295 { "R", "RW", "RW" },
296 { "R", "RWH", "RWH" },
298 { "RH", "", "RH" },
299 { "RH", "R", "RH" },
300 { "RH", "RH", "RH" },
301 { "RH", "RW", "RH" },
302 { "RH", "RWH", "RWH" },
304 { "RW", "", "RW" },
305 { "RW", "R", "RW" },
306 { "RW", "RH", "RW" },
307 { "RW", "RW", "RW" },
308 { "RW", "RWH", "RWH" },
310 { "RWH", "", "RWH" },
311 { "RWH", "R", "RWH" },
312 { "RWH", "RH", "RWH" },
313 { "RWH", "RW", "RWH" },
314 { "RWH", "RWH", "RWH" },
317 static bool test_lease_upgrade2(struct torture_context *tctx,
318 struct smb2_tree *tree)
320 TALLOC_CTX *mem_ctx = talloc_new(tctx);
321 struct smb2_handle h, hnew;
322 NTSTATUS status;
323 struct smb2_create io;
324 struct smb2_lease ls;
325 const char *fname = "lease.dat";
326 bool ret = true;
327 int i;
328 uint32_t caps;
330 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
331 if (!(caps & SMB2_CAP_LEASING)) {
332 torture_skip(tctx, "leases are not supported");
335 for (i = 0; i < NUM_UPGRADE_TESTS; i++) {
336 struct lease_upgrade2_test t = lease_upgrade2_tests[i];
338 smb2_util_unlink(tree, fname);
340 /* Grab a lease. */
341 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.initial));
342 status = smb2_create(tree, mem_ctx, &io);
343 CHECK_STATUS(status, NT_STATUS_OK);
344 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
345 CHECK_LEASE(&io, t.initial, true, LEASE1);
346 h = io.out.file.handle;
348 /* Upgrade. */
349 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.upgrade_to));
350 status = smb2_create(tree, mem_ctx, &io);
351 CHECK_STATUS(status, NT_STATUS_OK);
352 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
353 CHECK_LEASE(&io, t.expected, true, LEASE1);
354 hnew = io.out.file.handle;
356 smb2_util_close(tree, hnew);
357 smb2_util_close(tree, h);
360 done:
361 smb2_util_close(tree, h);
362 smb2_util_close(tree, hnew);
364 smb2_util_unlink(tree, fname);
366 talloc_free(mem_ctx);
368 return ret;
372 #define CHECK_LEASE_BREAK(__lb, __oldstate, __state, __key) \
373 do { \
374 CHECK_VAL((__lb)->new_lease_state, smb2_util_lease_state(__state)); \
375 CHECK_VAL((__lb)->current_lease.lease_state, smb2_util_lease_state(__oldstate)); \
376 CHECK_VAL((__lb)->current_lease.lease_key.data[0], (__key)); \
377 CHECK_VAL((__lb)->current_lease.lease_key.data[1], ~(__key)); \
378 } while(0)
380 #define CHECK_LEASE_BREAK_ACK(__lba, __state, __key) \
381 do { \
382 CHECK_VAL((__lba)->out.reserved, 0); \
383 CHECK_VAL((__lba)->out.lease.lease_key.data[0], (__key)); \
384 CHECK_VAL((__lba)->out.lease.lease_key.data[1], ~(__key)); \
385 CHECK_VAL((__lba)->out.lease.lease_state, smb2_util_lease_state(__state)); \
386 CHECK_VAL((__lba)->out.lease.lease_flags, 0); \
387 CHECK_VAL((__lba)->out.lease.lease_duration, 0); \
388 } while(0)
390 static struct {
391 struct smb2_lease_break lease_break;
392 struct smb2_lease_break_ack lease_break_ack;
393 int count;
394 int failures;
396 struct smb2_handle oplock_handle;
397 uint8_t held_oplock_level;
398 uint8_t oplock_level;
399 int oplock_count;
400 int oplock_failures;
401 } break_info;
403 #define CHECK_BREAK_INFO(__oldstate, __state, __key) \
404 do { \
405 CHECK_VAL(break_info.failures, 0); \
406 CHECK_VAL(break_info.count, 1); \
407 CHECK_LEASE_BREAK(&break_info.lease_break, (__oldstate), \
408 (__state), (__key)); \
409 if (break_info.lease_break.break_flags & \
410 SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) { \
411 CHECK_LEASE_BREAK_ACK(&break_info.lease_break_ack, \
412 (__state), (__key)); \
414 } while(0)
416 static void torture_lease_break_callback(struct smb2_request *req)
418 NTSTATUS status;
420 status = smb2_lease_break_ack_recv(req, &break_info.lease_break_ack);
421 if (!NT_STATUS_IS_OK(status))
422 break_info.failures++;
424 return;
427 /* a lease break request handler */
428 static bool torture_lease_handler(struct smb2_transport *transport,
429 const struct smb2_lease_break *lb,
430 void *private_data)
432 struct smb2_tree *tree = private_data;
433 struct smb2_lease_break_ack io;
434 struct smb2_request *req;
436 break_info.lease_break = *lb;
437 break_info.count++;
439 if (lb->break_flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) {
440 ZERO_STRUCT(io);
441 io.in.lease.lease_key = lb->current_lease.lease_key;
442 io.in.lease.lease_state = lb->new_lease_state;
444 req = smb2_lease_break_ack_send(tree, &io);
445 req->async.fn = torture_lease_break_callback;
446 req->async.private_data = NULL;
449 return true;
453 * upgrade3:
454 * full matrix of lease upgrade combinations
455 * (contended case)
457 * We start with 2 leases, and check how one can
458 * be upgraded
460 * The summary of the behaviour is this:
461 * -------------------------------------
463 * If we have two leases (lease1 and lease2) on the same file,
464 * then attempt to upgrade lease1 results in a change if and only
465 * if the requested lease state:
466 * - is valid,
467 * - is strictly a superset of lease1, and
468 * - can held together with lease2.
470 * In that case, the resuling lease state of the upgraded lease1
471 * is the state requested in the upgrade. lease2 is not broken
472 * and remains unchanged.
474 * Note that this contrasts the case of directly opening with
475 * an initial requested lease state, in which case you get that
476 * portion of the requested state that can be shared with the
477 * already existing leases (or the states that they get broken to).
479 struct lease_upgrade3_test {
480 const char *held1;
481 const char *held2;
482 const char *upgrade_to;
483 const char *upgraded_to;
486 #define NUM_UPGRADE3_TESTS ( 20 )
487 struct lease_upgrade3_test lease_upgrade3_tests[NUM_UPGRADE3_TESTS] = {
488 {"R", "R", "", "R" },
489 {"R", "R", "R", "R" },
490 {"R", "R", "RW", "R" },
491 {"R", "R", "RH", "RH" },
492 {"R", "R", "RHW", "R" },
494 {"R", "RH", "", "R" },
495 {"R", "RH", "R", "R" },
496 {"R", "RH", "RW", "R" },
497 {"R", "RH", "RH", "RH" },
498 {"R", "RH", "RHW", "R" },
500 {"RH", "R", "", "RH" },
501 {"RH", "R", "R", "RH" },
502 {"RH", "R", "RW", "RH" },
503 {"RH", "R", "RH", "RH" },
504 {"RH", "R", "RHW", "RH" },
506 {"RH", "RH", "", "RH" },
507 {"RH", "RH", "R", "RH" },
508 {"RH", "RH", "RW", "RH" },
509 {"RH", "RH", "RH", "RH" },
510 {"RH", "RH", "RHW", "RH" },
513 static bool test_lease_upgrade3(struct torture_context *tctx,
514 struct smb2_tree *tree)
516 TALLOC_CTX *mem_ctx = talloc_new(tctx);
517 struct smb2_handle h, h2, hnew;
518 NTSTATUS status;
519 struct smb2_create io;
520 struct smb2_lease ls;
521 const char *fname = "upgrade3.dat";
522 bool ret = true;
523 int i;
524 uint32_t caps;
526 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
527 if (!(caps & SMB2_CAP_LEASING)) {
528 torture_skip(tctx, "leases are not supported");
531 tree->session->transport->lease.handler = torture_lease_handler;
532 tree->session->transport->lease.private_data = tree;
534 smb2_util_unlink(tree, fname);
536 for (i = 0; i < NUM_UPGRADE3_TESTS; i++) {
537 struct lease_upgrade3_test t = lease_upgrade3_tests[i];
539 smb2_util_unlink(tree, fname);
541 ZERO_STRUCT(break_info);
543 /* grab first lease */
544 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.held1));
545 status = smb2_create(tree, mem_ctx, &io);
546 CHECK_STATUS(status, NT_STATUS_OK);
547 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
548 CHECK_LEASE(&io, t.held1, true, LEASE1);
549 h = io.out.file.handle;
551 /* grab second lease */
552 smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state(t.held2));
553 status = smb2_create(tree, mem_ctx, &io);
554 CHECK_STATUS(status, NT_STATUS_OK);
555 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
556 CHECK_LEASE(&io, t.held2, true, LEASE2);
557 h2 = io.out.file.handle;
559 /* no break has happened */
560 CHECK_VAL(break_info.count, 0);
561 CHECK_VAL(break_info.failures, 0);
563 /* try to upgrade lease1 */
564 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.upgrade_to));
565 status = smb2_create(tree, mem_ctx, &io);
566 CHECK_STATUS(status, NT_STATUS_OK);
567 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
568 CHECK_LEASE(&io, t.upgraded_to, true, LEASE1);
569 hnew = io.out.file.handle;
571 /* no break has happened */
572 CHECK_VAL(break_info.count, 0);
573 CHECK_VAL(break_info.failures, 0);
575 smb2_util_close(tree, hnew);
576 smb2_util_close(tree, h);
577 smb2_util_close(tree, h2);
580 done:
581 smb2_util_close(tree, h);
582 smb2_util_close(tree, hnew);
583 smb2_util_close(tree, h2);
585 smb2_util_unlink(tree, fname);
587 talloc_free(mem_ctx);
589 return ret;
595 Timer handler function notifies the registering function that time is up
597 static void timeout_cb(struct tevent_context *ev,
598 struct tevent_timer *te,
599 struct timeval current_time,
600 void *private_data)
602 bool *timesup = (bool *)private_data;
603 *timesup = true;
604 return;
608 Wait a short period of time to receive a single oplock break request
610 static void torture_wait_for_lease_break(struct torture_context *tctx)
612 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
613 struct tevent_timer *te = NULL;
614 struct timeval ne;
615 bool timesup = false;
616 int old_count = break_info.count;
618 /* Wait .1 seconds for an lease break */
619 ne = tevent_timeval_current_ofs(0, 100000);
621 te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup);
622 if (te == NULL) {
623 torture_comment(tctx, "Failed to wait for an oplock break. "
624 "test results may not be accurate.");
625 goto done;
628 while (!timesup && break_info.count < old_count + 1) {
629 if (tevent_loop_once(tctx->ev) != 0) {
630 torture_comment(tctx, "Failed to wait for an oplock "
631 "break. test results may not be "
632 "accurate.");
633 goto done;
637 done:
638 /* We don't know if the timed event fired and was freed, we received
639 * our oplock break, or some other event triggered the loop. Thus,
640 * we create a tmp_ctx to be able to safely free/remove the timed
641 * event in all 3 cases. */
642 talloc_free(tmp_ctx);
644 return;
648 break_results should be read as "held lease, new lease, hold broken to, new
649 grant", i.e. { "RH", "RW", "RH", "R" } means that if key1 holds RH and key2
650 tries for RW, key1 will be broken to RH (in this case, not broken at all)
651 and key2 will be granted R.
653 Note: break_results only includes things that Win7 will actually grant (see
654 request_results above).
656 #define NBREAK_RESULTS 16
657 static const char *break_results[NBREAK_RESULTS][4] = {
658 {"R", "R", "R", "R"},
659 {"R", "RH", "R", "RH"},
660 {"R", "RW", "R", "R"},
661 {"R", "RHW", "R", "RH"},
663 {"RH", "R", "RH", "R"},
664 {"RH", "RH", "RH", "RH"},
665 {"RH", "RW", "RH", "R"},
666 {"RH", "RHW", "RH", "RH"},
668 {"RW", "R", "R", "R"},
669 {"RW", "RH", "R", "RH"},
670 {"RW", "RW", "R", "R"},
671 {"RW", "RHW", "R", "RH"},
673 {"RHW", "R", "RH", "R"},
674 {"RHW", "RH", "RH", "RH"},
675 {"RHW", "RW", "RH", "R"},
676 {"RHW", "RHW", "RH", "RH"},
679 static bool test_lease_break(struct torture_context *tctx,
680 struct smb2_tree *tree)
682 TALLOC_CTX *mem_ctx = talloc_new(tctx);
683 struct smb2_create io;
684 struct smb2_lease ls;
685 struct smb2_handle h, h2, h3;
686 NTSTATUS status;
687 const char *fname = "lease.dat";
688 bool ret = true;
689 int i;
690 uint32_t caps;
692 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
693 if (!(caps & SMB2_CAP_LEASING)) {
694 torture_skip(tctx, "leases are not supported");
697 tree->session->transport->lease.handler = torture_lease_handler;
698 tree->session->transport->lease.private_data = tree;
700 smb2_util_unlink(tree, fname);
702 for (i = 0; i < NBREAK_RESULTS; i++) {
703 const char *held = break_results[i][0];
704 const char *contend = break_results[i][1];
705 const char *brokento = break_results[i][2];
706 const char *granted = break_results[i][3];
707 torture_comment(tctx, "Hold %s(%x), requesting %s(%x), "
708 "expecting break to %s(%x) and grant of %s(%x)\n",
709 held, smb2_util_lease_state(held), contend, smb2_util_lease_state(contend),
710 brokento, smb2_util_lease_state(brokento), granted, smb2_util_lease_state(granted));
712 ZERO_STRUCT(break_info);
714 /* Grab lease. */
715 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(held));
716 status = smb2_create(tree, mem_ctx, &io);
717 CHECK_STATUS(status, NT_STATUS_OK);
718 h = io.out.file.handle;
719 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
720 CHECK_LEASE(&io, held, true, LEASE1);
722 /* Possibly contend lease. */
723 smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state(contend));
724 status = smb2_create(tree, mem_ctx, &io);
725 CHECK_STATUS(status, NT_STATUS_OK);
726 h2 = io.out.file.handle;
727 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
728 CHECK_LEASE(&io, granted, true, LEASE2);
730 if (smb2_util_lease_state(held) != smb2_util_lease_state(brokento)) {
731 CHECK_BREAK_INFO(held, brokento, LEASE1);
732 } else {
733 CHECK_VAL(break_info.count, 0);
734 CHECK_VAL(break_info.failures, 0);
737 ZERO_STRUCT(break_info);
740 Now verify that an attempt to upgrade LEASE1 results in no
741 break and no change in LEASE1.
743 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
744 status = smb2_create(tree, mem_ctx, &io);
745 CHECK_STATUS(status, NT_STATUS_OK);
746 h3 = io.out.file.handle;
747 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
748 CHECK_LEASE(&io, brokento, true, LEASE1);
749 CHECK_VAL(break_info.count, 0);
750 CHECK_VAL(break_info.failures, 0);
752 smb2_util_close(tree, h);
753 smb2_util_close(tree, h2);
754 smb2_util_close(tree, h3);
756 status = smb2_util_unlink(tree, fname);
757 CHECK_STATUS(status, NT_STATUS_OK);
760 done:
761 smb2_util_close(tree, h);
762 smb2_util_close(tree, h2);
764 smb2_util_unlink(tree, fname);
766 talloc_free(mem_ctx);
768 return ret;
771 static void torture_oplock_break_callback(struct smb2_request *req)
773 NTSTATUS status;
774 struct smb2_break br;
776 ZERO_STRUCT(br);
777 status = smb2_break_recv(req, &br);
778 if (!NT_STATUS_IS_OK(status))
779 break_info.oplock_failures++;
781 return;
784 /* a oplock break request handler */
785 static bool torture_oplock_handler(struct smb2_transport *transport,
786 const struct smb2_handle *handle,
787 uint8_t level, void *private_data)
789 struct smb2_tree *tree = private_data;
790 struct smb2_request *req;
791 struct smb2_break br;
793 break_info.oplock_handle = *handle;
794 break_info.oplock_level = level;
795 break_info.oplock_count++;
797 ZERO_STRUCT(br);
798 br.in.file.handle = *handle;
799 br.in.oplock_level = level;
801 if (break_info.held_oplock_level > SMB2_OPLOCK_LEVEL_II) {
802 req = smb2_break_send(tree, &br);
803 req->async.fn = torture_oplock_break_callback;
804 req->async.private_data = NULL;
806 break_info.held_oplock_level = level;
808 return true;
811 #define NOPLOCK_RESULTS 12
812 static const char *oplock_results[NOPLOCK_RESULTS][4] = {
813 {"R", "s", "R", "s"},
814 {"R", "x", "R", "s"},
815 {"R", "b", "R", "s"},
817 {"RH", "s", "RH", ""},
818 {"RH", "x", "RH", ""},
819 {"RH", "b", "RH", ""},
821 {"RW", "s", "R", "s"},
822 {"RW", "x", "R", "s"},
823 {"RW", "b", "R", "s"},
825 {"RHW", "s", "RH", ""},
826 {"RHW", "x", "RH", ""},
827 {"RHW", "b", "RH", ""},
830 static const char *oplock_results_2[NOPLOCK_RESULTS][4] = {
831 {"s", "R", "s", "R"},
832 {"s", "RH", "s", "R"},
833 {"s", "RW", "s", "R"},
834 {"s", "RHW", "s", "R"},
836 {"x", "R", "s", "R"},
837 {"x", "RH", "s", "R"},
838 {"x", "RW", "s", "R"},
839 {"x", "RHW", "s", "R"},
841 {"b", "R", "s", "R"},
842 {"b", "RH", "s", "R"},
843 {"b", "RW", "s", "R"},
844 {"b", "RHW", "s", "R"},
847 static bool test_lease_oplock(struct torture_context *tctx,
848 struct smb2_tree *tree)
850 TALLOC_CTX *mem_ctx = talloc_new(tctx);
851 struct smb2_create io;
852 struct smb2_lease ls;
853 struct smb2_handle h, h2;
854 NTSTATUS status;
855 const char *fname = "lease.dat";
856 bool ret = true;
857 int i;
858 uint32_t caps;
860 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
861 if (!(caps & SMB2_CAP_LEASING)) {
862 torture_skip(tctx, "leases are not supported");
865 tree->session->transport->lease.handler = torture_lease_handler;
866 tree->session->transport->lease.private_data = tree;
867 tree->session->transport->oplock.handler = torture_oplock_handler;
868 tree->session->transport->oplock.private_data = tree;
870 smb2_util_unlink(tree, fname);
872 for (i = 0; i < NOPLOCK_RESULTS; i++) {
873 const char *held = oplock_results[i][0];
874 const char *contend = oplock_results[i][1];
875 const char *brokento = oplock_results[i][2];
876 const char *granted = oplock_results[i][3];
877 torture_comment(tctx, "Hold %s(%x), requesting %s(%x), "
878 "expecting break to %s(%x) and grant of %s(%x)\n",
879 held, smb2_util_lease_state(held), contend, smb2_util_oplock_level(contend),
880 brokento, smb2_util_lease_state(brokento), granted, smb2_util_oplock_level(granted));
882 ZERO_STRUCT(break_info);
884 /* Grab lease. */
885 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(held));
886 status = smb2_create(tree, mem_ctx, &io);
887 CHECK_STATUS(status, NT_STATUS_OK);
888 h = io.out.file.handle;
889 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
890 CHECK_LEASE(&io, held, true, LEASE1);
892 /* Does an oplock contend the lease? */
893 smb2_oplock_create(&io, fname, smb2_util_oplock_level(contend));
894 status = smb2_create(tree, mem_ctx, &io);
895 CHECK_STATUS(status, NT_STATUS_OK);
896 h2 = io.out.file.handle;
897 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
898 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(granted));
899 break_info.held_oplock_level = io.out.oplock_level;
901 if (smb2_util_lease_state(held) != smb2_util_lease_state(brokento)) {
902 CHECK_BREAK_INFO(held, brokento, LEASE1);
903 } else {
904 CHECK_VAL(break_info.count, 0);
905 CHECK_VAL(break_info.failures, 0);
908 smb2_util_close(tree, h);
909 smb2_util_close(tree, h2);
911 status = smb2_util_unlink(tree, fname);
912 CHECK_STATUS(status, NT_STATUS_OK);
915 for (i = 0; i < NOPLOCK_RESULTS; i++) {
916 const char *held = oplock_results_2[i][0];
917 const char *contend = oplock_results_2[i][1];
918 const char *brokento = oplock_results_2[i][2];
919 const char *granted = oplock_results_2[i][3];
920 torture_comment(tctx, "Hold %s(%x), requesting %s(%x), "
921 "expecting break to %s(%x) and grant of %s(%x)\n",
922 held, smb2_util_oplock_level(held), contend, smb2_util_lease_state(contend),
923 brokento, smb2_util_oplock_level(brokento), granted, smb2_util_lease_state(granted));
925 ZERO_STRUCT(break_info);
927 /* Grab an oplock. */
928 smb2_oplock_create(&io, fname, smb2_util_oplock_level(held));
929 status = smb2_create(tree, mem_ctx, &io);
930 CHECK_STATUS(status, NT_STATUS_OK);
931 h = io.out.file.handle;
932 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
933 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(held));
934 break_info.held_oplock_level = io.out.oplock_level;
936 /* Grab lease. */
937 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(contend));
938 status = smb2_create(tree, mem_ctx, &io);
939 CHECK_STATUS(status, NT_STATUS_OK);
940 h2 = io.out.file.handle;
941 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
942 CHECK_LEASE(&io, granted, true, LEASE1);
944 if (smb2_util_oplock_level(held) != smb2_util_oplock_level(brokento)) {
945 CHECK_VAL(break_info.oplock_count, 1);
946 CHECK_VAL(break_info.oplock_failures, 0);
947 CHECK_VAL(break_info.oplock_level, smb2_util_oplock_level(brokento));
948 break_info.held_oplock_level = break_info.oplock_level;
949 } else {
950 CHECK_VAL(break_info.oplock_count, 0);
951 CHECK_VAL(break_info.oplock_failures, 0);
954 smb2_util_close(tree, h);
955 smb2_util_close(tree, h2);
957 status = smb2_util_unlink(tree, fname);
958 CHECK_STATUS(status, NT_STATUS_OK);
961 done:
962 smb2_util_close(tree, h);
963 smb2_util_close(tree, h2);
965 smb2_util_unlink(tree, fname);
967 talloc_free(mem_ctx);
969 return ret;
972 static bool test_lease_multibreak(struct torture_context *tctx,
973 struct smb2_tree *tree)
975 TALLOC_CTX *mem_ctx = talloc_new(tctx);
976 struct smb2_create io;
977 struct smb2_lease ls;
978 struct smb2_handle h, h2, h3;
979 struct smb2_write w;
980 NTSTATUS status;
981 const char *fname = "lease.dat";
982 bool ret = true;
983 uint32_t caps;
985 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
986 if (!(caps & SMB2_CAP_LEASING)) {
987 torture_skip(tctx, "leases are not supported");
990 tree->session->transport->lease.handler = torture_lease_handler;
991 tree->session->transport->lease.private_data = tree;
992 tree->session->transport->oplock.handler = torture_oplock_handler;
993 tree->session->transport->oplock.private_data = tree;
995 smb2_util_unlink(tree, fname);
997 ZERO_STRUCT(break_info);
999 /* Grab lease, upgrade to RHW .. */
1000 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RH"));
1001 status = smb2_create(tree, mem_ctx, &io);
1002 CHECK_STATUS(status, NT_STATUS_OK);
1003 h = io.out.file.handle;
1004 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1005 CHECK_LEASE(&io, "RH", true, LEASE1);
1007 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
1008 status = smb2_create(tree, mem_ctx, &io);
1009 CHECK_STATUS(status, NT_STATUS_OK);
1010 h2 = io.out.file.handle;
1011 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1012 CHECK_LEASE(&io, "RHW", true, LEASE1);
1014 /* Contend with LEASE2. */
1015 smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state("RHW"));
1016 status = smb2_create(tree, mem_ctx, &io);
1017 CHECK_STATUS(status, NT_STATUS_OK);
1018 h3 = io.out.file.handle;
1019 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1020 CHECK_LEASE(&io, "RH", true, LEASE2);
1022 /* Verify that we were only sent one break. */
1023 CHECK_BREAK_INFO("RHW", "RH", LEASE1);
1025 /* Drop LEASE1 / LEASE2 */
1026 status = smb2_util_close(tree, h);
1027 CHECK_STATUS(status, NT_STATUS_OK);
1028 status = smb2_util_close(tree, h2);
1029 CHECK_STATUS(status, NT_STATUS_OK);
1030 status = smb2_util_close(tree, h3);
1031 CHECK_STATUS(status, NT_STATUS_OK);
1033 ZERO_STRUCT(break_info);
1035 /* Grab an R lease. */
1036 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("R"));
1037 status = smb2_create(tree, mem_ctx, &io);
1038 CHECK_STATUS(status, NT_STATUS_OK);
1039 h = io.out.file.handle;
1040 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1041 CHECK_LEASE(&io, "R", true, LEASE1);
1043 /* Grab a level-II oplock. */
1044 smb2_oplock_create(&io, fname, smb2_util_oplock_level("s"));
1045 status = smb2_create(tree, mem_ctx, &io);
1046 CHECK_STATUS(status, NT_STATUS_OK);
1047 h2 = io.out.file.handle;
1048 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1049 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
1050 break_info.held_oplock_level = io.out.oplock_level;
1052 /* Verify no breaks. */
1053 CHECK_VAL(break_info.count, 0);
1054 CHECK_VAL(break_info.failures, 0);
1056 /* Open for truncate, force a break. */
1057 smb2_generic_create(&io, NULL, false, fname,
1058 NTCREATEX_DISP_OVERWRITE_IF, smb2_util_oplock_level(""), 0, 0);
1059 status = smb2_create(tree, mem_ctx, &io);
1060 CHECK_STATUS(status, NT_STATUS_OK);
1061 h3 = io.out.file.handle;
1062 CHECK_CREATED(&io, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
1063 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(""));
1064 break_info.held_oplock_level = io.out.oplock_level;
1066 /* Sleep, use a write to clear the recv queue. */
1067 smb_msleep(250);
1068 ZERO_STRUCT(w);
1069 w.in.file.handle = h3;
1070 w.in.offset = 0;
1071 w.in.data = data_blob_talloc(mem_ctx, NULL, 4096);
1072 memset(w.in.data.data, 'o', w.in.data.length);
1073 status = smb2_write(tree, &w);
1074 CHECK_STATUS(status, NT_STATUS_OK);
1076 /* Verify one oplock break, one lease break. */
1077 CHECK_VAL(break_info.oplock_count, 1);
1078 CHECK_VAL(break_info.oplock_failures, 0);
1079 CHECK_VAL(break_info.oplock_level, smb2_util_oplock_level(""));
1080 CHECK_BREAK_INFO("R", "", LEASE1);
1082 done:
1083 smb2_util_close(tree, h);
1084 smb2_util_close(tree, h2);
1085 smb2_util_close(tree, h3);
1087 smb2_util_unlink(tree, fname);
1089 talloc_free(mem_ctx);
1091 return ret;
1094 static bool test_lease_v2_request(struct torture_context *tctx,
1095 struct smb2_tree *tree)
1097 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1098 struct smb2_create io;
1099 struct smb2_lease ls;
1100 struct smb2_handle h1, h2, h3, h4, h5;
1101 struct smb2_write w;
1102 NTSTATUS status;
1103 const char *fname = "lease.dat";
1104 const char *dname = "lease.dir";
1105 const char *dnamefname = "lease.dir\\lease.dat";
1106 const char *dnamefname2 = "lease.dir\\lease2.dat";
1107 bool ret = true;
1109 smb2_util_unlink(tree, fname);
1110 smb2_deltree(tree, dname);
1112 tree->session->transport->lease.handler = torture_lease_handler;
1113 tree->session->transport->lease.private_data = tree;
1114 tree->session->transport->oplock.handler = torture_oplock_handler;
1115 tree->session->transport->oplock.private_data = tree;
1117 ZERO_STRUCT(break_info);
1119 ZERO_STRUCT(io);
1120 smb2_lease_v2_create_share(&io, &ls, false, fname,
1121 smb2_util_share_access("RWD"),
1122 LEASE1, NULL,
1123 smb2_util_lease_state("RHW"),
1126 status = smb2_create(tree, mem_ctx, &io);
1127 CHECK_STATUS(status, NT_STATUS_OK);
1128 h1 = io.out.file.handle;
1129 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1130 CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0);
1132 ZERO_STRUCT(io);
1133 smb2_lease_v2_create_share(&io, &ls, true, dname,
1134 smb2_util_share_access("RWD"),
1135 LEASE2, NULL,
1136 smb2_util_lease_state("RHW"),
1138 status = smb2_create(tree, mem_ctx, &io);
1139 CHECK_STATUS(status, NT_STATUS_OK);
1140 h2 = io.out.file.handle;
1141 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_DIRECTORY);
1142 CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0);
1144 ZERO_STRUCT(io);
1145 smb2_lease_v2_create_share(&io, &ls, false, dnamefname,
1146 smb2_util_share_access("RWD"),
1147 LEASE3, &LEASE2,
1148 smb2_util_lease_state("RHW"),
1150 status = smb2_create(tree, mem_ctx, &io);
1151 CHECK_STATUS(status, NT_STATUS_OK);
1152 h3 = io.out.file.handle;
1153 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1154 CHECK_LEASE_V2(&io, "RHW", true, LEASE3,
1155 SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET);
1157 torture_wait_for_lease_break(tctx);
1158 CHECK_VAL(break_info.count, 0);
1159 CHECK_VAL(break_info.failures, 0);
1161 ZERO_STRUCT(io);
1162 smb2_lease_v2_create_share(&io, &ls, false, dnamefname2,
1163 smb2_util_share_access("RWD"),
1164 LEASE4, NULL,
1165 smb2_util_lease_state("RHW"),
1167 status = smb2_create(tree, mem_ctx, &io);
1168 CHECK_STATUS(status, NT_STATUS_OK);
1169 h4 = io.out.file.handle;
1170 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1171 CHECK_LEASE_V2(&io, "RHW", true, LEASE4, 0);
1173 torture_wait_for_lease_break(tctx);
1174 torture_wait_for_lease_break(tctx);
1175 CHECK_BREAK_INFO("RH", "", LEASE2);
1176 torture_wait_for_lease_break(tctx);
1178 ZERO_STRUCT(break_info);
1180 ZERO_STRUCT(io);
1181 smb2_lease_v2_create_share(&io, &ls, true, dname,
1182 smb2_util_share_access("RWD"),
1183 LEASE2, NULL,
1184 smb2_util_lease_state("RHW"),
1186 io.in.create_disposition = NTCREATEX_DISP_OPEN;
1187 status = smb2_create(tree, mem_ctx, &io);
1188 CHECK_STATUS(status, NT_STATUS_OK);
1189 h5 = io.out.file.handle;
1190 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_DIRECTORY);
1191 CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0);
1192 smb2_util_close(tree, h5);
1194 ZERO_STRUCT(w);
1195 w.in.file.handle = h4;
1196 w.in.offset = 0;
1197 w.in.data = data_blob_talloc(mem_ctx, NULL, 4096);
1198 memset(w.in.data.data, 'o', w.in.data.length);
1199 status = smb2_write(tree, &w);
1200 CHECK_STATUS(status, NT_STATUS_OK);
1202 smb_msleep(2000);
1203 torture_wait_for_lease_break(tctx);
1204 CHECK_VAL(break_info.count, 0);
1205 CHECK_VAL(break_info.failures, 0);
1207 smb2_util_close(tree, h4);
1208 torture_wait_for_lease_break(tctx);
1209 torture_wait_for_lease_break(tctx);
1210 CHECK_BREAK_INFO("RH", "", LEASE2);
1211 torture_wait_for_lease_break(tctx);
1213 done:
1214 smb2_util_close(tree, h1);
1215 smb2_util_close(tree, h2);
1216 smb2_util_close(tree, h3);
1217 smb2_util_close(tree, h4);
1218 smb2_util_close(tree, h5);
1220 smb2_util_unlink(tree, fname);
1221 smb2_deltree(tree, dname);
1223 talloc_free(mem_ctx);
1225 return ret;
1228 struct torture_suite *torture_smb2_lease_init(void)
1230 struct torture_suite *suite =
1231 torture_suite_create(talloc_autofree_context(), "lease");
1233 torture_suite_add_1smb2_test(suite, "request", test_lease_request);
1234 torture_suite_add_1smb2_test(suite, "upgrade", test_lease_upgrade);
1235 torture_suite_add_1smb2_test(suite, "upgrade2", test_lease_upgrade2);
1236 torture_suite_add_1smb2_test(suite, "upgrade3", test_lease_upgrade3);
1237 torture_suite_add_1smb2_test(suite, "break", test_lease_break);
1238 torture_suite_add_1smb2_test(suite, "oplock", test_lease_oplock);
1239 torture_suite_add_1smb2_test(suite, "multibreak", test_lease_multibreak);
1240 torture_suite_add_1smb2_test(suite, "v2_request", test_lease_v2_request);
1242 suite->description = talloc_strdup(suite, "SMB2-LEASE tests");
1244 return suite;