LCOV - code coverage report
Current view: top level - source4/torture/smb2 - oplock.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 2831 3282 86.3 %
Date: 2024-02-28 12:06:22 Functions: 71 77 92.2 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    test suite for SMB2 oplocks
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003
       7             :    Copyright (C) Stefan Metzmacher 2008
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : 
      25             : #include "libcli/smb2/smb2.h"
      26             : #include "libcli/smb2/smb2_calls.h"
      27             : #include "libcli/smb_composite/smb_composite.h"
      28             : #include "libcli/resolve/resolve.h"
      29             : #include "libcli/smb/smbXcli_base.h"
      30             : 
      31             : #include "lib/cmdline/cmdline.h"
      32             : #include "lib/events/events.h"
      33             : 
      34             : #include "param/param.h"
      35             : #include "system/filesys.h"
      36             : 
      37             : #include "torture/torture.h"
      38             : #include "torture/smb2/proto.h"
      39             : #include "torture/smb2/block.h"
      40             : 
      41             : #include "lib/util/sys_rw.h"
      42             : #include "libcli/security/security.h"
      43             : 
      44             : #define CHECK_RANGE(v, min, max) do { \
      45             :         if ((v) < (min) || (v) > (max)) { \
      46             :                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s " \
      47             :                                "got %d - should be between %d and %d\n", \
      48             :                                 __location__, #v, (int)v, (int)min, (int)max); \
      49             :                 ret = false; \
      50             :         }} while (0)
      51             : 
      52             : #define CHECK_STRMATCH(v, correct) do { \
      53             :         if (!v || strstr((v),(correct)) == NULL) { \
      54             :                 torture_result(tctx, TORTURE_FAIL,  "(%s): wrong value for %s "\
      55             :                                "got '%s' - should be '%s'\n", \
      56             :                                 __location__, #v, v?v:"NULL", correct); \
      57             :                 ret = false; \
      58             :         }} while (0)
      59             : 
      60             : #define CHECK_VAL(v, correct) do { \
      61             :         if ((v) != (correct)) { \
      62             :                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s " \
      63             :                                "got 0x%x - should be 0x%x\n", \
      64             :                                 __location__, #v, (int)v, (int)correct); \
      65             :                 ret = false; \
      66             :         }} while (0)
      67             : 
      68             : #define BASEDIR "oplock_test"
      69             : 
      70             : static struct {
      71             :         struct smb2_handle handle;
      72             :         uint8_t level;
      73             :         struct smb2_break br;
      74             :         int count;
      75             :         int failures;
      76             :         NTSTATUS failure_status;
      77             : } break_info;
      78             : 
      79         117 : static void torture_oplock_break_callback(struct smb2_request *req)
      80             : {
      81           0 :         NTSTATUS status;
      82           0 :         struct smb2_break br;
      83             : 
      84         117 :         ZERO_STRUCT(br);
      85         117 :         status = smb2_break_recv(req, &break_info.br);
      86         117 :         if (!NT_STATUS_IS_OK(status)) {
      87           2 :                 break_info.failures++;
      88           2 :                 break_info.failure_status = status;
      89             :         }
      90             : 
      91         117 :         return;
      92             : }
      93             : 
      94             : /* A general oplock break notification handler.  This should be used when a
      95             :  * test expects to break from batch or exclusive to a lower level. */
      96          98 : static bool torture_oplock_handler(struct smb2_transport *transport,
      97             :                                    const struct smb2_handle *handle,
      98             :                                    uint8_t level,
      99             :                                    void *private_data)
     100             : {
     101          98 :         struct smb2_tree *tree = private_data;
     102           0 :         const char *name;
     103           0 :         struct smb2_request *req;
     104          98 :         ZERO_STRUCT(break_info.br);
     105             : 
     106          98 :         break_info.handle       = *handle;
     107          98 :         break_info.level        = level;
     108          98 :         break_info.count++;
     109             : 
     110          98 :         switch (level) {
     111          80 :         case SMB2_OPLOCK_LEVEL_II:
     112          80 :                 name = "level II";
     113          80 :                 break;
     114          18 :         case SMB2_OPLOCK_LEVEL_NONE:
     115          18 :                 name = "none";
     116          18 :                 break;
     117           0 :         default:
     118           0 :                 name = "unknown";
     119           0 :                 break_info.failures++;
     120             :         }
     121          98 :         printf("Acking to %s [0x%02X] in oplock handler\n", name, level);
     122             : 
     123          98 :         break_info.br.in.file.handle    = *handle;
     124          98 :         break_info.br.in.oplock_level   = level;
     125          98 :         break_info.br.in.reserved       = 0;
     126          98 :         break_info.br.in.reserved2      = 0;
     127             : 
     128          98 :         req = smb2_break_send(tree, &break_info.br);
     129          98 :         req->async.fn = torture_oplock_break_callback;
     130          98 :         req->async.private_data = NULL;
     131          98 :         return true;
     132             : }
     133             : 
     134             : /*
     135             :   A handler function for oplock break notifications. Send a break to none
     136             :   request.
     137             : */
     138           3 : static bool torture_oplock_handler_ack_to_none(struct smb2_transport *transport,
     139             :                                                const struct smb2_handle *handle,
     140             :                                                uint8_t level,
     141             :                                                void *private_data)
     142             : {
     143           3 :         struct smb2_tree *tree = private_data;
     144           0 :         struct smb2_request *req;
     145             : 
     146           3 :         break_info.handle = *handle;
     147           3 :         break_info.level = level;
     148           3 :         break_info.count++;
     149             : 
     150           3 :         printf("Acking to none in oplock handler\n");
     151             : 
     152           3 :         ZERO_STRUCT(break_info.br);
     153           3 :         break_info.br.in.file.handle    = *handle;
     154           3 :         break_info.br.in.oplock_level   = SMB2_OPLOCK_LEVEL_NONE;
     155           3 :         break_info.br.in.reserved       = 0;
     156           3 :         break_info.br.in.reserved2      = 0;
     157             : 
     158           3 :         req = smb2_break_send(tree, &break_info.br);
     159           3 :         req->async.fn = torture_oplock_break_callback;
     160           3 :         req->async.private_data = NULL;
     161             : 
     162           3 :         return true;
     163             : }
     164             : 
     165             : /*
     166             :   A handler function for oplock break notifications. Break from level II to
     167             :   none.  SMB2 requires that the client does not send an oplock break request to
     168             :   the server in this case.
     169             : */
     170          24 : static bool torture_oplock_handler_level2_to_none(
     171             :                                                struct smb2_transport *transport,
     172             :                                                const struct smb2_handle *handle,
     173             :                                                uint8_t level,
     174             :                                                void *private_data)
     175             : {
     176          24 :         break_info.handle = *handle;
     177          24 :         break_info.level = level;
     178          24 :         break_info.count++;
     179             : 
     180          24 :         printf("Break from level II to none in oplock handler\n");
     181             : 
     182          24 :         return true;
     183             : }
     184             : 
     185             : /* A handler function for oplock break notifications.  This should be used when
     186             :  * test expects two break notifications, first to level II, then to none. */
     187          24 : static bool torture_oplock_handler_two_notifications(
     188             :                                         struct smb2_transport *transport,
     189             :                                         const struct smb2_handle *handle,
     190             :                                         uint8_t level,
     191             :                                         void *private_data)
     192             : {
     193          24 :         struct smb2_tree *tree = private_data;
     194           0 :         const char *name;
     195           0 :         struct smb2_request *req;
     196          24 :         ZERO_STRUCT(break_info.br);
     197             : 
     198          24 :         break_info.handle       = *handle;
     199          24 :         break_info.level        = level;
     200          24 :         break_info.count++;
     201             : 
     202          24 :         switch (level) {
     203          16 :         case SMB2_OPLOCK_LEVEL_II:
     204          16 :                 name = "level II";
     205          16 :                 break;
     206           8 :         case SMB2_OPLOCK_LEVEL_NONE:
     207           8 :                 name = "none";
     208           8 :                 break;
     209           0 :         default:
     210           0 :                 name = "unknown";
     211           0 :                 break_info.failures++;
     212             :         }
     213          24 :         printf("Breaking to %s [0x%02X] in oplock handler\n", name, level);
     214             : 
     215          24 :         if (level == SMB2_OPLOCK_LEVEL_NONE)
     216           8 :                 return true;
     217             : 
     218          16 :         break_info.br.in.file.handle    = *handle;
     219          16 :         break_info.br.in.oplock_level   = level;
     220          16 :         break_info.br.in.reserved       = 0;
     221          16 :         break_info.br.in.reserved2      = 0;
     222             : 
     223          16 :         req = smb2_break_send(tree, &break_info.br);
     224          16 :         req->async.fn = torture_oplock_break_callback;
     225          16 :         req->async.private_data = NULL;
     226          16 :         return true;
     227             : }
     228           7 : static void torture_oplock_handler_close_recv(struct smb2_request *req)
     229             : {
     230           7 :         if (!smb2_request_receive(req)) {
     231           0 :                 printf("close failed in oplock_handler_close\n");
     232           0 :                 break_info.failures++;
     233             :         }
     234           7 : }
     235             : 
     236             : /*
     237             :   a handler function for oplock break requests - close the file
     238             : */
     239           7 : static bool torture_oplock_handler_close(struct smb2_transport *transport,
     240             :                                          const struct smb2_handle *handle,
     241             :                                          uint8_t level,
     242             :                                          void *private_data)
     243             : {
     244           0 :         struct smb2_close io;
     245           7 :         struct smb2_tree *tree = private_data;
     246           0 :         struct smb2_request *req;
     247             : 
     248           7 :         break_info.handle = *handle;
     249           7 :         break_info.level = level;
     250           7 :         break_info.count++;
     251             : 
     252           7 :         ZERO_STRUCT(io);
     253           7 :         io.in.file.handle       = *handle;
     254           7 :         io.in.flags          = RAW_CLOSE_SMB2;
     255           7 :         req = smb2_close_send(tree, &io);
     256           7 :         if (req == NULL) {
     257           0 :                 printf("failed to send close in oplock_handler_close\n");
     258           0 :                 return false;
     259             :         }
     260             : 
     261           7 :         req->async.fn = torture_oplock_handler_close_recv;
     262           7 :         req->async.private_data = NULL;
     263             : 
     264           7 :         return true;
     265             : }
     266             : 
     267             : /*
     268             :   a handler function for oplock break requests. Let it timeout
     269             : */
     270           5 : static bool torture_oplock_handler_timeout(struct smb2_transport *transport,
     271             :                                            const struct smb2_handle *handle,
     272             :                                            uint8_t level,
     273             :                                            void *private_data)
     274             : {
     275           5 :         break_info.handle = *handle;
     276           5 :         break_info.level = level;
     277           5 :         break_info.count++;
     278             : 
     279           5 :         printf("Let oplock break timeout\n");
     280           5 :         return true;
     281             : }
     282             : 
     283           6 : static bool open_smb2_connection_no_level2_oplocks(struct torture_context *tctx,
     284             :                                                    struct smb2_tree **tree)
     285             : {
     286           0 :         NTSTATUS status;
     287           6 :         const char *host = torture_setting_string(tctx, "host", NULL);
     288           6 :         const char *share = torture_setting_string(tctx, "share", NULL);
     289           0 :         struct smbcli_options options;
     290             : 
     291           6 :         lpcfg_smbcli_options(tctx->lp_ctx, &options);
     292           6 :         options.use_level2_oplocks = false;
     293             : 
     294           6 :         status = smb2_connect(tctx, host,
     295             :                               lpcfg_smb_ports(tctx->lp_ctx), share,
     296             :                               lpcfg_resolve_context(tctx->lp_ctx),
     297             :                               samba_cmdline_get_creds(),
     298             :                               tree, tctx->ev, &options,
     299             :                               lpcfg_socket_options(tctx->lp_ctx),
     300             :                               lpcfg_gensec_settings(tctx, tctx->lp_ctx));
     301           6 :         if (!NT_STATUS_IS_OK(status)) {
     302           0 :                 torture_comment(tctx, "Failed to connect to SMB2 share "
     303             :                                 "\\\\%s\\%s - %s\n", host, share,
     304             :                                 nt_errstr(status));
     305           0 :                 return false;
     306             :         }
     307           6 :         return true;
     308             : }
     309             : 
     310           3 : static bool test_smb2_oplock_exclusive1(struct torture_context *tctx,
     311             :                                         struct smb2_tree *tree1,
     312             :                                         struct smb2_tree *tree2)
     313             : {
     314           3 :         const char *fname = BASEDIR "\\test_exclusive1.dat";
     315           0 :         NTSTATUS status;
     316           3 :         bool ret = true;
     317           0 :         union smb_open io;
     318           0 :         struct smb2_handle h1;
     319           0 :         struct smb2_handle h;
     320             : 
     321           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     322           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     323             : 
     324             :         /* cleanup */
     325           3 :         smb2_util_unlink(tree1, fname);
     326             : 
     327           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     328           3 :         tree1->session->transport->oplock.private_data = tree1;
     329             : 
     330             :         /*
     331             :           base ntcreatex parms
     332             :         */
     333           3 :         ZERO_STRUCT(io.smb2);
     334           3 :         io.generic.level = RAW_OPEN_SMB2;
     335           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     336           3 :         io.smb2.in.alloc_size = 0;
     337           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     338           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     339           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     340           3 :         io.smb2.in.create_options = 0;
     341           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     342           3 :         io.smb2.in.security_flags = 0;
     343           3 :         io.smb2.in.fname = fname;
     344             : 
     345           3 :         torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive "
     346             :                         "oplock (share mode: none)\n");
     347           3 :         ZERO_STRUCT(break_info);
     348           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     349             : 
     350           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
     351           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     352           3 :         h1 = io.smb2.out.file.handle;
     353           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     354             : 
     355           3 :         torture_comment(tctx, "a 2nd open should not cause a break\n");
     356           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
     357           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     358             :                                       "Incorrect status");
     359           3 :         torture_wait_for_oplock_break(tctx);
     360           3 :         CHECK_VAL(break_info.count, 0);
     361           3 :         CHECK_VAL(break_info.failures, 0);
     362             : 
     363           3 :         torture_comment(tctx, "unlink it - should also be no break\n");
     364           3 :         status = smb2_util_unlink(tree2, fname);
     365           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     366             :                                       "Incorrect status");
     367           3 :         torture_wait_for_oplock_break(tctx);
     368           3 :         CHECK_VAL(break_info.count, 0);
     369           3 :         CHECK_VAL(break_info.failures, 0);
     370             : 
     371           3 :         smb2_util_close(tree1, h1);
     372           3 :         smb2_util_close(tree1, h);
     373             : 
     374           3 :         smb2_deltree(tree1, BASEDIR);
     375           3 :         return ret;
     376             : }
     377             : 
     378           3 : static bool test_smb2_oplock_exclusive2(struct torture_context *tctx,
     379             :                                         struct smb2_tree *tree1,
     380             :                                         struct smb2_tree *tree2)
     381             : {
     382           3 :         const char *fname = BASEDIR "\\test_exclusive2.dat";
     383           0 :         NTSTATUS status;
     384           3 :         bool ret = true;
     385           0 :         union smb_open io;
     386           0 :         struct smb2_handle h, h1, h2;
     387             : 
     388           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     389           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     390             : 
     391             :         /* cleanup */
     392           3 :         smb2_util_unlink(tree1, fname);
     393             : 
     394           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     395           3 :         tree1->session->transport->oplock.private_data = tree1;
     396             : 
     397             :         /*
     398             :           base ntcreatex parms
     399             :         */
     400           3 :         ZERO_STRUCT(io.smb2);
     401           3 :         io.generic.level = RAW_OPEN_SMB2;
     402           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     403           3 :         io.smb2.in.alloc_size = 0;
     404           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     405           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     406           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     407           3 :         io.smb2.in.create_options = 0;
     408           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     409           3 :         io.smb2.in.security_flags = 0;
     410           3 :         io.smb2.in.fname = fname;
     411             : 
     412           3 :         torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive "
     413             :                         "oplock (share mode: all)\n");
     414           3 :         ZERO_STRUCT(break_info);
     415           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     416           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
     417             :                 NTCREATEX_SHARE_ACCESS_WRITE|
     418             :                 NTCREATEX_SHARE_ACCESS_DELETE;
     419           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     420             : 
     421           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
     422           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     423           3 :         h1 = io.smb2.out.file.handle;
     424           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     425             : 
     426           3 :         torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
     427           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
     428           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     429           3 :         h2 = io.smb2.out.file.handle;
     430           3 :         torture_wait_for_oplock_break(tctx);
     431           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
     432           3 :         CHECK_VAL(break_info.count, 1);
     433           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
     434           3 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
     435           3 :         CHECK_VAL(break_info.failures, 0);
     436           3 :         ZERO_STRUCT(break_info);
     437             : 
     438             :         /* now we have 2 level II oplocks... */
     439           3 :         torture_comment(tctx, "try to unlink it - should cause a break\n");
     440           3 :         status = smb2_util_unlink(tree2, fname);
     441           3 :         torture_assert_ntstatus_ok(tctx, status, "Error unlinking the file");
     442           2 :         torture_wait_for_oplock_break(tctx);
     443           2 :         CHECK_VAL(break_info.count, 0);
     444           2 :         CHECK_VAL(break_info.failures, 0);
     445             : 
     446           2 :         torture_comment(tctx, "close both handles\n");
     447           2 :         smb2_util_close(tree1, h1);
     448           2 :         smb2_util_close(tree1, h2);
     449           2 :         smb2_util_close(tree1, h);
     450             : 
     451           2 :         smb2_deltree(tree1, BASEDIR);
     452           2 :         return ret;
     453             : }
     454             : 
     455           3 : static bool test_smb2_oplock_exclusive3(struct torture_context *tctx,
     456             :                                         struct smb2_tree *tree1,
     457             :                                         struct smb2_tree *tree2)
     458             : {
     459           3 :         const char *fname = BASEDIR "\\test_exclusive3.dat";
     460           0 :         NTSTATUS status;
     461           3 :         bool ret = true;
     462           0 :         union smb_open io;
     463           0 :         union smb_setfileinfo sfi;
     464           0 :         struct smb2_handle h, h1;
     465             : 
     466           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     467           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     468             : 
     469             :         /* cleanup */
     470           3 :         smb2_util_unlink(tree1, fname);
     471             : 
     472           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     473           3 :         tree1->session->transport->oplock.private_data = tree1;
     474             : 
     475             :         /*
     476             :           base ntcreatex parms
     477             :         */
     478           3 :         ZERO_STRUCT(io.smb2);
     479           3 :         io.generic.level = RAW_OPEN_SMB2;
     480           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     481           3 :         io.smb2.in.alloc_size = 0;
     482           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     483           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     484           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     485           3 :         io.smb2.in.create_options = 0;
     486           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     487           3 :         io.smb2.in.security_flags = 0;
     488           3 :         io.smb2.in.fname = fname;
     489             : 
     490           3 :         torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive "
     491             :                         "oplock (share mode: none)\n");
     492             : 
     493           3 :         ZERO_STRUCT(break_info);
     494           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     495           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     496             : 
     497           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
     498           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     499           3 :         h1 = io.smb2.out.file.handle;
     500           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     501             : 
     502           3 :         torture_comment(tctx, "setpathinfo EOF should trigger a break to "
     503             :                         "none\n");
     504           3 :         ZERO_STRUCT(sfi);
     505           3 :         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
     506           3 :         sfi.generic.in.file.path = fname;
     507           3 :         sfi.end_of_file_info.in.size = 100;
     508             : 
     509           3 :         status = smb2_composite_setpathinfo(tree2, &sfi);
     510             : 
     511           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     512             :                                       "Incorrect status");
     513           3 :         torture_wait_for_oplock_break(tctx);
     514           3 :         CHECK_VAL(break_info.count, 0);
     515           3 :         CHECK_VAL(break_info.failures, 0);
     516           3 :         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
     517             : 
     518           3 :         smb2_util_close(tree1, h1);
     519           3 :         smb2_util_close(tree1, h);
     520             : 
     521           3 :         smb2_deltree(tree1, BASEDIR);
     522           3 :         return ret;
     523             : }
     524             : 
     525           3 : static bool test_smb2_oplock_exclusive4(struct torture_context *tctx,
     526             :                                         struct smb2_tree *tree1,
     527             :                                         struct smb2_tree *tree2)
     528             : {
     529           3 :         const char *fname = BASEDIR "\\test_exclusive4.dat";
     530           0 :         NTSTATUS status;
     531           3 :         bool ret = true;
     532           0 :         union smb_open io;
     533           0 :         struct smb2_handle h, h1, h2;
     534             : 
     535           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     536           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     537             : 
     538             :         /* cleanup */
     539           3 :         smb2_util_unlink(tree1, fname);
     540             : 
     541           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     542           3 :         tree1->session->transport->oplock.private_data = tree1;
     543             : 
     544             :         /*
     545             :           base ntcreatex parms
     546             :         */
     547           3 :         ZERO_STRUCT(io.smb2);
     548           3 :         io.generic.level = RAW_OPEN_SMB2;
     549           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     550           3 :         io.smb2.in.alloc_size = 0;
     551           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     552           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     553           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     554           3 :         io.smb2.in.create_options = 0;
     555           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     556           3 :         io.smb2.in.security_flags = 0;
     557           3 :         io.smb2.in.fname = fname;
     558             : 
     559           3 :         torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
     560           3 :         ZERO_STRUCT(break_info);
     561             : 
     562           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     563           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     564           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
     565           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     566           3 :         h1 = io.smb2.out.file.handle;
     567           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     568             : 
     569           3 :         ZERO_STRUCT(break_info);
     570           3 :         torture_comment(tctx, "second open with attributes only shouldn't "
     571             :                         "cause oplock break\n");
     572             : 
     573           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     574           3 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
     575             :                                 SEC_FILE_WRITE_ATTRIBUTE |
     576             :                                 SEC_STD_SYNCHRONIZE;
     577           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     578           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
     579           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
     580           3 :         h2 = io.smb2.out.file.handle;
     581           3 :         CHECK_VAL(io.smb2.out.oplock_level, NO_OPLOCK_RETURN);
     582           3 :         torture_wait_for_oplock_break(tctx);
     583           3 :         CHECK_VAL(break_info.count, 0);
     584           3 :         CHECK_VAL(break_info.failures, 0);
     585             : 
     586           3 :         smb2_util_close(tree1, h1);
     587           3 :         smb2_util_close(tree2, h2);
     588           3 :         smb2_util_close(tree1, h);
     589             : 
     590           3 :         smb2_deltree(tree1, BASEDIR);
     591           3 :         return ret;
     592             : }
     593             : 
     594           3 : static bool test_smb2_oplock_exclusive5(struct torture_context *tctx,
     595             :                                         struct smb2_tree *tree1,
     596             :                                         struct smb2_tree *tree2)
     597             : {
     598           3 :         const char *fname = BASEDIR "\\test_exclusive5.dat";
     599           0 :         NTSTATUS status;
     600           3 :         bool ret = true;
     601           0 :         union smb_open io;
     602           0 :         struct smb2_handle h, h1, h2;
     603             : 
     604           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     605           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     606             : 
     607             :         /* cleanup */
     608           3 :         smb2_util_unlink(tree1, fname);
     609             : 
     610           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     611           3 :         tree1->session->transport->oplock.private_data = tree1;
     612             : 
     613           3 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
     614           3 :         tree2->session->transport->oplock.private_data = tree2;
     615             : 
     616             :         /*
     617             :           base ntcreatex parms
     618             :         */
     619           3 :         ZERO_STRUCT(io.smb2);
     620           3 :         io.generic.level = RAW_OPEN_SMB2;
     621           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     622           3 :         io.smb2.in.alloc_size = 0;
     623           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     624           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     625           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     626           3 :         io.smb2.in.create_options = 0;
     627           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     628           3 :         io.smb2.in.security_flags = 0;
     629           3 :         io.smb2.in.fname = fname;
     630             : 
     631           3 :         torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
     632           3 :         ZERO_STRUCT(break_info);
     633             : 
     634           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     635           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
     636             :                 NTCREATEX_SHARE_ACCESS_WRITE|
     637             :                 NTCREATEX_SHARE_ACCESS_DELETE;
     638           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     639           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
     640           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     641           3 :         h1 = io.smb2.out.file.handle;
     642           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     643             : 
     644           3 :         ZERO_STRUCT(break_info);
     645             : 
     646           3 :         torture_comment(tctx, "second open with attributes only and "
     647             :                         "NTCREATEX_DISP_OVERWRITE_IF disposition causes "
     648             :                         "oplock break\n");
     649             : 
     650           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     651           3 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
     652             :                                 SEC_FILE_WRITE_ATTRIBUTE |
     653             :                                 SEC_STD_SYNCHRONIZE;
     654           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
     655           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
     656           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
     657           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
     658           3 :         h2 = io.smb2.out.file.handle;
     659           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
     660           3 :         torture_wait_for_oplock_break(tctx);
     661           3 :         CHECK_VAL(break_info.count, 1);
     662           3 :         CHECK_VAL(break_info.failures, 0);
     663             : 
     664           3 :         smb2_util_close(tree1, h1);
     665           3 :         smb2_util_close(tree2, h2);
     666           3 :         smb2_util_close(tree1, h);
     667             : 
     668           3 :         smb2_deltree(tree1, BASEDIR);
     669           3 :         return ret;
     670             : }
     671             : 
     672           3 : static bool test_smb2_oplock_exclusive6(struct torture_context *tctx,
     673             :                                         struct smb2_tree *tree1,
     674             :                                         struct smb2_tree *tree2)
     675             : {
     676           3 :         const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
     677           3 :         const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
     678           0 :         NTSTATUS status;
     679           3 :         bool ret = true;
     680           0 :         union smb_open io;
     681           0 :         union smb_setfileinfo sinfo;
     682           0 :         struct smb2_close closeio;
     683           0 :         struct smb2_handle h, h1;
     684             : 
     685           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     686           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     687             : 
     688             :         /* cleanup */
     689           3 :         smb2_util_unlink(tree1, fname1);
     690           3 :         smb2_util_unlink(tree2, fname2);
     691             : 
     692           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     693           3 :         tree1->session->transport->oplock.private_data = tree1;
     694             : 
     695             :         /*
     696             :           base ntcreatex parms
     697             :         */
     698           3 :         ZERO_STRUCT(io.smb2);
     699           3 :         io.generic.level = RAW_OPEN_SMB2;
     700           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     701           3 :         io.smb2.in.alloc_size = 0;
     702           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     703           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     704           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     705           3 :         io.smb2.in.create_options = 0;
     706           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     707           3 :         io.smb2.in.security_flags = 0;
     708           3 :         io.smb2.in.fname = fname1;
     709             : 
     710           3 :         torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
     711             :                         "oplock (share mode: none)\n");
     712           3 :         ZERO_STRUCT(break_info);
     713           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     714           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     715             : 
     716           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
     717           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     718           3 :         h1 = io.smb2.out.file.handle;
     719           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     720             : 
     721           3 :         torture_comment(tctx, "rename with the parent directory handle open "
     722             :                         "for DELETE should not generate a break but get "
     723             :                         "a sharing violation\n");
     724           3 :         ZERO_STRUCT(sinfo);
     725           3 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     726           3 :         sinfo.rename_information.in.file.handle = h1;
     727           3 :         sinfo.rename_information.in.overwrite = true;
     728           3 :         sinfo.rename_information.in.new_name = fname2;
     729           3 :         status = smb2_setinfo_file(tree1, &sinfo);
     730             : 
     731           3 :         torture_comment(tctx, "trying rename while parent handle open for delete.\n");
     732           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     733             :                                       "Incorrect status");
     734           2 :         torture_wait_for_oplock_break(tctx);
     735           2 :         CHECK_VAL(break_info.count, 0);
     736           2 :         CHECK_VAL(break_info.failures, 0);
     737             : 
     738             :         /* Close the parent directory handle. */
     739           2 :         ZERO_STRUCT(closeio);
     740           2 :         closeio.in.file.handle = h;
     741           2 :         status = smb2_close(tree1, &closeio);
     742           2 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
     743             :                                       "Incorrect status");
     744             : 
     745             :         /* Re-open without DELETE access. */
     746           2 :         ZERO_STRUCT(io);
     747           2 :         io.smb2.in.oplock_level = 0;
     748           2 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL & (~SEC_STD_DELETE);
     749           2 :         io.smb2.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
     750           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
     751           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
     752           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     753           2 :         io.smb2.in.fname = BASEDIR;
     754             : 
     755           2 :         status = smb2_create(tree1, tctx, &(io.smb2));
     756           2 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the base directory");
     757             : 
     758           2 :         torture_comment(tctx, "rename with the parent directory handle open "
     759             :                         "without DELETE should succeed without a break\n");
     760           2 :         ZERO_STRUCT(sinfo);
     761           2 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     762           2 :         sinfo.rename_information.in.file.handle = h1;
     763           2 :         sinfo.rename_information.in.overwrite = true;
     764           2 :         sinfo.rename_information.in.new_name = fname2;
     765           2 :         status = smb2_setinfo_file(tree1, &sinfo);
     766             : 
     767           2 :         torture_comment(tctx, "trying rename while parent handle open without delete\n");
     768           2 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
     769             :                                       "Incorrect status");
     770           2 :         torture_wait_for_oplock_break(tctx);
     771           2 :         CHECK_VAL(break_info.count, 0);
     772           2 :         CHECK_VAL(break_info.failures, 0);
     773             : 
     774           2 :         smb2_util_close(tree1, h1);
     775           2 :         smb2_util_close(tree1, h);
     776             : 
     777           2 :         smb2_deltree(tree1, BASEDIR);
     778           2 :         return ret;
     779             : }
     780             : 
     781           3 : static bool test_smb2_oplock_exclusive9(struct torture_context *tctx,
     782             :                                         struct smb2_tree *tree1,
     783             :                                         struct smb2_tree *tree2)
     784             : {
     785           3 :         const char *fname = BASEDIR "\\test_exclusive9.dat";
     786           0 :         NTSTATUS status;
     787           3 :         bool ret = true;
     788           0 :         union smb_open io;
     789           0 :         struct smb2_handle h1, h2;
     790           0 :         int i;
     791             : 
     792           0 :         struct {
     793             :                 uint32_t create_disposition;
     794             :                 uint32_t break_level;
     795           3 :         } levels[] = {
     796             :                 { NTCREATEX_DISP_SUPERSEDE, SMB2_OPLOCK_LEVEL_NONE },
     797             :                 { NTCREATEX_DISP_OPEN, SMB2_OPLOCK_LEVEL_II },
     798             :                 { NTCREATEX_DISP_OVERWRITE_IF, SMB2_OPLOCK_LEVEL_NONE },
     799             :                 { NTCREATEX_DISP_OPEN_IF, SMB2_OPLOCK_LEVEL_II },
     800             :         };
     801             : 
     802             : 
     803           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h1);
     804           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     805           3 :         smb2_util_close(tree1, h1);
     806             : 
     807             :         /* cleanup */
     808           3 :         smb2_util_unlink(tree1, fname);
     809             : 
     810           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     811           3 :         tree1->session->transport->oplock.private_data = tree1;
     812             : 
     813             :         /*
     814             :           base ntcreatex parms
     815             :         */
     816           3 :         ZERO_STRUCT(io.smb2);
     817           3 :         io.generic.level = RAW_OPEN_SMB2;
     818           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     819           3 :         io.smb2.in.alloc_size = 0;
     820           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     821           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     822             :                 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
     823           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     824           3 :         io.smb2.in.create_options = 0;
     825           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     826           3 :         io.smb2.in.security_flags = 0;
     827           3 :         io.smb2.in.fname = fname;
     828             : 
     829          15 :         for (i=0; i<ARRAY_SIZE(levels); i++) {
     830             : 
     831          12 :                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     832          12 :                 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     833             : 
     834          12 :                 status = smb2_create(tree1, tctx, &(io.smb2));
     835          12 :                 torture_assert_ntstatus_ok(tctx, status,
     836             :                                            "Error opening the file");
     837          12 :                 h1 = io.smb2.out.file.handle;
     838          12 :                 CHECK_VAL(io.smb2.out.oplock_level,
     839             :                           SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     840             : 
     841          12 :                 ZERO_STRUCT(break_info);
     842             : 
     843          12 :                 io.smb2.in.create_disposition = levels[i].create_disposition;
     844          12 :                 status = smb2_create(tree2, tctx, &(io.smb2));
     845          12 :                 torture_assert_ntstatus_ok(tctx, status,
     846             :                                            "Error opening the file");
     847          12 :                 h2 = io.smb2.out.file.handle;
     848          12 :                 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
     849             : 
     850          12 :                 CHECK_VAL(break_info.count, 1);
     851          12 :                 CHECK_VAL(break_info.level, levels[i].break_level);
     852          12 :                 CHECK_VAL(break_info.failures, 0);
     853             : 
     854          12 :                 smb2_util_close(tree2, h2);
     855          12 :                 smb2_util_close(tree1, h1);
     856             :         }
     857             : 
     858           3 :         smb2_deltree(tree1, BASEDIR);
     859           3 :         return ret;
     860             : }
     861             : 
     862           3 : static bool test_smb2_oplock_batch1(struct torture_context *tctx,
     863             :                                     struct smb2_tree *tree1,
     864             :                                     struct smb2_tree *tree2)
     865             : {
     866           3 :         const char *fname = BASEDIR "\\test_batch1.dat";
     867           0 :         NTSTATUS status;
     868           3 :         bool ret = true;
     869           0 :         union smb_open io;
     870           0 :         struct smb2_handle h, h1;
     871           3 :         char c = 0;
     872             : 
     873           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     874           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     875             : 
     876             :         /* cleanup */
     877           3 :         smb2_util_unlink(tree1, fname);
     878             : 
     879           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     880           3 :         tree1->session->transport->oplock.private_data = tree1;
     881             : 
     882             :         /*
     883             :           base ntcreatex parms
     884             :         */
     885           3 :         ZERO_STRUCT(io.smb2);
     886           3 :         io.generic.level = RAW_OPEN_SMB2;
     887           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     888           3 :         io.smb2.in.alloc_size = 0;
     889           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     890           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     891           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     892           3 :         io.smb2.in.create_options = 0;
     893           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     894           3 :         io.smb2.in.security_flags = 0;
     895           3 :         io.smb2.in.fname = fname;
     896             : 
     897             :         /*
     898             :           with a batch oplock we get a break
     899             :         */
     900           3 :         torture_comment(tctx, "BATCH1: open with batch oplock\n");
     901           3 :         ZERO_STRUCT(break_info);
     902           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     903           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
     904           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
     905           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     906           3 :         h1 = io.smb2.out.file.handle;
     907           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
     908             : 
     909           3 :         torture_comment(tctx, "unlink should generate a break\n");
     910           3 :         status = smb2_util_unlink(tree2, fname);
     911           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     912             :                                       "Incorrect status");
     913             : 
     914           3 :         torture_wait_for_oplock_break(tctx);
     915           3 :         CHECK_VAL(break_info.count, 1);
     916           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
     917           3 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
     918           3 :         CHECK_VAL(break_info.failures, 0);
     919             : 
     920           3 :         torture_comment(tctx, "2nd unlink should not generate a break\n");
     921           3 :         ZERO_STRUCT(break_info);
     922           3 :         status = smb2_util_unlink(tree2, fname);
     923           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     924             :                                       "Incorrect status");
     925             : 
     926           3 :         torture_wait_for_oplock_break(tctx);
     927           3 :         CHECK_VAL(break_info.count, 0);
     928             : 
     929           3 :         torture_comment(tctx, "writing should generate a self break to none\n");
     930           3 :         tree1->session->transport->oplock.handler =
     931             :             torture_oplock_handler_level2_to_none;
     932           3 :         smb2_util_write(tree1, h1, &c, 0, 1);
     933             : 
     934           3 :         torture_wait_for_oplock_break(tctx);
     935             : 
     936           3 :         CHECK_VAL(break_info.count, 1);
     937           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
     938           3 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
     939           3 :         CHECK_VAL(break_info.failures, 0);
     940             : 
     941           3 :         smb2_util_close(tree1, h1);
     942           3 :         smb2_util_close(tree1, h);
     943             : 
     944           3 :         smb2_deltree(tree1, BASEDIR);
     945           3 :         return ret;
     946             : }
     947             : 
     948           3 : static bool test_smb2_oplock_batch2(struct torture_context *tctx,
     949             :                                     struct smb2_tree *tree1,
     950             :                                     struct smb2_tree *tree2)
     951             : {
     952           3 :         const char *fname = BASEDIR "\\test_batch2.dat";
     953           0 :         NTSTATUS status;
     954           3 :         bool ret = true;
     955           0 :         union smb_open io;
     956           3 :         char c = 0;
     957           0 :         struct smb2_handle h, h1;
     958             : 
     959           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     960           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     961             : 
     962             :         /* cleanup */
     963           3 :         smb2_util_unlink(tree1, fname);
     964             : 
     965           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     966           3 :         tree1->session->transport->oplock.private_data = tree1;
     967             : 
     968             :         /*
     969             :           base ntcreatex parms
     970             :         */
     971           3 :         ZERO_STRUCT(io.smb2);
     972           3 :         io.generic.level = RAW_OPEN_SMB2;
     973           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     974           3 :         io.smb2.in.alloc_size = 0;
     975           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     976           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     977           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     978           3 :         io.smb2.in.create_options = 0;
     979           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     980           3 :         io.smb2.in.security_flags = 0;
     981           3 :         io.smb2.in.fname = fname;
     982             : 
     983           3 :         torture_comment(tctx, "BATCH2: open with batch oplock\n");
     984           3 :         ZERO_STRUCT(break_info);
     985           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     986           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
     987           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
     988           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     989           3 :         h1 = io.smb2.out.file.handle;
     990           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
     991             : 
     992           3 :         torture_comment(tctx, "unlink should generate a break, which we ack "
     993             :                         "as break to none\n");
     994           3 :         tree1->session->transport->oplock.handler =
     995             :                                 torture_oplock_handler_ack_to_none;
     996           3 :         tree1->session->transport->oplock.private_data = tree1;
     997           3 :         status = smb2_util_unlink(tree2, fname);
     998           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     999             :                                      "Incorrect status");
    1000             : 
    1001           3 :         torture_wait_for_oplock_break(tctx);
    1002           3 :         CHECK_VAL(break_info.count, 1);
    1003           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    1004           3 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    1005           3 :         CHECK_VAL(break_info.failures, 0);
    1006             : 
    1007           3 :         torture_comment(tctx, "2nd unlink should not generate a break\n");
    1008           3 :         ZERO_STRUCT(break_info);
    1009           3 :         status = smb2_util_unlink(tree2, fname);
    1010           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
    1011             :                                       "Incorrect status");
    1012             : 
    1013           3 :         torture_wait_for_oplock_break(tctx);
    1014           3 :         CHECK_VAL(break_info.count, 0);
    1015             : 
    1016           3 :         torture_comment(tctx, "writing should not generate a break\n");
    1017           3 :         smb2_util_write(tree1, h1, &c, 0, 1);
    1018             : 
    1019           3 :         torture_wait_for_oplock_break(tctx);
    1020           3 :         CHECK_VAL(break_info.count, 0);
    1021             : 
    1022           3 :         smb2_util_close(tree1, h1);
    1023           3 :         smb2_util_close(tree1, h);
    1024             : 
    1025           3 :         smb2_deltree(tree1, BASEDIR);
    1026           3 :         return ret;
    1027             : }
    1028             : 
    1029           3 : static bool test_smb2_oplock_batch3(struct torture_context *tctx,
    1030             :                                     struct smb2_tree *tree1,
    1031             :                                     struct smb2_tree *tree2)
    1032             : {
    1033           3 :         const char *fname = BASEDIR "\\test_batch3.dat";
    1034           0 :         NTSTATUS status;
    1035           3 :         bool ret = true;
    1036           0 :         union smb_open io;
    1037           0 :         struct smb2_handle h, h1;
    1038             : 
    1039           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1040           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1041             : 
    1042             :         /* cleanup */
    1043           3 :         smb2_util_unlink(tree1, fname);
    1044           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1045           3 :         tree1->session->transport->oplock.private_data = tree1;
    1046             : 
    1047             :         /*
    1048             :           base ntcreatex parms
    1049             :         */
    1050           3 :         ZERO_STRUCT(io.smb2);
    1051           3 :         io.generic.level = RAW_OPEN_SMB2;
    1052           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1053           3 :         io.smb2.in.alloc_size = 0;
    1054           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1055           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1056           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1057           3 :         io.smb2.in.create_options = 0;
    1058           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1059           3 :         io.smb2.in.security_flags = 0;
    1060           3 :         io.smb2.in.fname = fname;
    1061             : 
    1062           3 :         torture_comment(tctx, "BATCH3: if we close on break then the unlink "
    1063             :                         "can succeed\n");
    1064           3 :         ZERO_STRUCT(break_info);
    1065           3 :         tree1->session->transport->oplock.handler =
    1066             :                                         torture_oplock_handler_close;
    1067           3 :         tree1->session->transport->oplock.private_data = tree1;
    1068             : 
    1069           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1070           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1071           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1072           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1073           3 :         h1 = io.smb2.out.file.handle;
    1074           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1075             : 
    1076           3 :         ZERO_STRUCT(break_info);
    1077           3 :         status = smb2_util_unlink(tree2, fname);
    1078           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1079             : 
    1080           3 :         torture_wait_for_oplock_break(tctx);
    1081           3 :         CHECK_VAL(break_info.count, 1);
    1082           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    1083           3 :         CHECK_VAL(break_info.level, 1);
    1084           3 :         CHECK_VAL(break_info.failures, 0);
    1085             : 
    1086           3 :         smb2_util_close(tree1, h1);
    1087           3 :         smb2_util_close(tree1, h);
    1088             : 
    1089           3 :         smb2_deltree(tree1, BASEDIR);
    1090           3 :         return ret;
    1091             : }
    1092             : 
    1093           3 : static bool test_smb2_oplock_batch4(struct torture_context *tctx,
    1094             :                                     struct smb2_tree *tree1,
    1095             :                                     struct smb2_tree *tree2)
    1096             : {
    1097           3 :         const char *fname = BASEDIR "\\test_batch4.dat";
    1098           0 :         NTSTATUS status;
    1099           3 :         bool ret = true;
    1100           0 :         union smb_open io;
    1101           0 :         struct smb2_read r;
    1102           0 :         struct smb2_handle h, h1;
    1103             : 
    1104           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1105           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1106             : 
    1107             :         /* cleanup */
    1108           3 :         smb2_util_unlink(tree1, fname);
    1109             : 
    1110           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1111           3 :         tree1->session->transport->oplock.private_data = tree1;
    1112             : 
    1113             :         /*
    1114             :           base ntcreatex parms
    1115             :         */
    1116           3 :         ZERO_STRUCT(io.smb2);
    1117           3 :         io.generic.level = RAW_OPEN_SMB2;
    1118           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1119           3 :         io.smb2.in.alloc_size = 0;
    1120           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1121           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1122           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1123           3 :         io.smb2.in.create_options = 0;
    1124           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1125           3 :         io.smb2.in.security_flags = 0;
    1126           3 :         io.smb2.in.fname = fname;
    1127             : 
    1128           3 :         torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
    1129           3 :         ZERO_STRUCT(break_info);
    1130             : 
    1131           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1132           3 :         tree1->session->transport->oplock.private_data = tree1;
    1133             : 
    1134           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1135           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1136           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1137           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1138           3 :         h1 = io.smb2.out.file.handle;
    1139           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1140             : 
    1141           3 :         ZERO_STRUCT(r);
    1142           3 :         r.in.file.handle = h1;
    1143           3 :         r.in.offset      = 0;
    1144             : 
    1145           3 :         status = smb2_read(tree1, tree1, &r);
    1146           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1147           3 :         torture_wait_for_oplock_break(tctx);
    1148           3 :         CHECK_VAL(break_info.count, 0);
    1149           3 :         CHECK_VAL(break_info.failures, 0);
    1150             : 
    1151           3 :         smb2_util_close(tree1, h1);
    1152           3 :         smb2_util_close(tree1, h);
    1153             : 
    1154           3 :         smb2_deltree(tree1, BASEDIR);
    1155           3 :         return ret;
    1156             : }
    1157             : 
    1158           3 : static bool test_smb2_oplock_batch5(struct torture_context *tctx,
    1159             :                                     struct smb2_tree *tree1,
    1160             :                                     struct smb2_tree *tree2)
    1161             : {
    1162           3 :         const char *fname = BASEDIR "\\test_batch5.dat";
    1163           0 :         NTSTATUS status;
    1164           3 :         bool ret = true;
    1165           0 :         union smb_open io;
    1166           0 :         struct smb2_handle h, h1;
    1167             : 
    1168           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1169           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1170             : 
    1171             :         /* cleanup */
    1172           3 :         smb2_util_unlink(tree1, fname);
    1173             : 
    1174           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1175           3 :         tree1->session->transport->oplock.private_data = tree1;
    1176             : 
    1177             :         /*
    1178             :           base ntcreatex parms
    1179             :         */
    1180           3 :         ZERO_STRUCT(io.smb2);
    1181           3 :         io.generic.level = RAW_OPEN_SMB2;
    1182           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1183           3 :         io.smb2.in.alloc_size = 0;
    1184           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1185           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1186           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1187           3 :         io.smb2.in.create_options = 0;
    1188           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1189           3 :         io.smb2.in.security_flags = 0;
    1190           3 :         io.smb2.in.fname = fname;
    1191             : 
    1192           3 :         torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
    1193           3 :         ZERO_STRUCT(break_info);
    1194             : 
    1195           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1196           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1197           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1198           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1199           3 :         h1 = io.smb2.out.file.handle;
    1200           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1201             : 
    1202           3 :         ZERO_STRUCT(break_info);
    1203             : 
    1204           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1205           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1206           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
    1207             :                                       "Incorrect status");
    1208             : 
    1209           3 :         torture_wait_for_oplock_break(tctx);
    1210           3 :         CHECK_VAL(break_info.count, 1);
    1211           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    1212           3 :         CHECK_VAL(break_info.level, 1);
    1213           3 :         CHECK_VAL(break_info.failures, 0);
    1214             : 
    1215           3 :         smb2_util_close(tree1, h1);
    1216           3 :         smb2_util_close(tree1, h);
    1217             : 
    1218           3 :         smb2_deltree(tree1, BASEDIR);
    1219           3 :         return ret;
    1220             : }
    1221             : 
    1222           3 : static bool test_smb2_oplock_batch6(struct torture_context *tctx,
    1223             :                                     struct smb2_tree *tree1,
    1224             :                                     struct smb2_tree *tree2)
    1225             : {
    1226           3 :         const char *fname = BASEDIR "\\test_batch6.dat";
    1227           0 :         NTSTATUS status;
    1228           3 :         bool ret = true;
    1229           0 :         union smb_open io;
    1230           0 :         struct smb2_handle h, h1, h2;
    1231           3 :         char c = 0;
    1232             : 
    1233           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1234           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1235             : 
    1236             :         /* cleanup */
    1237           3 :         smb2_util_unlink(tree1, fname);
    1238             : 
    1239           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1240           3 :         tree1->session->transport->oplock.private_data = tree1;
    1241             : 
    1242             :         /*
    1243             :           base ntcreatex parms
    1244             :         */
    1245           3 :         ZERO_STRUCT(io.smb2);
    1246           3 :         io.generic.level = RAW_OPEN_SMB2;
    1247           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1248           3 :         io.smb2.in.alloc_size = 0;
    1249           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1250           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1251           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1252           3 :         io.smb2.in.create_options = 0;
    1253           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1254           3 :         io.smb2.in.security_flags = 0;
    1255           3 :         io.smb2.in.fname = fname;
    1256             : 
    1257           3 :         torture_comment(tctx, "BATCH6: a 2nd open should give a break to "
    1258             :                         "level II if the first open allowed shared read\n");
    1259           3 :         ZERO_STRUCT(break_info);
    1260           3 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    1261           3 :         tree2->session->transport->oplock.private_data = tree2;
    1262             : 
    1263           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    1264             :                                 SEC_RIGHTS_FILE_WRITE;
    1265           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1266             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1267           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1268           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1269           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1270           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1271           3 :         h1 = io.smb2.out.file.handle;
    1272           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1273             : 
    1274           3 :         ZERO_STRUCT(break_info);
    1275             : 
    1276           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1277           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1278           3 :         h2 = io.smb2.out.file.handle;
    1279           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    1280             : 
    1281           3 :         torture_wait_for_oplock_break(tctx);
    1282           3 :         CHECK_VAL(break_info.count, 1);
    1283           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    1284           3 :         CHECK_VAL(break_info.level, 1);
    1285           3 :         CHECK_VAL(break_info.failures, 0);
    1286           3 :         ZERO_STRUCT(break_info);
    1287             : 
    1288           3 :         torture_comment(tctx, "write should trigger a break to none on both\n");
    1289           3 :         tree1->session->transport->oplock.handler =
    1290             :             torture_oplock_handler_level2_to_none;
    1291           3 :         tree2->session->transport->oplock.handler =
    1292             :             torture_oplock_handler_level2_to_none;
    1293           3 :         smb2_util_write(tree1, h1, &c, 0, 1);
    1294             : 
    1295             :         /* We expect two breaks */
    1296           3 :         torture_wait_for_oplock_break(tctx);
    1297           3 :         torture_wait_for_oplock_break(tctx);
    1298             : 
    1299           3 :         CHECK_VAL(break_info.count, 2);
    1300           3 :         CHECK_VAL(break_info.level, 0);
    1301           3 :         CHECK_VAL(break_info.failures, 0);
    1302             : 
    1303           3 :         smb2_util_close(tree1, h1);
    1304           3 :         smb2_util_close(tree2, h2);
    1305           3 :         smb2_util_close(tree1, h);
    1306             : 
    1307           3 :         smb2_deltree(tree1, BASEDIR);
    1308           3 :         return ret;
    1309             : }
    1310             : 
    1311           3 : static bool test_smb2_oplock_batch7(struct torture_context *tctx,
    1312             :                                     struct smb2_tree *tree1,
    1313             :                                     struct smb2_tree *tree2)
    1314             : {
    1315           3 :         const char *fname = BASEDIR "\\test_batch7.dat";
    1316           0 :         NTSTATUS status;
    1317           3 :         bool ret = true;
    1318           0 :         union smb_open io;
    1319           0 :         struct smb2_handle h, h1, h2;
    1320             : 
    1321           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1322           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1323             : 
    1324             :         /* cleanup */
    1325           3 :         smb2_util_unlink(tree1, fname);
    1326             : 
    1327           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1328           3 :         tree1->session->transport->oplock.private_data = tree1;
    1329             : 
    1330             :         /*
    1331             :           base ntcreatex parms
    1332             :         */
    1333           3 :         ZERO_STRUCT(io.smb2);
    1334           3 :         io.generic.level = RAW_OPEN_SMB2;
    1335           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1336           3 :         io.smb2.in.alloc_size = 0;
    1337           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1338           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1339           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1340           3 :         io.smb2.in.create_options = 0;
    1341           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1342           3 :         io.smb2.in.security_flags = 0;
    1343           3 :         io.smb2.in.fname = fname;
    1344             : 
    1345           3 :         torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when "
    1346             :                         "we close instead of ack\n");
    1347           3 :         ZERO_STRUCT(break_info);
    1348           3 :         tree1->session->transport->oplock.handler =
    1349             :                         torture_oplock_handler_close;
    1350           3 :         tree1->session->transport->oplock.private_data = tree1;
    1351             : 
    1352           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1353           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1354           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1355           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1356           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1357           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1358           3 :         h2 = io.smb2.out.file.handle;
    1359           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1360             : 
    1361           3 :         ZERO_STRUCT(break_info);
    1362             : 
    1363           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1364           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1365           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1366           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1367           3 :         h1 = io.smb2.out.file.handle;
    1368           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1369             : 
    1370           3 :         torture_wait_for_oplock_break(tctx);
    1371           3 :         CHECK_VAL(break_info.count, 1);
    1372           3 :         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
    1373           3 :         CHECK_VAL(break_info.level, 1);
    1374           3 :         CHECK_VAL(break_info.failures, 0);
    1375             : 
    1376           3 :         smb2_util_close(tree2, h1);
    1377           3 :         smb2_util_close(tree2, h);
    1378             : 
    1379           3 :         smb2_deltree(tree1, BASEDIR);
    1380           3 :         return ret;
    1381             : }
    1382             : 
    1383           3 : static bool test_smb2_oplock_batch8(struct torture_context *tctx,
    1384             :                                     struct smb2_tree *tree1,
    1385             :                                     struct smb2_tree *tree2)
    1386             : {
    1387           3 :         const char *fname = BASEDIR "\\test_batch8.dat";
    1388           0 :         NTSTATUS status;
    1389           3 :         bool ret = true;
    1390           0 :         union smb_open io;
    1391           0 :         struct smb2_handle h, h1, h2;
    1392             : 
    1393           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1394           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1395             : 
    1396             :         /* cleanup */
    1397           3 :         smb2_util_unlink(tree1, fname);
    1398             : 
    1399           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1400           3 :         tree1->session->transport->oplock.private_data = tree1;
    1401             : 
    1402             :         /*
    1403             :           base ntcreatex parms
    1404             :         */
    1405           3 :         ZERO_STRUCT(io.smb2);
    1406           3 :         io.generic.level = RAW_OPEN_SMB2;
    1407           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1408           3 :         io.smb2.in.alloc_size = 0;
    1409           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1410           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1411           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1412           3 :         io.smb2.in.create_options = 0;
    1413           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1414           3 :         io.smb2.in.security_flags = 0;
    1415           3 :         io.smb2.in.fname = fname;
    1416             : 
    1417           3 :         torture_comment(tctx, "BATCH8: open with batch oplock\n");
    1418           3 :         ZERO_STRUCT(break_info);
    1419             : 
    1420           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1421           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1422           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1423           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1424           3 :         h1 = io.smb2.out.file.handle;
    1425           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1426             : 
    1427           3 :         ZERO_STRUCT(break_info);
    1428           3 :         torture_comment(tctx, "second open with attributes only shouldn't "
    1429             :                         "cause oplock break\n");
    1430             : 
    1431           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1432           3 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    1433             :                                 SEC_FILE_WRITE_ATTRIBUTE |
    1434             :                                 SEC_STD_SYNCHRONIZE;
    1435           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1436           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1437           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1438           3 :         h2 = io.smb2.out.file.handle;
    1439           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
    1440           3 :         torture_wait_for_oplock_break(tctx);
    1441           3 :         CHECK_VAL(break_info.count, 0);
    1442           3 :         CHECK_VAL(break_info.failures, 0);
    1443             : 
    1444           3 :         smb2_util_close(tree1, h1);
    1445           3 :         smb2_util_close(tree2, h2);
    1446           3 :         smb2_util_close(tree1, h);
    1447             : 
    1448           3 :         smb2_deltree(tree1, BASEDIR);
    1449           3 :         return ret;
    1450             : }
    1451             : 
    1452           3 : static bool test_smb2_oplock_batch9(struct torture_context *tctx,
    1453             :                                      struct smb2_tree *tree1,
    1454             :                                      struct smb2_tree *tree2)
    1455             : {
    1456           3 :         const char *fname = BASEDIR "\\test_batch9.dat";
    1457           0 :         NTSTATUS status;
    1458           3 :         bool ret = true;
    1459           0 :         union smb_open io;
    1460           0 :         struct smb2_handle h, h1, h2;
    1461           3 :         char c = 0;
    1462             : 
    1463           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1464           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1465             : 
    1466             :         /* cleanup */
    1467           3 :         smb2_util_unlink(tree1, fname);
    1468             : 
    1469           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1470           3 :         tree1->session->transport->oplock.private_data = tree1;
    1471             : 
    1472             :         /*
    1473             :           base ntcreatex parms
    1474             :         */
    1475           3 :         ZERO_STRUCT(io.smb2);
    1476           3 :         io.generic.level = RAW_OPEN_SMB2;
    1477           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1478           3 :         io.smb2.in.alloc_size = 0;
    1479           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1480           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1481           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1482           3 :         io.smb2.in.create_options = 0;
    1483           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1484           3 :         io.smb2.in.security_flags = 0;
    1485           3 :         io.smb2.in.fname = fname;
    1486             : 
    1487           3 :         torture_comment(tctx, "BATCH9: open with attributes only can create "
    1488             :                         "file\n");
    1489             : 
    1490           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1491           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1492           3 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    1493             :                                 SEC_FILE_WRITE_ATTRIBUTE |
    1494             :                                 SEC_STD_SYNCHRONIZE;
    1495           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1496           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1497           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1498           3 :         h1 = io.smb2.out.file.handle;
    1499           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1500             : 
    1501           3 :         torture_comment(tctx, "Subsequent normal open should break oplock on "
    1502             :                         "attribute only open to level II\n");
    1503             : 
    1504           3 :         ZERO_STRUCT(break_info);
    1505             : 
    1506           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1507           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1508           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1509           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1510           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1511           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1512           3 :         h2 = io.smb2.out.file.handle;
    1513           3 :         torture_wait_for_oplock_break(tctx);
    1514           3 :         CHECK_VAL(break_info.count, 1);
    1515           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    1516           3 :         CHECK_VAL(break_info.failures, 0);
    1517           3 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    1518           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    1519           3 :         smb2_util_close(tree2, h2);
    1520             : 
    1521           3 :         torture_comment(tctx, "third oplocked open should grant level2 without "
    1522             :                         "break\n");
    1523           3 :         ZERO_STRUCT(break_info);
    1524             : 
    1525           3 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    1526           3 :         tree2->session->transport->oplock.private_data = tree2;
    1527             : 
    1528           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1529           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1530           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1531           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1532           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1533           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1534           3 :         h2 = io.smb2.out.file.handle;
    1535           3 :         torture_wait_for_oplock_break(tctx);
    1536           3 :         CHECK_VAL(break_info.count, 0);
    1537           3 :         CHECK_VAL(break_info.failures, 0);
    1538           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    1539             : 
    1540           3 :         ZERO_STRUCT(break_info);
    1541             : 
    1542           3 :         torture_comment(tctx, "write should trigger a break to none on both\n");
    1543           3 :         tree1->session->transport->oplock.handler =
    1544             :             torture_oplock_handler_level2_to_none;
    1545           3 :         tree2->session->transport->oplock.handler =
    1546             :             torture_oplock_handler_level2_to_none;
    1547           3 :         smb2_util_write(tree2, h2, &c, 0, 1);
    1548             : 
    1549             :         /* We expect two breaks */
    1550           3 :         torture_wait_for_oplock_break(tctx);
    1551           3 :         torture_wait_for_oplock_break(tctx);
    1552             : 
    1553           3 :         CHECK_VAL(break_info.count, 2);
    1554           3 :         CHECK_VAL(break_info.level, 0);
    1555           3 :         CHECK_VAL(break_info.failures, 0);
    1556             : 
    1557           3 :         smb2_util_close(tree1, h1);
    1558           3 :         smb2_util_close(tree2, h2);
    1559           3 :         smb2_util_close(tree1, h);
    1560             : 
    1561           3 :         smb2_deltree(tree1, BASEDIR);
    1562           3 :         return ret;
    1563             : }
    1564             : 
    1565           3 : static bool test_smb2_oplock_batch9a(struct torture_context *tctx,
    1566             :                                      struct smb2_tree *tree1,
    1567             :                                      struct smb2_tree *tree2)
    1568             : {
    1569           3 :         const char *fname = BASEDIR "\\test_batch9a.dat";
    1570           0 :         NTSTATUS status;
    1571           3 :         bool ret = true;
    1572           0 :         union smb_open io;
    1573           0 :         struct smb2_handle h, h1, h2, h3;
    1574           3 :         char c = 0;
    1575             : 
    1576           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1577           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1578             : 
    1579             :         /* cleanup */
    1580           3 :         smb2_util_unlink(tree1, fname);
    1581             : 
    1582           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1583           3 :         tree1->session->transport->oplock.private_data = tree1;
    1584             : 
    1585             :         /*
    1586             :           base ntcreatex parms
    1587             :         */
    1588           3 :         ZERO_STRUCT(io.smb2);
    1589           3 :         io.generic.level = RAW_OPEN_SMB2;
    1590           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1591           3 :         io.smb2.in.alloc_size = 0;
    1592           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1593           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1594           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1595           3 :         io.smb2.in.create_options = 0;
    1596           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1597           3 :         io.smb2.in.security_flags = 0;
    1598           3 :         io.smb2.in.fname = fname;
    1599             : 
    1600           3 :         torture_comment(tctx, "BATCH9: open with attributes only can create "
    1601             :                         "file\n");
    1602             : 
    1603           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1604           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1605           3 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    1606             :                                 SEC_FILE_WRITE_ATTRIBUTE |
    1607             :                                 SEC_STD_SYNCHRONIZE;
    1608           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1609           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating the file");
    1610           3 :         h1 = io.smb2.out.file.handle;
    1611           3 :         CHECK_VAL(io.smb2.out.create_action, FILE_WAS_CREATED);
    1612           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1613             : 
    1614           3 :         torture_comment(tctx, "Subsequent attributes open should not break\n");
    1615             : 
    1616           3 :         ZERO_STRUCT(break_info);
    1617             : 
    1618           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1619           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1620           3 :         h3 = io.smb2.out.file.handle;
    1621           3 :         torture_wait_for_oplock_break(tctx);
    1622           3 :         CHECK_VAL(break_info.count, 0);
    1623           3 :         CHECK_VAL(io.smb2.out.create_action, FILE_WAS_OPENED);
    1624           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
    1625           3 :         smb2_util_close(tree2, h3);
    1626             : 
    1627           3 :         torture_comment(tctx, "Subsequent normal open should break oplock on "
    1628             :                         "attribute only open to level II\n");
    1629             : 
    1630           3 :         ZERO_STRUCT(break_info);
    1631             : 
    1632           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1633           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1634           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1635           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1636           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1637           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1638           3 :         h2 = io.smb2.out.file.handle;
    1639           3 :         torture_wait_for_oplock_break(tctx);
    1640           3 :         CHECK_VAL(break_info.count, 1);
    1641           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    1642           3 :         CHECK_VAL(break_info.failures, 0);
    1643           3 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    1644           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    1645           3 :         smb2_util_close(tree2, h2);
    1646             : 
    1647           3 :         torture_comment(tctx, "third oplocked open should grant level2 without "
    1648             :                         "break\n");
    1649           3 :         ZERO_STRUCT(break_info);
    1650             : 
    1651           3 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    1652           3 :         tree2->session->transport->oplock.private_data = tree2;
    1653             : 
    1654           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1655           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1656           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1657           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1658           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1659           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1660           3 :         h2 = io.smb2.out.file.handle;
    1661           3 :         torture_wait_for_oplock_break(tctx);
    1662           3 :         CHECK_VAL(break_info.count, 0);
    1663           3 :         CHECK_VAL(break_info.failures, 0);
    1664           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    1665             : 
    1666           3 :         ZERO_STRUCT(break_info);
    1667             : 
    1668           3 :         torture_comment(tctx, "write should trigger a break to none on both\n");
    1669           3 :         tree1->session->transport->oplock.handler =
    1670             :             torture_oplock_handler_level2_to_none;
    1671           3 :         tree2->session->transport->oplock.handler =
    1672             :             torture_oplock_handler_level2_to_none;
    1673           3 :         smb2_util_write(tree2, h2, &c, 0, 1);
    1674             : 
    1675             :         /* We expect two breaks */
    1676           3 :         torture_wait_for_oplock_break(tctx);
    1677           3 :         torture_wait_for_oplock_break(tctx);
    1678             : 
    1679           3 :         CHECK_VAL(break_info.count, 2);
    1680           3 :         CHECK_VAL(break_info.level, 0);
    1681           3 :         CHECK_VAL(break_info.failures, 0);
    1682             : 
    1683           3 :         smb2_util_close(tree1, h1);
    1684           3 :         smb2_util_close(tree2, h2);
    1685           3 :         smb2_util_close(tree1, h);
    1686             : 
    1687           3 :         smb2_deltree(tree1, BASEDIR);
    1688           3 :         return ret;
    1689             : }
    1690             : 
    1691             : 
    1692           3 : static bool test_smb2_oplock_batch10(struct torture_context *tctx,
    1693             :                                      struct smb2_tree *tree1,
    1694             :                                      struct smb2_tree *tree2)
    1695             : {
    1696           3 :         const char *fname = BASEDIR "\\test_batch10.dat";
    1697           0 :         NTSTATUS status;
    1698           3 :         bool ret = true;
    1699           0 :         union smb_open io;
    1700           0 :         struct smb2_handle h, h1, h2;
    1701             : 
    1702           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1703           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1704             : 
    1705             :         /* cleanup */
    1706           3 :         smb2_util_unlink(tree1, fname);
    1707             : 
    1708           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1709           3 :         tree1->session->transport->oplock.private_data = tree1;
    1710             : 
    1711             :         /*
    1712             :           base ntcreatex parms
    1713             :         */
    1714           3 :         ZERO_STRUCT(io.smb2);
    1715           3 :         io.generic.level = RAW_OPEN_SMB2;
    1716           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1717           3 :         io.smb2.in.alloc_size = 0;
    1718           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1719           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1720           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1721           3 :         io.smb2.in.create_options = 0;
    1722           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1723           3 :         io.smb2.in.security_flags = 0;
    1724           3 :         io.smb2.in.fname = fname;
    1725             : 
    1726           3 :         torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock "
    1727             :                         "open should grant level2\n");
    1728           3 :         ZERO_STRUCT(break_info);
    1729           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1730           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1731           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1732             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1733             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1734           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1735           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1736           3 :         h1 = io.smb2.out.file.handle;
    1737           3 :         torture_wait_for_oplock_break(tctx);
    1738           3 :         CHECK_VAL(break_info.count, 0);
    1739           3 :         CHECK_VAL(break_info.failures, 0);
    1740           3 :         CHECK_VAL(io.smb2.out.oplock_level, 0);
    1741             : 
    1742           3 :         tree2->session->transport->oplock.handler =
    1743             :             torture_oplock_handler_level2_to_none;
    1744           3 :         tree2->session->transport->oplock.private_data = tree2;
    1745             : 
    1746           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1747           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1748           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1749           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1750             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1751             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1752           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1753           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1754           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1755           3 :         h2 = io.smb2.out.file.handle;
    1756           3 :         torture_wait_for_oplock_break(tctx);
    1757           3 :         CHECK_VAL(break_info.count, 0);
    1758           3 :         CHECK_VAL(break_info.failures, 0);
    1759           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    1760             : 
    1761           3 :         torture_comment(tctx, "write should trigger a break to none\n");
    1762             :         {
    1763           0 :                 struct smb2_write wr;
    1764           0 :                 DATA_BLOB data;
    1765           3 :                 data = data_blob_talloc_zero(tree1, UINT16_MAX);
    1766           3 :                 data.data[0] = (const uint8_t)'x';
    1767           3 :                 ZERO_STRUCT(wr);
    1768           3 :                 wr.in.file.handle = h1;
    1769           3 :                 wr.in.offset      = 0;
    1770           3 :                 wr.in.data        = data;
    1771           3 :                 status = smb2_write(tree1, &wr);
    1772           3 :                 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1773             :         }
    1774             : 
    1775           3 :         torture_wait_for_oplock_break(tctx);
    1776             : 
    1777           3 :         CHECK_VAL(break_info.count, 1);
    1778           3 :         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
    1779           3 :         CHECK_VAL(break_info.level, 0);
    1780           3 :         CHECK_VAL(break_info.failures, 0);
    1781             : 
    1782           3 :         smb2_util_close(tree1, h1);
    1783           3 :         smb2_util_close(tree2, h2);
    1784           3 :         smb2_util_close(tree1, h);
    1785             : 
    1786           3 :         smb2_deltree(tree1, BASEDIR);
    1787           3 :         return ret;
    1788             : }
    1789             : 
    1790           3 : static bool test_smb2_oplock_batch11(struct torture_context *tctx,
    1791             :                                      struct smb2_tree *tree1,
    1792             :                                      struct smb2_tree *tree2)
    1793             : {
    1794           3 :         const char *fname = BASEDIR "\\test_batch11.dat";
    1795           0 :         NTSTATUS status;
    1796           3 :         bool ret = true;
    1797           0 :         union smb_open io;
    1798           0 :         union smb_setfileinfo sfi;
    1799           0 :         struct smb2_handle h, h1;
    1800             : 
    1801           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1802           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1803             : 
    1804             :         /* cleanup */
    1805           3 :         smb2_util_unlink(tree1, fname);
    1806             : 
    1807           3 :         tree1->session->transport->oplock.handler =
    1808             :             torture_oplock_handler_two_notifications;
    1809           3 :         tree1->session->transport->oplock.private_data = tree1;
    1810             : 
    1811             :         /*
    1812             :           base ntcreatex parms
    1813             :         */
    1814           3 :         ZERO_STRUCT(io.smb2);
    1815           3 :         io.generic.level = RAW_OPEN_SMB2;
    1816           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1817           3 :         io.smb2.in.alloc_size = 0;
    1818           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1819           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1820           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1821           3 :         io.smb2.in.create_options = 0;
    1822           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1823           3 :         io.smb2.in.security_flags = 0;
    1824           3 :         io.smb2.in.fname = fname;
    1825             : 
    1826             :         /* Test if a set-eof on pathname breaks an exclusive oplock. */
    1827           3 :         torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks "
    1828             :                         "oplocks.\n");
    1829             : 
    1830           3 :         ZERO_STRUCT(break_info);
    1831             : 
    1832           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1833           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1834           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1835           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1836             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    1837             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1838           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1839           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1840           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1841           3 :         h1 = io.smb2.out.file.handle;
    1842           3 :         torture_wait_for_oplock_break(tctx);
    1843           3 :         CHECK_VAL(break_info.count, 0);
    1844           3 :         CHECK_VAL(break_info.failures, 0);
    1845           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1846             : 
    1847           3 :         ZERO_STRUCT(sfi);
    1848           3 :         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
    1849           3 :         sfi.generic.in.file.path = fname;
    1850           3 :         sfi.end_of_file_info.in.size = 100;
    1851             : 
    1852           3 :         status = smb2_composite_setpathinfo(tree2, &sfi);
    1853           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1854             : 
    1855             :         /* We expect two breaks */
    1856           3 :         torture_wait_for_oplock_break(tctx);
    1857           3 :         torture_wait_for_oplock_break(tctx);
    1858             : 
    1859           3 :         CHECK_VAL(break_info.count, 2);
    1860           3 :         CHECK_VAL(break_info.failures, 0);
    1861           3 :         CHECK_VAL(break_info.level, 0);
    1862             : 
    1863           3 :         smb2_util_close(tree1, h1);
    1864           3 :         smb2_util_close(tree1, h);
    1865             : 
    1866           3 :         smb2_deltree(tree1, BASEDIR);
    1867           3 :         return ret;
    1868             : }
    1869             : 
    1870           3 : static bool test_smb2_oplock_batch12(struct torture_context *tctx,
    1871             :                                      struct smb2_tree *tree1,
    1872             :                                      struct smb2_tree *tree2)
    1873             : {
    1874           3 :         const char *fname = BASEDIR "\\test_batch12.dat";
    1875           0 :         NTSTATUS status;
    1876           3 :         bool ret = true;
    1877           0 :         union smb_open io;
    1878           0 :         union smb_setfileinfo sfi;
    1879           0 :         struct smb2_handle h, h1;
    1880             : 
    1881           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1882           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1883             : 
    1884             :         /* cleanup */
    1885           3 :         smb2_util_unlink(tree1, fname);
    1886             : 
    1887           3 :         tree1->session->transport->oplock.handler =
    1888             :             torture_oplock_handler_two_notifications;
    1889           3 :         tree1->session->transport->oplock.private_data = tree1;
    1890             : 
    1891             :         /*
    1892             :           base ntcreatex parms
    1893             :         */
    1894           3 :         ZERO_STRUCT(io.smb2);
    1895           3 :         io.generic.level = RAW_OPEN_SMB2;
    1896           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1897           3 :         io.smb2.in.alloc_size = 0;
    1898           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1899           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1900           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1901           3 :         io.smb2.in.create_options = 0;
    1902           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1903           3 :         io.smb2.in.security_flags = 0;
    1904           3 :         io.smb2.in.fname = fname;
    1905             : 
    1906             :         /* Test if a set-allocation size on pathname breaks an exclusive
    1907             :          * oplock. */
    1908           3 :         torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size "
    1909             :                         "breaks oplocks.\n");
    1910             : 
    1911           3 :         ZERO_STRUCT(break_info);
    1912             : 
    1913           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1914           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1915           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1916           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1917             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    1918             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1919           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1920           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1921           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1922           3 :         h1 = io.smb2.out.file.handle;
    1923           3 :         torture_wait_for_oplock_break(tctx);
    1924           3 :         CHECK_VAL(break_info.count, 0);
    1925           3 :         CHECK_VAL(break_info.failures, 0);
    1926           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1927             : 
    1928           3 :         ZERO_STRUCT(sfi);
    1929           3 :         sfi.generic.level = RAW_SFILEINFO_ALLOCATION_INFORMATION;
    1930           3 :         sfi.generic.in.file.path = fname;
    1931           3 :         sfi.allocation_info.in.alloc_size = 65536 * 8;
    1932             : 
    1933           3 :         status = smb2_composite_setpathinfo(tree2, &sfi);
    1934           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1935             : 
    1936             :         /* We expect two breaks */
    1937           3 :         torture_wait_for_oplock_break(tctx);
    1938           3 :         torture_wait_for_oplock_break(tctx);
    1939             : 
    1940           3 :         CHECK_VAL(break_info.count, 2);
    1941           3 :         CHECK_VAL(break_info.failures, 0);
    1942           3 :         CHECK_VAL(break_info.level, 0);
    1943             : 
    1944           3 :         smb2_util_close(tree1, h1);
    1945           3 :         smb2_util_close(tree1, h);
    1946             : 
    1947           3 :         smb2_deltree(tree1, BASEDIR);
    1948           3 :         return ret;
    1949             : }
    1950             : 
    1951           3 : static bool test_smb2_oplock_batch13(struct torture_context *tctx,
    1952             :                                      struct smb2_tree *tree1,
    1953             :                                      struct smb2_tree *tree2)
    1954             : {
    1955           3 :         const char *fname = BASEDIR "\\test_batch13.dat";
    1956           0 :         NTSTATUS status;
    1957           3 :         bool ret = true;
    1958           0 :         union smb_open io;
    1959           0 :         struct smb2_handle h, h1, h2;
    1960             : 
    1961           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1962           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1963             : 
    1964             :         /* cleanup */
    1965           3 :         smb2_util_unlink(tree1, fname);
    1966             : 
    1967           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1968           3 :         tree1->session->transport->oplock.private_data = tree1;
    1969             : 
    1970           3 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    1971           3 :         tree2->session->transport->oplock.private_data = tree2;
    1972             : 
    1973             :         /*
    1974             :           base ntcreatex parms
    1975             :         */
    1976           3 :         ZERO_STRUCT(io.smb2);
    1977           3 :         io.generic.level = RAW_OPEN_SMB2;
    1978           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1979           3 :         io.smb2.in.alloc_size = 0;
    1980           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1981           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1982           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1983           3 :         io.smb2.in.create_options = 0;
    1984           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1985           3 :         io.smb2.in.security_flags = 0;
    1986           3 :         io.smb2.in.fname = fname;
    1987             : 
    1988           3 :         torture_comment(tctx, "BATCH13: open with batch oplock\n");
    1989           3 :         ZERO_STRUCT(break_info);
    1990             : 
    1991           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1992           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1993           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1994             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1995             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1996           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1997           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1998           3 :         h1 = io.smb2.out.file.handle;
    1999           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2000             : 
    2001           3 :         ZERO_STRUCT(break_info);
    2002             : 
    2003           3 :         torture_comment(tctx, "second open with attributes only and "
    2004             :                         "NTCREATEX_DISP_OVERWRITE disposition causes "
    2005             :                         "oplock break\n");
    2006             : 
    2007           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2008           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2009           3 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    2010             :                                 SEC_FILE_WRITE_ATTRIBUTE |
    2011             :                                 SEC_STD_SYNCHRONIZE;
    2012           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2013             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    2014             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    2015           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
    2016           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2017           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2018           3 :         h2 = io.smb2.out.file.handle;
    2019           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2020           3 :         torture_wait_for_oplock_break(tctx);
    2021           3 :         CHECK_VAL(break_info.count, 1);
    2022           3 :         CHECK_VAL(break_info.failures, 0);
    2023             : 
    2024           3 :         smb2_util_close(tree1, h1);
    2025           3 :         smb2_util_close(tree2, h2);
    2026           3 :         smb2_util_close(tree1, h);
    2027             : 
    2028           3 :         smb2_deltree(tree1, BASEDIR);
    2029             : 
    2030           3 :         return ret;
    2031             : }
    2032             : 
    2033           3 : static bool test_smb2_oplock_batch14(struct torture_context *tctx,
    2034             :                                      struct smb2_tree *tree1,
    2035             :                                      struct smb2_tree *tree2)
    2036             : {
    2037           3 :         const char *fname = BASEDIR "\\test_batch14.dat";
    2038           0 :         NTSTATUS status;
    2039           3 :         bool ret = true;
    2040           0 :         union smb_open io;
    2041           0 :         struct smb2_handle h, h1, h2;
    2042             : 
    2043           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2044           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2045             : 
    2046             :         /* cleanup */
    2047           3 :         smb2_util_unlink(tree1, fname);
    2048             : 
    2049           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2050           3 :         tree1->session->transport->oplock.private_data = tree1;
    2051             : 
    2052             :         /*
    2053             :           base ntcreatex parms
    2054             :         */
    2055           3 :         ZERO_STRUCT(io.smb2);
    2056           3 :         io.generic.level = RAW_OPEN_SMB2;
    2057           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2058           3 :         io.smb2.in.alloc_size = 0;
    2059           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2060           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2061           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2062           3 :         io.smb2.in.create_options = 0;
    2063           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2064           3 :         io.smb2.in.security_flags = 0;
    2065           3 :         io.smb2.in.fname = fname;
    2066             : 
    2067           3 :         torture_comment(tctx, "BATCH14: open with batch oplock\n");
    2068           3 :         ZERO_STRUCT(break_info);
    2069             : 
    2070           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2071           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2072           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2073             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    2074             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    2075           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2076           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2077           3 :         h1 = io.smb2.out.file.handle;
    2078           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2079             : 
    2080           3 :         ZERO_STRUCT(break_info);
    2081             : 
    2082           3 :         torture_comment(tctx, "second open with attributes only and "
    2083             :                         "NTCREATEX_DISP_SUPERSEDE disposition causes "
    2084             :                         "oplock break\n");
    2085             : 
    2086           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2087           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2088           3 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    2089             :                                 SEC_FILE_WRITE_ATTRIBUTE |
    2090             :                                 SEC_STD_SYNCHRONIZE;
    2091           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2092             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    2093             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    2094           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
    2095           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2096           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2097           3 :         h2 = io.smb2.out.file.handle;
    2098           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2099             : 
    2100           3 :         torture_wait_for_oplock_break(tctx);
    2101           3 :         CHECK_VAL(break_info.count, 1);
    2102           3 :         CHECK_VAL(break_info.failures, 0);
    2103             : 
    2104           3 :         smb2_util_close(tree1, h1);
    2105           3 :         smb2_util_close(tree2, h2);
    2106           3 :         smb2_util_close(tree1, h);
    2107             : 
    2108           3 :         smb2_deltree(tree1, BASEDIR);
    2109           3 :         return ret;
    2110             : }
    2111             : 
    2112           3 : static bool test_smb2_oplock_batch15(struct torture_context *tctx,
    2113             :                                      struct smb2_tree *tree1,
    2114             :                                      struct smb2_tree *tree2)
    2115             : {
    2116           3 :         const char *fname = BASEDIR "\\test_batch15.dat";
    2117           0 :         NTSTATUS status;
    2118           3 :         bool ret = true;
    2119           0 :         union smb_open io;
    2120           0 :         union smb_fileinfo qfi;
    2121           0 :         struct smb2_handle h, h1;
    2122             : 
    2123           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2124           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2125             : 
    2126             :         /* cleanup */
    2127           3 :         smb2_util_unlink(tree1, fname);
    2128             : 
    2129           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2130           3 :         tree1->session->transport->oplock.private_data = tree1;
    2131             : 
    2132             :         /*
    2133             :           base ntcreatex parms
    2134             :         */
    2135           3 :         ZERO_STRUCT(io.smb2);
    2136           3 :         io.generic.level = RAW_OPEN_SMB2;
    2137           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2138           3 :         io.smb2.in.alloc_size = 0;
    2139           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2140           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2141           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2142           3 :         io.smb2.in.create_options = 0;
    2143           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2144           3 :         io.smb2.in.security_flags = 0;
    2145           3 :         io.smb2.in.fname = fname;
    2146             : 
    2147             :         /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
    2148           3 :         torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks "
    2149             :                         "a batch oplock (should not).\n");
    2150             : 
    2151           3 :         ZERO_STRUCT(break_info);
    2152             : 
    2153           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2154           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2155           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2156           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2157             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    2158             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    2159           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    2160           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2161           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2162           3 :         h1 = io.smb2.out.file.handle;
    2163             : 
    2164           3 :         torture_wait_for_oplock_break(tctx);
    2165           3 :         CHECK_VAL(break_info.count, 0);
    2166           3 :         CHECK_VAL(break_info.failures, 0);
    2167           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2168             : 
    2169           3 :         ZERO_STRUCT(qfi);
    2170           3 :         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
    2171           3 :         qfi.generic.in.file.handle = h1;
    2172           3 :         status = smb2_getinfo_file(tree2, tctx, &qfi);
    2173             : 
    2174           3 :         torture_wait_for_oplock_break(tctx);
    2175           3 :         CHECK_VAL(break_info.count, 0);
    2176             : 
    2177           3 :         smb2_util_close(tree1, h1);
    2178           3 :         smb2_util_close(tree1, h);
    2179             : 
    2180           3 :         smb2_deltree(tree1, BASEDIR);
    2181           3 :         return ret;
    2182             : }
    2183             : 
    2184           3 : static bool test_smb2_oplock_batch16(struct torture_context *tctx,
    2185             :                                      struct smb2_tree *tree1,
    2186             :                                      struct smb2_tree *tree2)
    2187             : {
    2188           3 :         const char *fname = BASEDIR "\\test_batch16.dat";
    2189           0 :         NTSTATUS status;
    2190           3 :         bool ret = true;
    2191           0 :         union smb_open io;
    2192           0 :         struct smb2_handle h, h1, h2;
    2193             : 
    2194           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2195           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2196             : 
    2197             :         /* cleanup */
    2198           3 :         smb2_util_unlink(tree1, fname);
    2199             : 
    2200           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2201           3 :         tree1->session->transport->oplock.private_data = tree1;
    2202             : 
    2203           3 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    2204           3 :         tree2->session->transport->oplock.private_data = tree2;
    2205             : 
    2206             :         /*
    2207             :           base ntcreatex parms
    2208             :         */
    2209           3 :         ZERO_STRUCT(io.smb2);
    2210           3 :         io.generic.level = RAW_OPEN_SMB2;
    2211           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2212           3 :         io.smb2.in.alloc_size = 0;
    2213           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2214           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2215           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2216           3 :         io.smb2.in.create_options = 0;
    2217           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2218           3 :         io.smb2.in.security_flags = 0;
    2219           3 :         io.smb2.in.fname = fname;
    2220             : 
    2221           3 :         torture_comment(tctx, "BATCH16: open with batch oplock\n");
    2222           3 :         ZERO_STRUCT(break_info);
    2223             : 
    2224           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2225           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2226           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2227             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    2228             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    2229           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2230           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2231           3 :         h1 = io.smb2.out.file.handle;
    2232           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2233             : 
    2234           3 :         ZERO_STRUCT(break_info);
    2235             : 
    2236           3 :         torture_comment(tctx, "second open with attributes only and "
    2237             :                         "NTCREATEX_DISP_OVERWRITE_IF disposition causes "
    2238             :                         "oplock break\n");
    2239             : 
    2240           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2241           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2242           3 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    2243             :                                 SEC_FILE_WRITE_ATTRIBUTE |
    2244             :                                 SEC_STD_SYNCHRONIZE;
    2245           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2246             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    2247             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    2248           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
    2249           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2250           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2251           3 :         h2 = io.smb2.out.file.handle;
    2252           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2253             : 
    2254           3 :         torture_wait_for_oplock_break(tctx);
    2255           3 :         CHECK_VAL(break_info.count, 1);
    2256           3 :         CHECK_VAL(break_info.failures, 0);
    2257             : 
    2258           3 :         smb2_util_close(tree1, h1);
    2259           3 :         smb2_util_close(tree2, h2);
    2260           3 :         smb2_util_close(tree1, h);
    2261             : 
    2262           3 :         smb2_deltree(tree1, BASEDIR);
    2263           3 :         return ret;
    2264             : }
    2265             : 
    2266             : /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH17 test.  Since
    2267             :  * SMB2 doesn't have a RENAME command this test isn't applicable.  However,
    2268             :  * it's much less confusing, when comparing test, to keep the SMB1 and SMB2
    2269             :  * test numbers in sync. */
    2270             : #if 0
    2271             : static bool test_raw_oplock_batch17(struct torture_context *tctx,
    2272             :                                     struct smb2_tree *tree1,
    2273             :                                     struct smb2_tree *tree2)
    2274             : {
    2275             :         return true;
    2276             : }
    2277             : #endif
    2278             : 
    2279             : /* This function is a placeholder for the SMB1 RAW-OPLOCK-BATCH18 test.  Since
    2280             :  * SMB2 doesn't have an NTRENAME command this test isn't applicable.  However,
    2281             :  * it's much less confusing, when comparing tests, to keep the SMB1 and SMB2
    2282             :  * test numbers in sync. */
    2283             : #if 0
    2284             : static bool test_raw_oplock_batch18(struct torture_context *tctx,
    2285             :                                     struct smb2_tree *tree1,
    2286             :                                     struct smb2_tree *tree2)
    2287             : {
    2288             :         return true;
    2289             : }
    2290             : #endif
    2291             : 
    2292           3 : static bool test_smb2_oplock_batch19(struct torture_context *tctx,
    2293             :                                      struct smb2_tree *tree1)
    2294             : {
    2295           3 :         const char *fname1 = BASEDIR "\\test_batch19_1.dat";
    2296           3 :         const char *fname2 = BASEDIR "\\test_batch19_2.dat";
    2297           0 :         NTSTATUS status;
    2298           3 :         bool ret = true;
    2299           0 :         union smb_open io;
    2300           0 :         union smb_fileinfo qfi;
    2301           0 :         union smb_setfileinfo sfi;
    2302           0 :         struct smb2_handle h, h1;
    2303             : 
    2304           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2305           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2306             : 
    2307             :         /* cleanup */
    2308           3 :         smb2_util_unlink(tree1, fname1);
    2309           3 :         smb2_util_unlink(tree1, fname2);
    2310             : 
    2311           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2312           3 :         tree1->session->transport->oplock.private_data = tree1;
    2313             : 
    2314             :         /*
    2315             :           base ntcreatex parms
    2316             :         */
    2317           3 :         ZERO_STRUCT(io.smb2);
    2318           3 :         io.generic.level = RAW_OPEN_SMB2;
    2319           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2320           3 :         io.smb2.in.alloc_size = 0;
    2321           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2322           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2323           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2324           3 :         io.smb2.in.create_options = 0;
    2325           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2326           3 :         io.smb2.in.security_flags = 0;
    2327           3 :         io.smb2.in.fname = fname1;
    2328             : 
    2329           3 :         torture_comment(tctx, "BATCH19: open a file with an batch oplock "
    2330             :                         "(share mode: none)\n");
    2331           3 :         ZERO_STRUCT(break_info);
    2332           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2333           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2334           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2335           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2336           3 :         h1 = io.smb2.out.file.handle;
    2337           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2338             : 
    2339           3 :         torture_comment(tctx, "setfileinfo rename info should not trigger "
    2340             :                         "a break but should cause a sharing violation\n");
    2341           3 :         ZERO_STRUCT(sfi);
    2342           3 :         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
    2343           3 :         sfi.generic.in.file.path = fname1;
    2344           3 :         sfi.rename_information.in.file.handle   = h1;
    2345           3 :         sfi.rename_information.in.overwrite     = 0;
    2346           3 :         sfi.rename_information.in.root_fid      = 0;
    2347           3 :         sfi.rename_information.in.new_name      = fname2;
    2348             : 
    2349           3 :         status = smb2_setinfo_file(tree1, &sfi);
    2350             : 
    2351           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
    2352             :                                       "Incorrect status");
    2353             : 
    2354           2 :         torture_wait_for_oplock_break(tctx);
    2355           2 :         CHECK_VAL(break_info.count, 0);
    2356             : 
    2357           2 :         ZERO_STRUCT(qfi);
    2358           2 :         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
    2359           2 :         qfi.generic.in.file.handle = h1;
    2360             : 
    2361           2 :         status = smb2_getinfo_file(tree1, tctx, &qfi);
    2362           2 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2363           2 :         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
    2364             : 
    2365           2 :         smb2_util_close(tree1, h1);
    2366           2 :         smb2_util_close(tree1, h);
    2367             : 
    2368           2 :         smb2_deltree(tree1, fname1);
    2369           2 :         smb2_deltree(tree1, fname2);
    2370           2 :         return ret;
    2371             : }
    2372             : 
    2373           3 : static bool test_smb2_oplock_batch20(struct torture_context *tctx,
    2374             :                                      struct smb2_tree *tree1,
    2375             :                                      struct smb2_tree *tree2)
    2376             : {
    2377           3 :         const char *fname1 = BASEDIR "\\test_batch20_1.dat";
    2378           3 :         const char *fname2 = BASEDIR "\\test_batch20_2.dat";
    2379           0 :         NTSTATUS status;
    2380           3 :         bool ret = true;
    2381           0 :         union smb_open io;
    2382           0 :         union smb_fileinfo qfi;
    2383           0 :         union smb_setfileinfo sfi;
    2384           0 :         struct smb2_handle h, h1, h2;
    2385             : 
    2386           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2387           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2388             : 
    2389             :         /* cleanup */
    2390           3 :         smb2_util_unlink(tree1, fname1);
    2391           3 :         smb2_util_unlink(tree1, fname2);
    2392             : 
    2393           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2394           3 :         tree1->session->transport->oplock.private_data = tree1;
    2395             : 
    2396             :         /*
    2397             :           base ntcreatex parms
    2398             :         */
    2399           3 :         ZERO_STRUCT(io.smb2);
    2400           3 :         io.generic.level = RAW_OPEN_SMB2;
    2401           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2402           3 :         io.smb2.in.alloc_size = 0;
    2403           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2404           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2405           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2406           3 :         io.smb2.in.create_options = 0;
    2407           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2408           3 :         io.smb2.in.security_flags = 0;
    2409           3 :         io.smb2.in.fname = fname1;
    2410             : 
    2411           3 :         torture_comment(tctx, "BATCH20: open a file with an batch oplock "
    2412             :                         "(share mode: all)\n");
    2413           3 :         ZERO_STRUCT(break_info);
    2414           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2415           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2416           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2417             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    2418             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    2419           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2420           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2421           3 :         h1 = io.smb2.out.file.handle;
    2422           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2423             : 
    2424           3 :         torture_comment(tctx, "setfileinfo rename info should not trigger "
    2425             :                         "a break but should cause a sharing violation\n");
    2426           3 :         ZERO_STRUCT(sfi);
    2427           3 :         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
    2428           3 :         sfi.rename_information.in.file.handle   = h1;
    2429           3 :         sfi.rename_information.in.overwrite     = 0;
    2430           3 :         sfi.rename_information.in.new_name      = fname2;
    2431             : 
    2432           3 :         status = smb2_setinfo_file(tree1, &sfi);
    2433           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
    2434             :                                       "Incorrect status");
    2435             : 
    2436           2 :         torture_wait_for_oplock_break(tctx);
    2437           2 :         CHECK_VAL(break_info.count, 0);
    2438             : 
    2439           2 :         ZERO_STRUCT(qfi);
    2440           2 :         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
    2441           2 :         qfi.generic.in.file.handle = h1;
    2442             : 
    2443           2 :         status = smb2_getinfo_file(tree1, tctx, &qfi);
    2444           2 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2445           2 :         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
    2446             : 
    2447           2 :         torture_comment(tctx, "open the file a second time requesting batch "
    2448             :                         "(share mode: all)\n");
    2449           2 :         ZERO_STRUCT(break_info);
    2450           2 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2451           2 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2452           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2453             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    2454             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    2455           2 :         io.smb2.in.fname = fname1;
    2456           2 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2457           2 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2458           2 :         h2 = io.smb2.out.file.handle;
    2459           2 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2460             : 
    2461           2 :         torture_wait_for_oplock_break(tctx);
    2462           2 :         CHECK_VAL(break_info.count, 1);
    2463           2 :         CHECK_VAL(break_info.failures, 0);
    2464           2 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    2465             : 
    2466           2 :         torture_comment(tctx, "setfileinfo rename info should not trigger "
    2467             :                         "a break but should cause a sharing violation\n");
    2468           2 :         ZERO_STRUCT(break_info);
    2469           2 :         ZERO_STRUCT(sfi);
    2470           2 :         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
    2471           2 :         sfi.rename_information.in.file.handle   = h2;
    2472           2 :         sfi.rename_information.in.overwrite     = 0;
    2473           2 :         sfi.rename_information.in.new_name      = fname2;
    2474             : 
    2475           2 :         status = smb2_setinfo_file(tree2, &sfi);
    2476           2 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
    2477             :                                       "Incorrect status");
    2478             : 
    2479           0 :         torture_wait_for_oplock_break(tctx);
    2480           0 :         CHECK_VAL(break_info.count, 0);
    2481             : 
    2482           0 :         ZERO_STRUCT(qfi);
    2483           0 :         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
    2484           0 :         qfi.generic.in.file.handle = h1;
    2485             : 
    2486           0 :         status = smb2_getinfo_file(tree1, tctx, &qfi);
    2487           0 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2488           0 :         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
    2489             : 
    2490           0 :         ZERO_STRUCT(qfi);
    2491           0 :         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
    2492           0 :         qfi.generic.in.file.handle = h2;
    2493             : 
    2494           0 :         status = smb2_getinfo_file(tree2, tctx, &qfi);
    2495           0 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2496           0 :         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
    2497             : 
    2498           0 :         smb2_util_close(tree1, h1);
    2499           0 :         smb2_util_close(tree2, h2);
    2500           0 :         smb2_util_close(tree1, h);
    2501             : 
    2502           0 :         smb2_deltree(tree1, fname1);
    2503           0 :         return ret;
    2504             : }
    2505             : 
    2506           3 : static bool test_smb2_oplock_batch21(struct torture_context *tctx,
    2507             :                                      struct smb2_tree *tree1)
    2508             : {
    2509           3 :         const char *fname = BASEDIR "\\test_batch21.dat";
    2510           0 :         NTSTATUS status;
    2511           3 :         bool ret = true;
    2512           0 :         union smb_open io;
    2513           0 :         struct smb2_handle h, h1;
    2514           3 :         char c = 0;
    2515             : 
    2516           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2517           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2518             : 
    2519             :         /* cleanup */
    2520           3 :         smb2_util_unlink(tree1, fname);
    2521             : 
    2522           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2523           3 :         tree1->session->transport->oplock.private_data = tree1;
    2524             : 
    2525             :         /*
    2526             :           base ntcreatex parms
    2527             :         */
    2528           3 :         ZERO_STRUCT(io.smb2);
    2529           3 :         io.generic.level = RAW_OPEN_SMB2;
    2530           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2531           3 :         io.smb2.in.alloc_size = 0;
    2532           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2533           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2534           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2535           3 :         io.smb2.in.create_options = 0;
    2536           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2537           3 :         io.smb2.in.security_flags = 0;
    2538           3 :         io.smb2.in.fname = fname;
    2539             : 
    2540             :         /*
    2541             :           with a batch oplock we get a break
    2542             :         */
    2543           3 :         torture_comment(tctx, "BATCH21: open with batch oplock\n");
    2544           3 :         ZERO_STRUCT(break_info);
    2545           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2546           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2547           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2548           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2549           3 :         h1 = io.smb2.out.file.handle;
    2550           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2551             : 
    2552           3 :         torture_comment(tctx, "writing should not generate a break\n");
    2553           3 :         status = smb2_util_write(tree1, h1, &c, 0, 1);
    2554           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2555             : 
    2556           3 :         torture_wait_for_oplock_break(tctx);
    2557           3 :         CHECK_VAL(break_info.count, 0);
    2558             : 
    2559           3 :         smb2_util_close(tree1, h1);
    2560           3 :         smb2_util_close(tree1, h);
    2561             : 
    2562           3 :         smb2_deltree(tree1, BASEDIR);
    2563           3 :         return ret;
    2564             : }
    2565             : 
    2566           3 : static bool test_smb2_oplock_batch22a(struct torture_context *tctx,
    2567             :                                       struct smb2_tree *tree1)
    2568             : {
    2569           3 :         const char *fname = BASEDIR "\\test_batch22a.dat";
    2570           0 :         NTSTATUS status;
    2571           3 :         bool ret = true;
    2572           0 :         union smb_open io;
    2573           0 :         struct smb2_handle h, h1, h2;
    2574           0 :         struct timeval tv;
    2575           3 :         int timeout = torture_setting_int(tctx, "oplocktimeout", 35);
    2576           0 :         int te;
    2577             : 
    2578           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2579           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2580             : 
    2581             :         /* cleanup */
    2582           3 :         smb2_util_unlink(tree1, fname);
    2583             : 
    2584           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2585           3 :         tree1->session->transport->oplock.private_data = tree1;
    2586             :         /*
    2587             :           base ntcreatex parms
    2588             :         */
    2589           3 :         ZERO_STRUCT(io.smb2);
    2590           3 :         io.generic.level = RAW_OPEN_SMB2;
    2591           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2592           3 :         io.smb2.in.alloc_size = 0;
    2593           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2594           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2595           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2596           3 :         io.smb2.in.create_options = 0;
    2597           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2598           3 :         io.smb2.in.security_flags = 0;
    2599           3 :         io.smb2.in.fname = fname;
    2600             : 
    2601             :         /*
    2602             :           with a batch oplock we get a break
    2603             :         */
    2604           3 :         torture_comment(tctx, "BATCH22: open with batch oplock\n");
    2605           3 :         ZERO_STRUCT(break_info);
    2606           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2607           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2608           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2609             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    2610             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    2611           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2612           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2613           3 :         h1 = io.smb2.out.file.handle;
    2614           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2615             : 
    2616           3 :         torture_comment(tctx, "a 2nd open should succeed after the oplock "
    2617             :                         "break timeout\n");
    2618           3 :         tv = timeval_current();
    2619           3 :         tree1->session->transport->oplock.handler =
    2620             :                                 torture_oplock_handler_timeout;
    2621           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2622           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2623           2 :         h2 = io.smb2.out.file.handle;
    2624           2 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2625             : 
    2626           2 :         torture_wait_for_oplock_break(tctx);
    2627           2 :         te = (int)timeval_elapsed(&tv);
    2628           2 :         CHECK_RANGE(te, timeout - 1, timeout + 15);
    2629           2 :         torture_comment(tctx, "waited %d seconds for oplock timeout\n", te);
    2630             : 
    2631           2 :         CHECK_VAL(break_info.count, 1);
    2632           2 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    2633           2 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    2634           2 :         CHECK_VAL(break_info.failures, 0);
    2635             : 
    2636           2 :         smb2_util_close(tree1, h1);
    2637           2 :         smb2_util_close(tree1, h2);
    2638           2 :         smb2_util_close(tree1, h);
    2639             : 
    2640           2 :         smb2_deltree(tree1, BASEDIR);
    2641           2 :         return ret;
    2642             : }
    2643             : 
    2644           3 : static bool test_smb2_oplock_batch22b(struct torture_context *tctx,
    2645             :                                       struct smb2_tree *tree1,
    2646             :                                       struct smb2_tree *tree2)
    2647             : {
    2648           3 :         const char *fname = BASEDIR "\\test_batch22b.dat";
    2649           0 :         NTSTATUS status;
    2650           3 :         bool ret = true;
    2651           0 :         union smb_open io;
    2652           3 :         struct smb2_handle h, h1, h2 = {{0}};
    2653           0 :         struct timeval tv;
    2654           3 :         int timeout = torture_setting_int(tctx, "oplocktimeout", 35);
    2655           3 :         struct smb2_transport *transport1 = tree1->session->transport;
    2656           3 :         bool block_setup = false;
    2657           3 :         bool block_ok = false;
    2658           0 :         int te;
    2659             : 
    2660           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2661           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2662             : 
    2663             :         /* cleanup */
    2664           3 :         smb2_util_unlink(tree1, fname);
    2665             : 
    2666           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2667           3 :         tree1->session->transport->oplock.private_data = tree1;
    2668             :         /*
    2669             :           base ntcreatex parms
    2670             :         */
    2671           3 :         ZERO_STRUCT(io.smb2);
    2672           3 :         io.generic.level = RAW_OPEN_SMB2;
    2673           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2674           3 :         io.smb2.in.alloc_size = 0;
    2675           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2676           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2677           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2678           3 :         io.smb2.in.create_options = 0;
    2679           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2680           3 :         io.smb2.in.security_flags = 0;
    2681           3 :         io.smb2.in.fname = fname;
    2682             : 
    2683             :         /*
    2684             :           with a batch oplock we get a break
    2685             :         */
    2686           3 :         torture_comment(tctx, "BATCH22: open with batch oplock\n");
    2687           3 :         ZERO_STRUCT(break_info);
    2688           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2689           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2690           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2691             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    2692             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    2693           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2694           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2695           3 :         h1 = io.smb2.out.file.handle;
    2696           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2697             : 
    2698           3 :         torture_comment(tctx, "a 2nd open should succeed after the oplock "
    2699             :                         "break timeout\n");
    2700           3 :         tv = timeval_current();
    2701           3 :         tree1->session->transport->oplock.handler =
    2702             :                                 torture_oplock_handler_timeout;
    2703           3 :         block_setup = test_setup_blocked_transports(tctx);
    2704           3 :         torture_assert(tctx, block_setup, "test_setup_blocked_transports");
    2705           3 :         block_ok = test_block_smb2_transport(tctx, transport1);
    2706           3 :         torture_assert(tctx, block_ok, "test_block_smb2_transport");
    2707             : 
    2708           2 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2709           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Incorrect status");
    2710           2 :         h2 = io.smb2.out.file.handle;
    2711           2 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2712             : 
    2713           2 :         torture_wait_for_oplock_break(tctx);
    2714           2 :         te = (int)timeval_elapsed(&tv);
    2715           2 :         CHECK_RANGE(te, 0, timeout);
    2716           2 :         torture_comment(tctx, "waited %d seconds for oplock timeout\n", te);
    2717             : 
    2718           2 :         CHECK_VAL(break_info.count, 1);
    2719           2 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    2720           2 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    2721           2 :         CHECK_VAL(break_info.failures, 0);
    2722             : 
    2723           2 : done:
    2724           2 :         if (block_ok) {
    2725           2 :                 test_unblock_smb2_transport(tctx, transport1);
    2726             :         }
    2727           2 :         test_cleanup_blocked_transports(tctx);
    2728             : 
    2729           2 :         smb2_util_close(tree1, h1);
    2730           2 :         if (!smb2_util_handle_empty(h2)) {
    2731           2 :                 smb2_util_close(tree1, h2);
    2732             :         }
    2733           2 :         smb2_util_close(tree1, h);
    2734             : 
    2735           2 :         smb2_deltree(tree1, BASEDIR);
    2736           2 :         return ret;
    2737             : }
    2738             : 
    2739           3 : static bool test_smb2_oplock_batch23(struct torture_context *tctx,
    2740             :                                      struct smb2_tree *tree1,
    2741             :                                      struct smb2_tree *tree2)
    2742             : {
    2743           3 :         const char *fname = BASEDIR "\\test_batch23.dat";
    2744           0 :         NTSTATUS status;
    2745           3 :         bool ret = true;
    2746           0 :         union smb_open io;
    2747           0 :         struct smb2_handle h, h1, h2, h3;
    2748           3 :         struct smb2_tree *tree3 = NULL;
    2749             : 
    2750           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2751           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2752             : 
    2753             :         /* cleanup */
    2754           3 :         smb2_util_unlink(tree1, fname);
    2755             : 
    2756           3 :         ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
    2757           3 :         CHECK_VAL(ret, true);
    2758             : 
    2759           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2760           3 :         tree1->session->transport->oplock.private_data = tree1;
    2761             : 
    2762           3 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    2763           3 :         tree2->session->transport->oplock.private_data = tree2;
    2764             : 
    2765           3 :         tree3->session->transport->oplock.handler = torture_oplock_handler;
    2766           3 :         tree3->session->transport->oplock.private_data = tree3;
    2767             : 
    2768             :         /*
    2769             :           base ntcreatex parms
    2770             :         */
    2771           3 :         ZERO_STRUCT(io.smb2);
    2772           3 :         io.generic.level = RAW_OPEN_SMB2;
    2773           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2774           3 :         io.smb2.in.alloc_size = 0;
    2775           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2776           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2777           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2778           3 :         io.smb2.in.create_options = 0;
    2779           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2780           3 :         io.smb2.in.security_flags = 0;
    2781           3 :         io.smb2.in.fname = fname;
    2782             : 
    2783           3 :         torture_comment(tctx, "BATCH23: an open and ask for a batch oplock\n");
    2784           3 :         ZERO_STRUCT(break_info);
    2785             : 
    2786           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    2787             :                                 SEC_RIGHTS_FILE_WRITE;
    2788           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    2789             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    2790           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2791           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2792           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2793           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2794           3 :         h1 = io.smb2.out.file.handle;
    2795           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2796             : 
    2797           3 :         ZERO_STRUCT(break_info);
    2798             : 
    2799           3 :         torture_comment(tctx, "a 2nd open without level2 oplock support "
    2800             :                         "should generate a break to level2\n");
    2801           3 :         status = smb2_create(tree3, tctx, &(io.smb2));
    2802           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2803           3 :         h3 = io.smb2.out.file.handle;
    2804             : 
    2805           3 :         torture_wait_for_oplock_break(tctx);
    2806           3 :         CHECK_VAL(break_info.count, 1);
    2807           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    2808           3 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    2809           3 :         CHECK_VAL(break_info.failures, 0);
    2810             : 
    2811           3 :         ZERO_STRUCT(break_info);
    2812             : 
    2813           3 :         torture_comment(tctx, "a 3rd open with level2 oplock support should "
    2814             :                         "not generate a break\n");
    2815           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2816           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2817           3 :         h2 = io.smb2.out.file.handle;
    2818           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2819             : 
    2820           3 :         torture_wait_for_oplock_break(tctx);
    2821           3 :         CHECK_VAL(break_info.count, 0);
    2822             : 
    2823           3 :         smb2_util_close(tree1, h1);
    2824           3 :         smb2_util_close(tree2, h2);
    2825           3 :         smb2_util_close(tree3, h3);
    2826           3 :         smb2_util_close(tree1, h);
    2827             : 
    2828           3 :         smb2_deltree(tree1, BASEDIR);
    2829           3 :         return ret;
    2830             : }
    2831             : 
    2832           3 : static bool test_smb2_oplock_batch24(struct torture_context *tctx,
    2833             :                                      struct smb2_tree *tree1,
    2834             :                                      struct smb2_tree *tree2)
    2835             : {
    2836           3 :         const char *fname = BASEDIR "\\test_batch24.dat";
    2837           0 :         NTSTATUS status;
    2838           3 :         bool ret = true;
    2839           0 :         union smb_open io;
    2840           0 :         struct smb2_handle h, h1, h2;
    2841           3 :         struct smb2_tree *tree3 = NULL;
    2842             : 
    2843           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2844           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2845             : 
    2846             :         /* cleanup */
    2847           3 :         smb2_util_unlink(tree1, fname);
    2848             : 
    2849           3 :         ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
    2850           3 :         CHECK_VAL(ret, true);
    2851             : 
    2852           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2853           3 :         tree1->session->transport->oplock.private_data = tree1;
    2854             : 
    2855           3 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    2856           3 :         tree2->session->transport->oplock.private_data = tree2;
    2857             : 
    2858           3 :         tree3->session->transport->oplock.handler = torture_oplock_handler;
    2859           3 :         tree3->session->transport->oplock.private_data = tree3;
    2860             : 
    2861             :         /*
    2862             :           base ntcreatex parms
    2863             :         */
    2864           3 :         ZERO_STRUCT(io.smb2);
    2865           3 :         io.generic.level = RAW_OPEN_SMB2;
    2866           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2867           3 :         io.smb2.in.alloc_size = 0;
    2868           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2869           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2870           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2871           3 :         io.smb2.in.create_options = 0;
    2872           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2873           3 :         io.smb2.in.security_flags = 0;
    2874           3 :         io.smb2.in.fname = fname;
    2875             : 
    2876           3 :         torture_comment(tctx, "BATCH24: a open without level support and "
    2877             :                         "ask for a batch oplock\n");
    2878           3 :         ZERO_STRUCT(break_info);
    2879             : 
    2880           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    2881             :                                 SEC_RIGHTS_FILE_WRITE;
    2882           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    2883             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    2884           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2885           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2886             : 
    2887           3 :         status = smb2_create(tree3, tctx, &(io.smb2));
    2888           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2889           3 :         h2 = io.smb2.out.file.handle;
    2890           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2891             : 
    2892           3 :         ZERO_STRUCT(break_info);
    2893             : 
    2894           3 :         torture_comment(tctx, "a 2nd open with level2 oplock support should "
    2895             :                         "generate a break\n");
    2896           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2897           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2898           3 :         h1 = io.smb2.out.file.handle;
    2899           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2900             : 
    2901           3 :         torture_wait_for_oplock_break(tctx);
    2902           3 :         CHECK_VAL(break_info.count, 1);
    2903           3 :         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
    2904           3 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    2905           3 :         CHECK_VAL(break_info.failures, 0);
    2906             : 
    2907           3 :         smb2_util_close(tree3, h2);
    2908           3 :         smb2_util_close(tree2, h1);
    2909           3 :         smb2_util_close(tree1, h);
    2910             : 
    2911           3 :         smb2_deltree(tree1, BASEDIR);
    2912           3 :         return ret;
    2913             : }
    2914             : 
    2915           3 : static bool test_smb2_oplock_batch25(struct torture_context *tctx,
    2916             :                                      struct smb2_tree *tree1)
    2917             : {
    2918           3 :         const char *fname = BASEDIR "\\test_batch25.dat";
    2919           0 :         NTSTATUS status;
    2920           3 :         bool ret = true;
    2921           0 :         union smb_open io;
    2922           0 :         struct smb2_handle h, h1;
    2923             : 
    2924           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2925           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2926             : 
    2927             :         /* cleanup */
    2928           3 :         smb2_util_unlink(tree1, fname);
    2929             : 
    2930           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2931           3 :         tree1->session->transport->oplock.private_data = tree1;
    2932             : 
    2933             :         /*
    2934             :           base ntcreatex parms
    2935             :         */
    2936           3 :         ZERO_STRUCT(io.smb2);
    2937           3 :         io.generic.level = RAW_OPEN_SMB2;
    2938           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2939           3 :         io.smb2.in.alloc_size = 0;
    2940           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2941           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2942           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2943           3 :         io.smb2.in.create_options = 0;
    2944           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2945           3 :         io.smb2.in.security_flags = 0;
    2946           3 :         io.smb2.in.fname = fname;
    2947             : 
    2948           3 :         torture_comment(tctx, "BATCH25: open a file with an batch oplock "
    2949             :                         "(share mode: none)\n");
    2950             : 
    2951           3 :         ZERO_STRUCT(break_info);
    2952           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2953           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2954             : 
    2955           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2956           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2957           3 :         h1 = io.smb2.out.file.handle;
    2958           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2959             : 
    2960           3 :         status = smb2_util_setatr(tree1, fname, FILE_ATTRIBUTE_HIDDEN);
    2961           3 :         torture_assert_ntstatus_ok(tctx, status, "Setting attributes "
    2962             :                                    "shouldn't trigger an oplock break");
    2963             : 
    2964           3 :         smb2_util_close(tree1, h1);
    2965           3 :         smb2_util_close(tree1, h);
    2966             : 
    2967           3 :         smb2_deltree(tree1, fname);
    2968           3 :         return ret;
    2969             : }
    2970             : 
    2971           3 : static bool test_smb2_oplock_batch26(struct torture_context *tctx,
    2972             :                                         struct smb2_tree *tree1)
    2973             : {
    2974             : 
    2975           0 :         NTSTATUS status;
    2976           3 :         bool ret = true;
    2977           0 :         union smb_open io;
    2978           0 :         struct smb2_handle h, h1, h2, h3;
    2979           3 :         const char *fname_base = BASEDIR "\\test_oplock.txt";
    2980           3 :         const char *stream = "Stream One:$DATA";
    2981           0 :         const char *fname_stream;
    2982             : 
    2983           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2984           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2985             : 
    2986           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2987           3 :         tree1->session->transport->oplock.private_data = tree1;
    2988             : 
    2989           3 :         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
    2990             : 
    2991             :         /*
    2992             :           base ntcreatex parms
    2993             :         */
    2994           3 :         ZERO_STRUCT(io.smb2);
    2995           3 :         io.generic.level = RAW_OPEN_SMB2;
    2996           3 :         io.smb2.in.desired_access = 0x120089;
    2997           3 :         io.smb2.in.alloc_size = 0;
    2998           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2999           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_DELETE |
    3000             :                                   NTCREATEX_SHARE_ACCESS_WRITE;
    3001           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3002           3 :         io.smb2.in.create_options = 0;
    3003           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3004           3 :         io.smb2.in.security_flags = 0;
    3005           3 :         io.smb2.in.fname = fname_base;
    3006             : 
    3007             :         /*
    3008             :           Open base file with a batch oplock.
    3009             :         */
    3010           3 :         torture_comment(tctx, "Open the base file with batch oplock\n");
    3011           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3012           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3013             : 
    3014           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3015           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening base file");
    3016           3 :         h1 = io.smb2.out.file.handle;
    3017           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3018             : 
    3019           3 :         torture_comment(tctx, "Got batch oplock on base file\n");
    3020             : 
    3021           3 :         torture_comment(tctx, "Opening stream file with batch oplock..\n");
    3022             : 
    3023           3 :         io.smb2.in.fname = fname_stream;
    3024             : 
    3025           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3026           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening stream file");
    3027           3 :         h2 = io.smb2.out.file.handle;
    3028           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3029             : 
    3030           3 :         torture_comment(tctx, "Got batch oplock on stream file\n");
    3031             : 
    3032           3 :         torture_comment(tctx, "Open base file again with batch oplock\n");
    3033             : 
    3034           3 :         io.smb2.in.fname = fname_base;
    3035             : 
    3036           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3037           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    3038           3 :         h3 = io.smb2.out.file.handle;
    3039           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    3040             : 
    3041           3 :         smb2_util_close(tree1, h1);
    3042           3 :         smb2_util_close(tree1, h2);
    3043           3 :         smb2_util_close(tree1, h3);
    3044           3 :         smb2_util_close(tree1, h);
    3045           3 :         smb2_deltree(tree1, BASEDIR);
    3046           3 :         return ret;
    3047             : 
    3048             : }
    3049             : 
    3050             : /* Test how oplocks work on streams. */
    3051           3 : static bool test_raw_oplock_stream1(struct torture_context *tctx,
    3052             :                                     struct smb2_tree *tree1,
    3053             :                                     struct smb2_tree *tree2)
    3054             : {
    3055           0 :         NTSTATUS status;
    3056           0 :         union smb_open io;
    3057           3 :         const char *fname_base = BASEDIR "\\test_stream1.txt";
    3058           0 :         const char *fname_stream, *fname_default_stream;
    3059           3 :         const char *default_stream = "::$DATA";
    3060           3 :         const char *stream = "Stream One:$DATA";
    3061           3 :         bool ret = true;
    3062           0 :         struct smb2_handle h, h_base, h_stream;
    3063           0 :         int i;
    3064             : 
    3065             : #define NSTREAM_OPLOCK_RESULTS 8
    3066           0 :         struct {
    3067             :                 const char **fname;
    3068             :                 bool open_base_file;
    3069             :                 uint32_t oplock_req;
    3070             :                 uint32_t oplock_granted;
    3071           3 :         } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
    3072             :                 /* Request oplock on stream without the base file open. */
    3073             :                 {&fname_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
    3074             :                 {&fname_default_stream, false, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
    3075             :                 {&fname_stream, false, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
    3076             :                 {&fname_default_stream, false,  SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
    3077             : 
    3078             :                 /* Request oplock on stream with the base file open. */
    3079             :                 {&fname_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_BATCH},
    3080             :                 {&fname_default_stream, true, SMB2_OPLOCK_LEVEL_BATCH, SMB2_OPLOCK_LEVEL_II},
    3081             :                 {&fname_stream, true, SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_EXCLUSIVE},
    3082             :                 {&fname_default_stream, true,  SMB2_OPLOCK_LEVEL_EXCLUSIVE, SMB2_OPLOCK_LEVEL_II},
    3083             :         };
    3084             : 
    3085           3 :         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
    3086           3 :         fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
    3087             :                                                default_stream);
    3088             : 
    3089           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    3090           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3091             : 
    3092             :         /* Initialize handles to "closed".  Using -1 in the first 64-bytes
    3093             :          * as the sentry for this */
    3094           3 :         h_stream.data[0] = -1;
    3095             : 
    3096             :         /* cleanup */
    3097           3 :         smb2_util_unlink(tree1, fname_base);
    3098             : 
    3099           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    3100           3 :         tree1->session->transport->oplock.private_data = tree1;
    3101             : 
    3102           3 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    3103           3 :         tree2->session->transport->oplock.private_data = tree2;
    3104             : 
    3105             :         /* Setup generic open parameters. */
    3106           3 :         ZERO_STRUCT(io.smb2);
    3107           3 :         io.generic.level = RAW_OPEN_SMB2;
    3108           3 :         io.smb2.in.desired_access = (SEC_FILE_READ_DATA |
    3109             :                                      SEC_FILE_WRITE_DATA |
    3110             :                                      SEC_FILE_APPEND_DATA |
    3111             :                                      SEC_STD_READ_CONTROL);
    3112           3 :         io.smb2.in.alloc_size = 0;
    3113           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3114           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3115             :                                   NTCREATEX_SHARE_ACCESS_WRITE;
    3116           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3117           3 :         io.smb2.in.create_options = 0;
    3118           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3119           3 :         io.smb2.in.security_flags = 0;
    3120             : 
    3121             :         /* Create the file with a stream */
    3122           3 :         io.smb2.in.fname = fname_stream;
    3123           3 :         io.smb2.in.create_flags = 0;
    3124           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    3125           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3126           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating file");
    3127           3 :         smb2_util_close(tree1, io.smb2.out.file.handle);
    3128             : 
    3129             :         /* Change the disposition to open now that the file has been created. */
    3130           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    3131             : 
    3132             :         /* Try some permutations of taking oplocks on streams. */
    3133          27 :         for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
    3134          24 :                 const char *fname = *stream_oplock_results[i].fname;
    3135          24 :                 bool open_base_file = stream_oplock_results[i].open_base_file;
    3136          24 :                 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
    3137          24 :                 uint32_t oplock_granted =
    3138             :                     stream_oplock_results[i].oplock_granted;
    3139             : 
    3140          24 :                 if (open_base_file) {
    3141          12 :                         torture_comment(tctx, "Opening base file: %s with "
    3142             :                             "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
    3143          12 :                         io.smb2.in.fname = fname_base;
    3144          12 :                         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3145          12 :                         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3146          12 :                         status = smb2_create(tree2, tctx, &(io.smb2));
    3147          12 :                         torture_assert_ntstatus_ok(tctx, status,
    3148             :                             "Error opening file");
    3149          12 :                         CHECK_VAL(io.smb2.out.oplock_level,
    3150             :                             SMB2_OPLOCK_LEVEL_BATCH);
    3151          12 :                         h_base = io.smb2.out.file.handle;
    3152             :                 }
    3153             : 
    3154          24 :                 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
    3155             :                     fname, oplock_req);
    3156          24 :                 io.smb2.in.fname = fname;
    3157          24 :                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3158          24 :                 io.smb2.in.oplock_level = oplock_req;
    3159             : 
    3160             :                 /* Do the open with the desired oplock on the stream. */
    3161          24 :                 status = smb2_create(tree1, tctx, &(io.smb2));
    3162          24 :                 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
    3163          24 :                 CHECK_VAL(io.smb2.out.oplock_level, oplock_granted);
    3164          24 :                 smb2_util_close(tree1, io.smb2.out.file.handle);
    3165             : 
    3166             :                 /* Cleanup the base file if it was opened. */
    3167          24 :                 if (open_base_file)
    3168          12 :                         smb2_util_close(tree2, h_base);
    3169             :         }
    3170             : 
    3171             :         /* Open the stream with an exclusive oplock. */
    3172           3 :         torture_comment(tctx, "Opening stream: %s with %d\n",
    3173             :             fname_stream, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
    3174           3 :         io.smb2.in.fname = fname_stream;
    3175           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3176           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    3177           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3178           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
    3179           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
    3180           3 :         h_stream = io.smb2.out.file.handle;
    3181             : 
    3182             :         /* Open the base file and see if it contends. */
    3183           3 :         ZERO_STRUCT(break_info);
    3184           3 :         torture_comment(tctx, "Opening base file: %s with %d\n",
    3185             :             fname_base, SMB2_OPLOCK_LEVEL_BATCH);
    3186           3 :         io.smb2.in.fname = fname_base;
    3187           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3188           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3189           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    3190           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
    3191           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3192           3 :         smb2_util_close(tree2, io.smb2.out.file.handle);
    3193             : 
    3194           3 :         torture_wait_for_oplock_break(tctx);
    3195           3 :         CHECK_VAL(break_info.count, 0);
    3196           3 :         CHECK_VAL(break_info.failures, 0);
    3197             : 
    3198             :         /* Open the stream again to see if it contends. */
    3199           3 :         ZERO_STRUCT(break_info);
    3200           3 :         torture_comment(tctx, "Opening stream again: %s with "
    3201             :             "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
    3202           3 :         io.smb2.in.fname = fname_stream;
    3203           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3204           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    3205           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    3206           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
    3207           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    3208           3 :         smb2_util_close(tree2, io.smb2.out.file.handle);
    3209             : 
    3210           3 :         torture_wait_for_oplock_break(tctx);
    3211           3 :         CHECK_VAL(break_info.count, 1);
    3212           3 :         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
    3213           3 :         CHECK_VAL(break_info.failures, 0);
    3214             : 
    3215             :         /* Close the stream. */
    3216           3 :         if (h_stream.data[0] != -1) {
    3217           3 :                 smb2_util_close(tree1, h_stream);
    3218             :         }
    3219             : 
    3220           3 :         smb2_util_close(tree1, h);
    3221             : 
    3222           3 :         smb2_deltree(tree1, BASEDIR);
    3223           3 :         return ret;
    3224             : }
    3225             : 
    3226           3 : static bool test_smb2_oplock_doc(struct torture_context *tctx, struct smb2_tree *tree,
    3227             :                                  struct smb2_tree *tree2)
    3228             : {
    3229           3 :         const char *fname = BASEDIR "\\test_oplock_doc.dat";
    3230           0 :         NTSTATUS status;
    3231           3 :         bool ret = true;
    3232           0 :         union smb_open io;
    3233           0 :         struct smb2_handle h, h1;
    3234           0 :         union smb_setfileinfo sfinfo;
    3235             : 
    3236           3 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    3237           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3238           3 :         smb2_util_close(tree, h);
    3239             : 
    3240             :         /* cleanup */
    3241           3 :         smb2_util_unlink(tree, fname);
    3242           3 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    3243           3 :         tree->session->transport->oplock.private_data = tree;
    3244             : 
    3245             :         /*
    3246             :           base ntcreatex parms
    3247             :         */
    3248           3 :         ZERO_STRUCT(io.smb2);
    3249           3 :         io.generic.level = RAW_OPEN_SMB2;
    3250           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    3251           3 :         io.smb2.in.alloc_size = 0;
    3252           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3253           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    3254             :                 NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
    3255           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3256           3 :         io.smb2.in.create_options = 0;
    3257           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3258           3 :         io.smb2.in.security_flags = 0;
    3259           3 :         io.smb2.in.fname = fname;
    3260             : 
    3261           3 :         torture_comment(tctx, "open a file with a batch oplock\n");
    3262           3 :         ZERO_STRUCT(break_info);
    3263           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3264           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3265             : 
    3266           3 :         status = smb2_create(tree, tctx, &(io.smb2));
    3267           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3268           3 :         h1 = io.smb2.out.file.handle;
    3269           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3270             : 
    3271           3 :         torture_comment(tctx, "Set delete on close\n");
    3272           3 :         ZERO_STRUCT(sfinfo);
    3273           3 :         sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
    3274           3 :         sfinfo.generic.in.file.handle = h1;
    3275           3 :         sfinfo.disposition_info.in.delete_on_close = 1;
    3276           3 :         status = smb2_setinfo_file(tree, &sfinfo);
    3277           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3278             : 
    3279           3 :         torture_comment(tctx, "2nd open should not break and get "
    3280             :                         "DELETE_PENDING\n");
    3281           3 :         ZERO_STRUCT(break_info);
    3282           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    3283           3 :         io.smb2.in.create_options = 0;
    3284           3 :         io.smb2.in.desired_access = SEC_FILE_READ_DATA;
    3285           3 :         status = smb2_create(tree2, tctx, &io.smb2);
    3286           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DELETE_PENDING,
    3287             :                                       "Incorrect status");
    3288           3 :         CHECK_VAL(break_info.count, 0);
    3289             : 
    3290           3 :         smb2_util_close(tree, h1);
    3291             : 
    3292           3 :         smb2_util_unlink(tree, fname);
    3293           3 :         smb2_deltree(tree, BASEDIR);
    3294           3 :         return ret;
    3295             : }
    3296             : 
    3297             : /* Open a file with a batch oplock, then open it again from a second client
    3298             :  * requesting no oplock. Having two open file handles should break our own
    3299             :  * oplock during BRL acquisition.
    3300             :  */
    3301           3 : static bool test_smb2_oplock_brl1(struct torture_context *tctx,
    3302             :                                 struct smb2_tree *tree1,
    3303             :                                 struct smb2_tree *tree2)
    3304             : {
    3305           3 :         const char *fname = BASEDIR "\\test_batch_brl.dat";
    3306             :         /*int fname, f;*/
    3307           3 :         bool ret = true;
    3308           0 :         uint8_t buf[1000];
    3309           0 :         union smb_open io;
    3310           0 :         NTSTATUS status;
    3311           0 :         struct smb2_lock lck;
    3312           0 :         struct smb2_lock_element lock[1];
    3313           0 :         struct smb2_handle h, h1, h2;
    3314             : 
    3315           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    3316           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3317             : 
    3318             :         /* cleanup */
    3319           3 :         smb2_util_unlink(tree1, fname);
    3320             : 
    3321           3 :         tree1->session->transport->oplock.handler =
    3322             :             torture_oplock_handler_two_notifications;
    3323           3 :         tree1->session->transport->oplock.private_data = tree1;
    3324             : 
    3325             :         /*
    3326             :           base ntcreatex parms
    3327             :         */
    3328           3 :         ZERO_STRUCT(io.smb2);
    3329           3 :         io.generic.level = RAW_OPEN_SMB2;
    3330           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    3331             :                                     SEC_RIGHTS_FILE_WRITE;
    3332           3 :         io.smb2.in.alloc_size = 0;
    3333           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3334           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3335             :                                   NTCREATEX_SHARE_ACCESS_WRITE;
    3336           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3337           3 :         io.smb2.in.create_options = 0;
    3338           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3339           3 :         io.smb2.in.security_flags = 0;
    3340           3 :         io.smb2.in.fname = fname;
    3341             : 
    3342             :         /*
    3343             :           with a batch oplock we get a break
    3344             :         */
    3345           3 :         torture_comment(tctx, "open with batch oplock\n");
    3346           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3347           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3348             : 
    3349           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3350           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    3351           3 :         h1 = io.smb2.out.file.handle;
    3352           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3353             : 
    3354             :         /* create a file with bogus data */
    3355           3 :         memset(buf, 0, sizeof(buf));
    3356             : 
    3357           3 :         status = smb2_util_write(tree1, h1,buf, 0, sizeof(buf));
    3358           3 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
    3359           0 :                 torture_comment(tctx, "Failed to create file\n");
    3360           0 :                 ret = false;
    3361           0 :                 goto done;
    3362             :         }
    3363             : 
    3364           3 :         torture_comment(tctx, "a 2nd open should give a break\n");
    3365           3 :         ZERO_STRUCT(break_info);
    3366             : 
    3367           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3368           3 :         io.smb2.in.oplock_level = 0;
    3369           3 :         status = smb2_create(tree2, tctx, &(io.smb2));
    3370           3 :         h2 = io.smb2.out.file.handle;
    3371           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3372             : 
    3373           3 :         torture_wait_for_oplock_break(tctx);
    3374           3 :         CHECK_VAL(break_info.count, 1);
    3375           3 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    3376           3 :         CHECK_VAL(break_info.failures, 0);
    3377           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    3378             : 
    3379           3 :         ZERO_STRUCT(break_info);
    3380             : 
    3381           3 :         torture_comment(tctx, "a self BRL acquisition should break to none\n");
    3382             : 
    3383           3 :         ZERO_STRUCT(lock);
    3384             : 
    3385           3 :         lock[0].offset = 0;
    3386           3 :         lock[0].length = 4;
    3387           3 :         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
    3388             :                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3389             : 
    3390           3 :         ZERO_STRUCT(lck);
    3391           3 :         lck.in.file.handle = h1;
    3392           3 :         lck.in.locks = &lock[0];
    3393           3 :         lck.in.lock_count = 1;
    3394           3 :         status = smb2_lock(tree1, &lck);
    3395           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3396             : 
    3397           3 :         torture_wait_for_oplock_break(tctx);
    3398           3 :         CHECK_VAL(break_info.count, 1);
    3399           3 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
    3400           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    3401           3 :         CHECK_VAL(break_info.failures, 0);
    3402             : 
    3403             :         /* expect no oplock break */
    3404           3 :         ZERO_STRUCT(break_info);
    3405           3 :         lock[0].offset = 2;
    3406           3 :         status = smb2_lock(tree1, &lck);
    3407           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
    3408             :                                       "Incorrect status");
    3409             : 
    3410           3 :         torture_wait_for_oplock_break(tctx);
    3411           3 :         CHECK_VAL(break_info.count, 0);
    3412           3 :         CHECK_VAL(break_info.level, 0);
    3413           3 :         CHECK_VAL(break_info.failures, 0);
    3414             : 
    3415           3 :         smb2_util_close(tree1, h1);
    3416           3 :         smb2_util_close(tree2, h2);
    3417           3 :         smb2_util_close(tree1, h);
    3418             : 
    3419           3 : done:
    3420           3 :         smb2_deltree(tree1, BASEDIR);
    3421           3 :         return ret;
    3422             : 
    3423             : }
    3424             : 
    3425             : /* Open a file with a batch oplock on one tree and then acquire a brl.
    3426             :  * We should not contend our own oplock.
    3427             :  */
    3428           3 : static bool test_smb2_oplock_brl2(struct torture_context *tctx, struct smb2_tree *tree1)
    3429             : {
    3430           3 :         const char *fname = BASEDIR "\\test_batch_brl.dat";
    3431             :         /*int fname, f;*/
    3432           3 :         bool ret = true;
    3433           0 :         uint8_t buf[1000];
    3434           0 :         union smb_open io;
    3435           0 :         NTSTATUS status;
    3436           0 :         struct smb2_handle h, h1;
    3437           0 :         struct smb2_lock lck;
    3438           0 :         struct smb2_lock_element lock[1];
    3439             : 
    3440           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    3441           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3442             : 
    3443             :         /* cleanup */
    3444           3 :         smb2_util_unlink(tree1, fname);
    3445             : 
    3446           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    3447           3 :         tree1->session->transport->oplock.private_data = tree1;
    3448             : 
    3449             :         /*
    3450             :           base ntcreatex parms
    3451             :         */
    3452           3 :         ZERO_STRUCT(io.smb2);
    3453           3 :         io.generic.level = RAW_OPEN_SMB2;
    3454           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    3455             :                                     SEC_RIGHTS_FILE_WRITE;
    3456           3 :         io.smb2.in.alloc_size = 0;
    3457           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3458           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3459             :                                   NTCREATEX_SHARE_ACCESS_WRITE;
    3460           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3461           3 :         io.smb2.in.create_options = 0;
    3462           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3463           3 :         io.smb2.in.security_flags = 0;
    3464           3 :         io.smb2.in.fname = fname;
    3465             : 
    3466             :         /*
    3467             :           with a batch oplock we get a break
    3468             :         */
    3469           3 :         torture_comment(tctx, "open with batch oplock\n");
    3470           3 :         ZERO_STRUCT(break_info);
    3471           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3472           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3473             : 
    3474           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3475           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    3476           3 :         h1 = io.smb2.out.file.handle;
    3477           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3478             : 
    3479             :         /* create a file with bogus data */
    3480           3 :         memset(buf, 0, sizeof(buf));
    3481             : 
    3482           3 :         status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
    3483           3 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
    3484           0 :                 torture_comment(tctx, "Failed to create file\n");
    3485           0 :                 ret = false;
    3486           0 :                 goto done;
    3487             :         }
    3488             : 
    3489           3 :         ZERO_STRUCT(break_info);
    3490             : 
    3491           3 :         torture_comment(tctx, "a self BRL acquisition should not break to "
    3492             :                         "none\n");
    3493             : 
    3494           3 :         ZERO_STRUCT(lock);
    3495             : 
    3496           3 :         lock[0].offset = 0;
    3497           3 :         lock[0].length = 4;
    3498           3 :         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
    3499             :                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3500             : 
    3501           3 :         ZERO_STRUCT(lck);
    3502           3 :         lck.in.file.handle = h1;
    3503           3 :         lck.in.locks = &lock[0];
    3504           3 :         lck.in.lock_count = 1;
    3505           3 :         status = smb2_lock(tree1, &lck);
    3506           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3507             : 
    3508           3 :         lock[0].offset = 2;
    3509           3 :         status = smb2_lock(tree1, &lck);
    3510           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
    3511             :                                       "Incorrect status");
    3512             : 
    3513             :         /* With one file handle open a BRL should not contend our oplock.
    3514             :          * Thus, no oplock break will be received and the entire break_info
    3515             :          * struct will be 0 */
    3516           3 :         torture_wait_for_oplock_break(tctx);
    3517           3 :         CHECK_VAL(break_info.count, 0);
    3518           3 :         CHECK_VAL(break_info.level, 0);
    3519           3 :         CHECK_VAL(break_info.failures, 0);
    3520             : 
    3521           3 :         smb2_util_close(tree1, h1);
    3522           3 :         smb2_util_close(tree1, h);
    3523             : 
    3524           3 : done:
    3525           3 :         smb2_deltree(tree1, BASEDIR);
    3526           3 :         return ret;
    3527             : }
    3528             : 
    3529             : /* Open a file with a batch oplock twice from one tree and then acquire a
    3530             :  * brl. BRL acquisition should break our own oplock.
    3531             :  */
    3532           3 : static bool test_smb2_oplock_brl3(struct torture_context *tctx, struct smb2_tree *tree1)
    3533             : {
    3534           3 :         const char *fname = BASEDIR "\\test_batch_brl.dat";
    3535           3 :         bool ret = true;
    3536           0 :         uint8_t buf[1000];
    3537           0 :         union smb_open io;
    3538           0 :         NTSTATUS status;
    3539           0 :         struct smb2_handle h, h1, h2;
    3540           0 :         struct smb2_lock lck;
    3541           0 :         struct smb2_lock_element lock[1];
    3542             : 
    3543           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    3544           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3545             : 
    3546             :         /* cleanup */
    3547           3 :         smb2_util_unlink(tree1, fname);
    3548           3 :         tree1->session->transport->oplock.handler =
    3549             :             torture_oplock_handler_two_notifications;
    3550           3 :         tree1->session->transport->oplock.private_data = tree1;
    3551             : 
    3552             :         /*
    3553             :           base ntcreatex parms
    3554             :         */
    3555           3 :         ZERO_STRUCT(io.smb2);
    3556           3 :         io.generic.level = RAW_OPEN_SMB2;
    3557           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    3558             :                                     SEC_RIGHTS_FILE_WRITE;
    3559           3 :         io.smb2.in.alloc_size = 0;
    3560           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3561           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3562             :                                   NTCREATEX_SHARE_ACCESS_WRITE;
    3563           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3564           3 :         io.smb2.in.create_options = 0;
    3565           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3566           3 :         io.smb2.in.security_flags = 0;
    3567           3 :         io.smb2.in.fname = fname;
    3568             : 
    3569             :         /*
    3570             :           with a batch oplock we get a break
    3571             :         */
    3572           3 :         torture_comment(tctx, "open with batch oplock\n");
    3573           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3574           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3575             : 
    3576           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3577           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    3578           3 :         h1 = io.smb2.out.file.handle;
    3579           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3580             : 
    3581             :         /* create a file with bogus data */
    3582           3 :         memset(buf, 0, sizeof(buf));
    3583           3 :         status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
    3584             : 
    3585           3 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
    3586           0 :                 torture_comment(tctx, "Failed to create file\n");
    3587           0 :                 ret = false;
    3588           0 :                 goto done;
    3589             :         }
    3590             : 
    3591           3 :         torture_comment(tctx, "a 2nd open should give a break\n");
    3592           3 :         ZERO_STRUCT(break_info);
    3593             : 
    3594           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3595           3 :         io.smb2.in.oplock_level = 0;
    3596           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3597           3 :         h2 = io.smb2.out.file.handle;
    3598           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3599           3 :         CHECK_VAL(break_info.count, 1);
    3600           3 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    3601           3 :         CHECK_VAL(break_info.failures, 0);
    3602           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    3603             : 
    3604           3 :         ZERO_STRUCT(break_info);
    3605             : 
    3606           3 :         torture_comment(tctx, "a self BRL acquisition should break to none\n");
    3607             : 
    3608           3 :         ZERO_STRUCT(lock);
    3609             : 
    3610           3 :         lock[0].offset = 0;
    3611           3 :         lock[0].length = 4;
    3612           3 :         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
    3613             :                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3614             : 
    3615           3 :         ZERO_STRUCT(lck);
    3616           3 :         lck.in.file.handle = h1;
    3617           3 :         lck.in.locks = &lock[0];
    3618           3 :         lck.in.lock_count = 1;
    3619           3 :         status = smb2_lock(tree1, &lck);
    3620           3 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3621             : 
    3622           3 :         torture_wait_for_oplock_break(tctx);
    3623           3 :         CHECK_VAL(break_info.count, 1);
    3624           3 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
    3625           3 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    3626           3 :         CHECK_VAL(break_info.failures, 0);
    3627             : 
    3628             :         /* expect no oplock break */
    3629           3 :         ZERO_STRUCT(break_info);
    3630           3 :         lock[0].offset = 2;
    3631           3 :         status = smb2_lock(tree1, &lck);
    3632           3 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
    3633             :                                       "Incorrect status");
    3634             : 
    3635           3 :         torture_wait_for_oplock_break(tctx);
    3636           3 :         CHECK_VAL(break_info.count, 0);
    3637           3 :         CHECK_VAL(break_info.level, 0);
    3638           3 :         CHECK_VAL(break_info.failures, 0);
    3639             : 
    3640           3 :         smb2_util_close(tree1, h1);
    3641           3 :         smb2_util_close(tree1, h2);
    3642           3 :         smb2_util_close(tree1, h);
    3643             : 
    3644           3 : done:
    3645           3 :         smb2_deltree(tree1, BASEDIR);
    3646           3 :         return ret;
    3647             : 
    3648             : }
    3649             : 
    3650             : /* Starting the SMB2 specific oplock tests at 500 so we can keep the SMB1
    3651             :  * tests in sync with an identically numbered SMB2 test */
    3652             : 
    3653             : /* Test whether the server correctly returns an error when we send
    3654             :  * a response to a levelII to none oplock notification. */
    3655           3 : static bool test_smb2_oplock_levelII500(struct torture_context *tctx,
    3656             :                                       struct smb2_tree *tree1)
    3657             : {
    3658           3 :         const char *fname = BASEDIR "\\test_levelII500.dat";
    3659           0 :         NTSTATUS status;
    3660           3 :         bool ret = true;
    3661           0 :         union smb_open io;
    3662           0 :         struct smb2_handle h, h1;
    3663           3 :         char c = 0;
    3664             : 
    3665           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    3666           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3667             : 
    3668             :         /* cleanup */
    3669           3 :         smb2_util_unlink(tree1, fname);
    3670             : 
    3671           3 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    3672           3 :         tree1->session->transport->oplock.private_data = tree1;
    3673             : 
    3674             :         /*
    3675             :           base ntcreatex parms
    3676             :         */
    3677           3 :         ZERO_STRUCT(io.smb2);
    3678           3 :         io.generic.level = RAW_OPEN_SMB2;
    3679           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    3680           3 :         io.smb2.in.alloc_size = 0;
    3681           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3682           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3683           3 :         io.smb2.in.create_options = 0;
    3684           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3685           3 :         io.smb2.in.security_flags = 0;
    3686           3 :         io.smb2.in.fname = fname;
    3687             : 
    3688           3 :         torture_comment(tctx, "LEVELII500: acknowledging a break from II to "
    3689             :                         "none should return an error\n");
    3690           3 :         ZERO_STRUCT(break_info);
    3691             : 
    3692           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    3693             :                                 SEC_RIGHTS_FILE_WRITE;
    3694           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3695             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    3696           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3697           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
    3698           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3699           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    3700           3 :         h1 = io.smb2.out.file.handle;
    3701           3 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    3702             : 
    3703           3 :         ZERO_STRUCT(break_info);
    3704             : 
    3705           3 :         torture_comment(tctx, "write should trigger a break to none and when "
    3706             :                         "we reply, an oplock break failure\n");
    3707           3 :         smb2_util_write(tree1, h1, &c, 0, 1);
    3708             : 
    3709             :         /* Wait several times to receive both the break notification, and the
    3710             :          * NT_STATUS_INVALID_OPLOCK_PROTOCOL error in the break response */
    3711           3 :         torture_wait_for_oplock_break(tctx);
    3712           3 :         torture_wait_for_oplock_break(tctx);
    3713           3 :         torture_wait_for_oplock_break(tctx);
    3714           3 :         torture_wait_for_oplock_break(tctx);
    3715             : 
    3716             :         /* There appears to be a race condition in W2K8 and W2K8R2 where
    3717             :          * sometimes the server will happily reply to our break response with
    3718             :          * NT_STATUS_OK, and sometimes it will return the OPLOCK_PROTOCOL
    3719             :          * error.  As the MS-SMB2 doc states that a client should not reply to
    3720             :          * a level2 to none break notification, I'm leaving the protocol error
    3721             :          * as the expected behavior. */
    3722           3 :         CHECK_VAL(break_info.count, 1);
    3723           3 :         CHECK_VAL(break_info.level, 0);
    3724           3 :         CHECK_VAL(break_info.failures, 1);
    3725           3 :         torture_assert_ntstatus_equal(tctx, break_info.failure_status,
    3726             :                                       NT_STATUS_INVALID_OPLOCK_PROTOCOL,
    3727             :                                       "Incorrect status");
    3728             : 
    3729           2 :         smb2_util_close(tree1, h1);
    3730           2 :         smb2_util_close(tree1, h);
    3731             : 
    3732           2 :         smb2_deltree(tree1, BASEDIR);
    3733           2 :         return ret;
    3734             : }
    3735             : 
    3736             : /*
    3737             :  * Test a double-break. Open a file with exclusive. Send off a second open
    3738             :  * request with OPEN_IF, triggering a break to level2. This should respond
    3739             :  * with level2. Before replying to the break to level2, fire off a third open
    3740             :  * with OVERWRITE_IF. The expected sequence would be that the 3rd opener gets
    3741             :  * a level2 immediately triggered by a break to none, but that seems not the
    3742             :  * case. Still investigating what the right behaviour should be.
    3743             :  */
    3744             : 
    3745             : struct levelII501_state {
    3746             :         struct torture_context *tctx;
    3747             :         struct smb2_tree *tree1;
    3748             :         struct smb2_tree *tree2;
    3749             :         struct smb2_tree *tree3;
    3750             :         struct smb2_handle h;
    3751             :         struct smb2_handle h1;
    3752             :         union smb_open io;
    3753             : 
    3754             :         struct smb2_handle break_handle;
    3755             :         uint8_t break_to;
    3756             :         struct smb2_break br;
    3757             : 
    3758             :         bool done;
    3759             : };
    3760             : 
    3761             : static bool torture_oplock_break_delay(struct smb2_transport *transport,
    3762             :                                        const struct smb2_handle *handle,
    3763             :                                        uint8_t level, void *private_data);
    3764             : static void levelII501_break_done(struct smb2_request *req);
    3765             : static void levelII501_open1_done(struct smb2_request *req);
    3766             : static void levelII501_open2_done(struct smb2_request *req);
    3767             : static void levelII501_2ndopen_cb(struct tevent_context *ev,
    3768             :                                   struct tevent_timer *te,
    3769             :                                   struct timeval current_time,
    3770             :                                   void *private_data);
    3771             : static void levelII501_break_timeout_cb(struct tevent_context *ev,
    3772             :                                         struct tevent_timer *te,
    3773             :                                         struct timeval current_time,
    3774             :                                         void *private_data);
    3775             : static void levelII501_timeout_cb(struct tevent_context *ev,
    3776             :                                   struct tevent_timer *te,
    3777             :                                   struct timeval current_time,
    3778             :                                   void *private_data);
    3779             : 
    3780           3 : static bool test_smb2_oplock_levelII501(struct torture_context *tctx,
    3781             :                                         struct smb2_tree *tree1,
    3782             :                                         struct smb2_tree *tree2)
    3783             : {
    3784           3 :         const char *fname = BASEDIR "\\test_levelII501.dat";
    3785           0 :         NTSTATUS status;
    3786           3 :         bool ret = true;
    3787           0 :         struct levelII501_state *state;
    3788           0 :         struct smb2_request *req;
    3789           0 :         struct tevent_timer *te;
    3790             : 
    3791           3 :         state = talloc(tctx, struct levelII501_state);
    3792           3 :         state->tctx = tctx;
    3793           3 :         state->done = false;
    3794           3 :         state->tree1 = tree1;
    3795           3 :         state->tree2 = tree2;
    3796             : 
    3797           3 :         if (!torture_smb2_connection(tctx, &state->tree3)) {
    3798           0 :                 torture_fail(tctx, "Establishing SMB2 connection failed\n");
    3799             :                 return false;
    3800             :         }
    3801             : 
    3802           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &state->h);
    3803           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3804             : 
    3805             :         /* cleanup */
    3806           3 :         smb2_util_unlink(tree1, fname);
    3807             : 
    3808             :         /*
    3809             :           base ntcreatex parms
    3810             :         */
    3811           3 :         ZERO_STRUCT(state->io.smb2);
    3812           3 :         state->io.generic.level = RAW_OPEN_SMB2;
    3813           3 :         state->io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    3814           3 :         state->io.smb2.in.alloc_size = 0;
    3815           3 :         state->io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3816           3 :         state->io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3817           3 :         state->io.smb2.in.create_options = 0;
    3818           3 :         state->io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3819           3 :         state->io.smb2.in.security_flags = 0;
    3820           3 :         state->io.smb2.in.fname = fname;
    3821             : 
    3822           3 :         torture_comment(tctx, "LEVELII501: Test double break sequence\n");
    3823           3 :         ZERO_STRUCT(break_info);
    3824             : 
    3825           3 :         state->io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    3826             :                                 SEC_RIGHTS_FILE_WRITE;
    3827           3 :         state->io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3828             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    3829           3 :         state->io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3830           3 :         state->io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    3831             : 
    3832           3 :         tree1->session->transport->oplock.handler = torture_oplock_break_delay;
    3833           3 :         tree1->session->transport->oplock.private_data = state;
    3834             : 
    3835           3 :         status = smb2_create(tree1, tctx, &(state->io.smb2));
    3836           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    3837           3 :         state->h1 = state->io.smb2.out.file.handle;
    3838           3 :         CHECK_VAL(state->io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
    3839             : 
    3840             :         /*
    3841             :          * Trigger a break to level2
    3842             :          */
    3843             : 
    3844           3 :         req = smb2_create_send(tree2, &state->io.smb2);
    3845           3 :         req->async.fn = levelII501_open1_done;
    3846           3 :         req->async.private_data = state;
    3847             : 
    3848           3 :         te = tevent_add_timer(
    3849             :                 tctx->ev, tctx, tevent_timeval_current_ofs(0, 200000),
    3850             :                 levelII501_2ndopen_cb, state);
    3851           3 :         torture_assert(tctx, te != NULL, "tevent_add_timer failed\n");
    3852             : 
    3853           3 :         te = tevent_add_timer(
    3854             :                 tctx->ev, tctx, tevent_timeval_current_ofs(2, 0),
    3855             :                 levelII501_timeout_cb, state);
    3856           3 :         torture_assert(tctx, te != NULL, "tevent_add_timer failed\n");
    3857             : 
    3858          91 :         while (!state->done) {
    3859          88 :                 if (tevent_loop_once(tctx->ev) != 0) {
    3860           0 :                         torture_comment(tctx, "tevent_loop_once failed\n");
    3861             :                 }
    3862             :         }
    3863             : 
    3864           3 :         return ret;
    3865             : }
    3866             : 
    3867             : /*
    3868             :  * Fire off a second open after a little timeout
    3869             :  */
    3870             : 
    3871           3 : static void levelII501_2ndopen_cb(struct tevent_context *ev,
    3872             :                                   struct tevent_timer *te,
    3873             :                                   struct timeval current_time,
    3874             :                                   void *private_data)
    3875             : {
    3876           3 :         struct levelII501_state *state = talloc_get_type_abort(
    3877             :                 private_data, struct levelII501_state);
    3878           0 :         struct smb2_request *req;
    3879             : 
    3880           3 :         state->io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
    3881           3 :         req = smb2_create_send(state->tree3, &state->io.smb2);
    3882           3 :         req->async.fn = levelII501_open2_done;
    3883           3 :         req->async.private_data = state;
    3884           3 : }
    3885             : 
    3886             : /*
    3887             :  * Postpone the break response by 500 msec
    3888             :  */
    3889           5 : static bool torture_oplock_break_delay(struct smb2_transport *transport,
    3890             :                                        const struct smb2_handle *handle,
    3891             :                                        uint8_t level, void *private_data)
    3892             : {
    3893           5 :         struct levelII501_state *state = talloc_get_type_abort(
    3894             :                 private_data, struct levelII501_state);
    3895           0 :         const char *name;
    3896           0 :         struct tevent_timer *te;
    3897             : 
    3898           5 :         break_info.handle       = *handle;
    3899           5 :         break_info.level        = level;
    3900           5 :         break_info.count++;
    3901             : 
    3902           5 :         state->break_handle = *handle;
    3903           5 :         state->break_to = level;
    3904             : 
    3905           5 :         switch(level) {
    3906           3 :         case SMB2_OPLOCK_LEVEL_II:
    3907           3 :                 name = "level II";
    3908           3 :                 break;
    3909           2 :         case SMB2_OPLOCK_LEVEL_NONE:
    3910           2 :                 name = "none";
    3911           2 :                 break;
    3912           0 :         default:
    3913           0 :                 name = "unknown";
    3914           0 :                 break;
    3915             :         }
    3916           5 :         printf("Got break to %s [0x%02X] in oplock handler, postponing "
    3917             :                "break response for 500msec\n", name, level);
    3918             : 
    3919           5 :         te = tevent_add_timer(
    3920             :                 state->tctx->ev, state->tctx,
    3921             :                 tevent_timeval_current_ofs(0, 500000),
    3922             :                 levelII501_break_timeout_cb, state);
    3923           5 :         torture_assert(state->tctx, te != NULL, "tevent_add_timer failed\n");
    3924             : 
    3925           5 :         return true;
    3926             : }
    3927             : 
    3928           5 : static void levelII501_break_timeout_cb(struct tevent_context *ev,
    3929             :                                         struct tevent_timer *te,
    3930             :                                         struct timeval current_time,
    3931             :                                         void *private_data)
    3932             : {
    3933           5 :         struct levelII501_state *state = talloc_get_type_abort(
    3934             :                 private_data, struct levelII501_state);
    3935           0 :         struct smb2_request *req;
    3936             : 
    3937           5 :         talloc_free(te);
    3938             : 
    3939           5 :         ZERO_STRUCT(state->br);
    3940           5 :         state->br.in.file.handle = state->break_handle;
    3941           5 :         state->br.in.oplock_level = state->break_to;
    3942             : 
    3943           5 :         req = smb2_break_send(state->tree1, &state->br);
    3944           5 :         req->async.fn = levelII501_break_done;
    3945           5 :         req->async.private_data = state;
    3946           5 : }
    3947             : 
    3948           5 : static void levelII501_break_done(struct smb2_request *req)
    3949             : {
    3950           0 :         struct smb2_break io;
    3951           0 :         NTSTATUS status;
    3952             : 
    3953           5 :         status = smb2_break_recv(req, &io);
    3954           5 :         printf("break done: %s\n", nt_errstr(status));
    3955           5 : }
    3956             : 
    3957           3 : static void levelII501_open1_done(struct smb2_request *req)
    3958             : {
    3959           3 :         struct levelII501_state *state = talloc_get_type_abort(
    3960             :                 req->async.private_data, struct levelII501_state);
    3961           0 :         struct smb2_create io;
    3962           0 :         NTSTATUS status;
    3963             : 
    3964           3 :         status = smb2_create_recv(req, state, &io);
    3965           3 :         printf("open1 done: %s\n", nt_errstr(status));
    3966           3 : }
    3967             : 
    3968           3 : static void levelII501_open2_done(struct smb2_request *req)
    3969             : {
    3970           3 :         struct levelII501_state *state = talloc_get_type_abort(
    3971             :                 req->async.private_data, struct levelII501_state);
    3972           0 :         struct smb2_create io;
    3973           0 :         NTSTATUS status;
    3974             : 
    3975           3 :         status = smb2_create_recv(req, state, &io);
    3976           3 :         printf("open2 done: %s\n", nt_errstr(status));
    3977           3 : }
    3978             : 
    3979           3 : static void levelII501_timeout_cb(struct tevent_context *ev,
    3980             :                                   struct tevent_timer *te,
    3981             :                                   struct timeval current_time,
    3982             :                                   void *private_data)
    3983             : {
    3984           3 :         struct levelII501_state *state = talloc_get_type_abort(
    3985             :                 private_data, struct levelII501_state);
    3986           3 :         talloc_free(te);
    3987           3 :         state->done = true;
    3988           3 : }
    3989             : 
    3990           3 : static bool test_smb2_oplock_levelII502(struct torture_context *tctx,
    3991             :                                         struct smb2_tree *tree1,
    3992             :                                         struct smb2_tree *tree2)
    3993             : 
    3994             : {
    3995           3 :         const char *fname = BASEDIR "\\test_levelII502.dat";
    3996           0 :         NTSTATUS status;
    3997           0 :         union smb_open io;
    3998           0 :         struct smb2_close closeio;
    3999           0 :         struct smb2_handle h;
    4000             : 
    4001           3 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    4002           3 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    4003             : 
    4004             :         /* cleanup */
    4005           3 :         smb2_util_unlink(tree1, fname);
    4006             : 
    4007             :         /*
    4008             :           base ntcreatex parms
    4009             :         */
    4010           3 :         ZERO_STRUCT(io.smb2);
    4011           3 :         io.generic.level = RAW_OPEN_SMB2;
    4012           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4013           3 :         io.smb2.in.alloc_size = 0;
    4014           3 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4015           3 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4016           3 :         io.smb2.in.create_options = 0;
    4017           3 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4018           3 :         io.smb2.in.security_flags = 0;
    4019           3 :         io.smb2.in.fname = fname;
    4020             : 
    4021           3 :         torture_comment(
    4022             :                 tctx,
    4023             :                 "LEVELII502: Open a stale LEVEL2 oplock with OVERWRITE");
    4024             : 
    4025           3 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    4026             :                                 SEC_RIGHTS_FILE_WRITE;
    4027           3 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    4028             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    4029           3 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    4030           3 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
    4031           3 :         status = smb2_create(tree1, tctx, &(io.smb2));
    4032           3 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    4033           3 :         torture_assert(tctx,
    4034             :                        io.smb2.out.oplock_level==SMB2_OPLOCK_LEVEL_II,
    4035             :                        "Did not get LEVEL_II oplock\n");
    4036             : 
    4037           2 :         status = smbXcli_conn_samba_suicide(
    4038           2 :                 tree1->session->transport->conn, 93);
    4039           2 :         torture_assert_ntstatus_ok(tctx, status, "suicide failed");
    4040             : 
    4041           2 :         sleep(1);
    4042             : 
    4043           2 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    4044           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
    4045             : 
    4046           2 :         status = smb2_create(tree2, tctx, &(io.smb2));
    4047           2 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    4048           2 :         torture_assert(tctx,
    4049             :                        io.smb2.out.oplock_level==SMB2_OPLOCK_LEVEL_BATCH,
    4050             :                        "Did not get BATCH oplock\n");
    4051             : 
    4052           2 :         closeio = (struct smb2_close) {
    4053             :                 .in.file.handle = io.smb2.out.file.handle,
    4054             :         };
    4055           2 :         status = smb2_close(tree2, &closeio);
    4056           2 :         torture_assert_ntstatus_equal(
    4057             :                 tctx, status, NT_STATUS_OK, "close failed");
    4058             : 
    4059           2 :         return true;
    4060             : }
    4061             : 
    4062          36 : static bool test_oplock_statopen1_do(struct torture_context *tctx,
    4063             :                                      struct smb2_tree *tree,
    4064             :                                      uint32_t access_mask,
    4065             :                                      bool expect_stat_open)
    4066             : {
    4067          36 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    4068           0 :         struct smb2_create cr;
    4069          36 :         struct smb2_handle h1 = {{0}};
    4070          36 :         struct smb2_handle h2 = {{0}};
    4071           0 :         NTSTATUS status;
    4072          36 :         const char *fname = "oplock_statopen1.dat";
    4073          36 :         bool ret = true;
    4074             : 
    4075             :         /* Open file with exclusive oplock. */
    4076          36 :         cr = (struct smb2_create) {
    4077             :                 .in.desired_access = SEC_FILE_ALL,
    4078             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    4079             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    4080             :                 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
    4081             :                 .in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION,
    4082             :                 .in.fname = fname,
    4083             :                 .in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH,
    4084             :         };
    4085          36 :         status = smb2_create(tree, mem_ctx, &cr);
    4086          36 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4087             :                                         "smb2_create failed\n");
    4088          36 :         h1 = cr.out.file.handle;
    4089          36 :         CHECK_VAL(cr.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    4090             : 
    4091             :         /* Stat open */
    4092          36 :         cr = (struct smb2_create) {
    4093             :                 .in.desired_access = access_mask,
    4094             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    4095             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    4096             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    4097             :                 .in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION,
    4098             :                 .in.fname = fname,
    4099             :         };
    4100          36 :         status = smb2_create(tree, mem_ctx, &cr);
    4101          36 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4102             :                                         "smb2_create failed\n");
    4103          35 :         h2 = cr.out.file.handle;
    4104             : 
    4105          35 :         if (expect_stat_open) {
    4106           8 :                 torture_wait_for_oplock_break(tctx);
    4107           8 :                 CHECK_VAL(break_info.count, 0);
    4108           8 :                 CHECK_VAL(break_info.level, 0);
    4109           8 :                 CHECK_VAL(break_info.failures, 0);
    4110           8 :                 if (!ret) {
    4111           0 :                         goto done;
    4112             :                 }
    4113             :         } else {
    4114          27 :                 CHECK_VAL(break_info.count, 1);
    4115             :         }
    4116             : 
    4117          27 : done:
    4118          36 :         if (!smb2_util_handle_empty(h2)) {
    4119          35 :                 smb2_util_close(tree, h2);
    4120             :         }
    4121          36 :         if (!smb2_util_handle_empty(h1)) {
    4122          36 :                 smb2_util_close(tree, h1);
    4123             :         }
    4124          36 :         talloc_free(mem_ctx);
    4125          36 :         return ret;
    4126             : }
    4127             : 
    4128           3 : static bool test_smb2_oplock_statopen1(struct torture_context *tctx,
    4129             :                                        struct smb2_tree *tree)
    4130             : {
    4131           3 :         const char *fname = "oplock_statopen1.dat";
    4132           0 :         size_t i;
    4133           3 :         bool ret = true;
    4134           0 :         struct {
    4135             :                 uint32_t access_mask;
    4136             :                 bool expect_stat_open;
    4137           3 :         } tests[] = {
    4138             :                 {
    4139             :                         .access_mask = FILE_READ_DATA,
    4140             :                         .expect_stat_open = false,
    4141             :                 },
    4142             :                 {
    4143             :                         .access_mask = FILE_WRITE_DATA,
    4144             :                         .expect_stat_open = false,
    4145             :                 },
    4146             :                 {
    4147             :                         .access_mask = FILE_READ_EA,
    4148             :                         .expect_stat_open = false,
    4149             :                 },
    4150             :                 {
    4151             :                         .access_mask = FILE_WRITE_EA,
    4152             :                         .expect_stat_open = false,
    4153             :                 },
    4154             :                 {
    4155             :                         .access_mask = FILE_EXECUTE,
    4156             :                         .expect_stat_open = false,
    4157             :                 },
    4158             :                 {
    4159             :                         .access_mask = FILE_READ_ATTRIBUTES,
    4160             :                         .expect_stat_open = true,
    4161             :                 },
    4162             :                 {
    4163             :                         .access_mask = FILE_WRITE_ATTRIBUTES,
    4164             :                         .expect_stat_open = true,
    4165             :                 },
    4166             :                 {
    4167             :                         .access_mask = DELETE_ACCESS,
    4168             :                         .expect_stat_open = false,
    4169             :                 },
    4170             :                 {
    4171             :                         .access_mask = READ_CONTROL_ACCESS,
    4172             :                         .expect_stat_open = false,
    4173             :                 },
    4174             :                 {
    4175             :                         .access_mask = WRITE_DAC_ACCESS,
    4176             :                         .expect_stat_open = false,
    4177             :                 },
    4178             :                 {
    4179             :                         .access_mask = WRITE_OWNER_ACCESS,
    4180             :                         .expect_stat_open = false,
    4181             :                 },
    4182             :                 {
    4183             :                         .access_mask = SYNCHRONIZE_ACCESS,
    4184             :                         .expect_stat_open = true,
    4185             :                 },
    4186             :         };
    4187             : 
    4188           3 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4189           3 :         tree->session->transport->oplock.private_data = tree;
    4190             : 
    4191          38 :         for (i = 0; i < ARRAY_SIZE(tests); i++) {
    4192          36 :                 ZERO_STRUCT(break_info);
    4193             : 
    4194          36 :                 ret = test_oplock_statopen1_do(tctx,
    4195             :                                                tree,
    4196             :                                                tests[i].access_mask,
    4197          36 :                                                tests[i].expect_stat_open);
    4198          36 :                 if (ret == true) {
    4199          35 :                         continue;
    4200             :                 }
    4201           1 :                 torture_result(tctx, TORTURE_FAIL,
    4202             :                                "test %zu: access_mask: %s, "
    4203             :                                "expect_stat_open: %s\n",
    4204             :                                i,
    4205             :                                get_sec_mask_str(tree, tests[i].access_mask),
    4206           1 :                                tests[i].expect_stat_open ? "yes" : "no");
    4207           1 :                 goto done;
    4208             :         }
    4209             : 
    4210           2 : done:
    4211           3 :         smb2_util_unlink(tree, fname);
    4212           3 :         return ret;
    4213             : }
    4214             : 
    4215        2379 : struct torture_suite *torture_smb2_oplocks_init(TALLOC_CTX *ctx)
    4216             : {
    4217         125 :         struct torture_suite *suite =
    4218        2379 :             torture_suite_create(ctx, "oplock");
    4219             : 
    4220        2379 :         torture_suite_add_2smb2_test(suite, "exclusive1", test_smb2_oplock_exclusive1);
    4221        2379 :         torture_suite_add_2smb2_test(suite, "exclusive2", test_smb2_oplock_exclusive2);
    4222        2379 :         torture_suite_add_2smb2_test(suite, "exclusive3", test_smb2_oplock_exclusive3);
    4223        2379 :         torture_suite_add_2smb2_test(suite, "exclusive4", test_smb2_oplock_exclusive4);
    4224        2379 :         torture_suite_add_2smb2_test(suite, "exclusive5", test_smb2_oplock_exclusive5);
    4225        2379 :         torture_suite_add_2smb2_test(suite, "exclusive6", test_smb2_oplock_exclusive6);
    4226        2379 :         torture_suite_add_2smb2_test(suite, "exclusive9",
    4227             :                                      test_smb2_oplock_exclusive9);
    4228        2379 :         torture_suite_add_2smb2_test(suite, "batch1", test_smb2_oplock_batch1);
    4229        2379 :         torture_suite_add_2smb2_test(suite, "batch2", test_smb2_oplock_batch2);
    4230        2379 :         torture_suite_add_2smb2_test(suite, "batch3", test_smb2_oplock_batch3);
    4231        2379 :         torture_suite_add_2smb2_test(suite, "batch4", test_smb2_oplock_batch4);
    4232        2379 :         torture_suite_add_2smb2_test(suite, "batch5", test_smb2_oplock_batch5);
    4233        2379 :         torture_suite_add_2smb2_test(suite, "batch6", test_smb2_oplock_batch6);
    4234        2379 :         torture_suite_add_2smb2_test(suite, "batch7", test_smb2_oplock_batch7);
    4235        2379 :         torture_suite_add_2smb2_test(suite, "batch8", test_smb2_oplock_batch8);
    4236        2379 :         torture_suite_add_2smb2_test(suite, "batch9", test_smb2_oplock_batch9);
    4237        2379 :         torture_suite_add_2smb2_test(suite, "batch9a", test_smb2_oplock_batch9a);
    4238        2379 :         torture_suite_add_2smb2_test(suite, "batch10", test_smb2_oplock_batch10);
    4239        2379 :         torture_suite_add_2smb2_test(suite, "batch11", test_smb2_oplock_batch11);
    4240        2379 :         torture_suite_add_2smb2_test(suite, "batch12", test_smb2_oplock_batch12);
    4241        2379 :         torture_suite_add_2smb2_test(suite, "batch13", test_smb2_oplock_batch13);
    4242        2379 :         torture_suite_add_2smb2_test(suite, "batch14", test_smb2_oplock_batch14);
    4243        2379 :         torture_suite_add_2smb2_test(suite, "batch15", test_smb2_oplock_batch15);
    4244        2379 :         torture_suite_add_2smb2_test(suite, "batch16", test_smb2_oplock_batch16);
    4245        2379 :         torture_suite_add_1smb2_test(suite, "batch19", test_smb2_oplock_batch19);
    4246        2379 :         torture_suite_add_2smb2_test(suite, "batch20", test_smb2_oplock_batch20);
    4247        2379 :         torture_suite_add_1smb2_test(suite, "batch21", test_smb2_oplock_batch21);
    4248        2379 :         torture_suite_add_1smb2_test(suite, "batch22a", test_smb2_oplock_batch22a);
    4249        2379 :         torture_suite_add_2smb2_test(suite, "batch22b", test_smb2_oplock_batch22b);
    4250        2379 :         torture_suite_add_2smb2_test(suite, "batch23", test_smb2_oplock_batch23);
    4251        2379 :         torture_suite_add_2smb2_test(suite, "batch24", test_smb2_oplock_batch24);
    4252        2379 :         torture_suite_add_1smb2_test(suite, "batch25", test_smb2_oplock_batch25);
    4253        2379 :         torture_suite_add_1smb2_test(suite, "batch26", test_smb2_oplock_batch26);
    4254        2379 :         torture_suite_add_2smb2_test(suite, "stream1", test_raw_oplock_stream1);
    4255        2379 :         torture_suite_add_2smb2_test(suite, "doc", test_smb2_oplock_doc);
    4256        2379 :         torture_suite_add_2smb2_test(suite, "brl1", test_smb2_oplock_brl1);
    4257        2379 :         torture_suite_add_1smb2_test(suite, "brl2", test_smb2_oplock_brl2);
    4258        2379 :         torture_suite_add_1smb2_test(suite, "brl3", test_smb2_oplock_brl3);
    4259        2379 :         torture_suite_add_1smb2_test(suite, "levelii500", test_smb2_oplock_levelII500);
    4260        2379 :         torture_suite_add_2smb2_test(suite, "levelii501",
    4261             :                                      test_smb2_oplock_levelII501);
    4262        2379 :         torture_suite_add_2smb2_test(suite, "levelii502",
    4263             :                                      test_smb2_oplock_levelII502);
    4264        2379 :         torture_suite_add_1smb2_test(suite, "statopen1", test_smb2_oplock_statopen1);
    4265        2379 :         suite->description = talloc_strdup(suite, "SMB2-OPLOCK tests");
    4266             : 
    4267        2379 :         return suite;
    4268             : }
    4269             : 
    4270             : /*
    4271             :    stress testing of oplocks
    4272             : */
    4273           0 : bool test_smb2_bench_oplock(struct torture_context *tctx,
    4274             :                                    struct smb2_tree *tree)
    4275             : {
    4276           0 :         struct smb2_tree **trees;
    4277           0 :         bool ret = true;
    4278           0 :         NTSTATUS status;
    4279           0 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    4280           0 :         int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
    4281           0 :         int i, count=0;
    4282           0 :         int timelimit = torture_setting_int(tctx, "timelimit", 10);
    4283           0 :         union smb_open io;
    4284           0 :         struct timeval tv;
    4285           0 :         struct smb2_handle h;
    4286             : 
    4287           0 :         trees = talloc_array(mem_ctx, struct smb2_tree *, torture_nprocs);
    4288             : 
    4289           0 :         torture_comment(tctx, "Opening %d connections\n", torture_nprocs);
    4290           0 :         for (i=0;i<torture_nprocs;i++) {
    4291           0 :                 if (!torture_smb2_connection(tctx, &trees[i])) {
    4292           0 :                         return false;
    4293             :                 }
    4294           0 :                 talloc_steal(mem_ctx, trees[i]);
    4295           0 :                 trees[i]->session->transport->oplock.handler =
    4296             :                                         torture_oplock_handler_close;
    4297           0 :                 trees[i]->session->transport->oplock.private_data = trees[i];
    4298             :         }
    4299             : 
    4300           0 :         status = torture_smb2_testdir(trees[0], BASEDIR, &h);
    4301           0 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    4302             : 
    4303           0 :         ZERO_STRUCT(io.smb2);
    4304           0 :         io.smb2.level = RAW_OPEN_SMB2;
    4305           0 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4306           0 :         io.smb2.in.alloc_size = 0;
    4307           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4308           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    4309           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4310           0 :         io.smb2.in.create_options = 0;
    4311           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4312           0 :         io.smb2.in.security_flags = 0;
    4313           0 :         io.smb2.in.fname = BASEDIR "\\test.dat";
    4314           0 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    4315           0 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    4316             : 
    4317           0 :         tv = timeval_current();
    4318             : 
    4319             :         /*
    4320             :           we open the same file with SHARE_ACCESS_NONE from all the
    4321             :           connections in a round robin fashion. Each open causes an
    4322             :           oplock break on the previous connection, which is answered
    4323             :           by the oplock_handler_close() to close the file.
    4324             : 
    4325             :           This measures how fast we can pass on oplocks, and stresses
    4326             :           the oplock handling code
    4327             :         */
    4328           0 :         torture_comment(tctx, "Running for %d seconds\n", timelimit);
    4329           0 :         while (timeval_elapsed(&tv) < timelimit) {
    4330           0 :                 for (i=0;i<torture_nprocs;i++) {
    4331           0 :                         status = smb2_create(trees[i], mem_ctx, &(io.smb2));
    4332           0 :                         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    4333           0 :                         count++;
    4334             :                 }
    4335             : 
    4336           0 :                 if (torture_setting_bool(tctx, "progress", true)) {
    4337           0 :                         torture_comment(tctx, "%.2f ops/second\r",
    4338           0 :                                         count/timeval_elapsed(&tv));
    4339             :                 }
    4340             :         }
    4341             : 
    4342           0 :         torture_comment(tctx, "%.2f ops/second\n", count/timeval_elapsed(&tv));
    4343           0 :         smb2_util_close(trees[0], io.smb2.out.file.handle);
    4344           0 :         smb2_util_unlink(trees[0], BASEDIR "\\test.dat");
    4345           0 :         smb2_deltree(trees[0], BASEDIR);
    4346           0 :         talloc_free(mem_ctx);
    4347           0 :         return ret;
    4348             : }
    4349             : 
    4350             : static struct hold_oplock_info {
    4351             :         const char *fname;
    4352             :         bool close_on_break;
    4353             :         uint32_t share_access;
    4354             :         struct smb2_handle handle;
    4355             : } hold_info[] = {
    4356             :         {
    4357             :                 .fname          = BASEDIR "\\notshared_close",
    4358             :                 .close_on_break = true,
    4359             :                 .share_access   = NTCREATEX_SHARE_ACCESS_NONE,
    4360             :         },
    4361             :         {
    4362             :                 .fname          = BASEDIR "\\notshared_noclose",
    4363             :                 .close_on_break = false,
    4364             :                 .share_access   = NTCREATEX_SHARE_ACCESS_NONE,
    4365             :         },
    4366             :         {
    4367             :                 .fname          = BASEDIR "\\shared_close",
    4368             :                 .close_on_break = true,
    4369             :                 .share_access   = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
    4370             :         },
    4371             :         {
    4372             :                 .fname          = BASEDIR "\\shared_noclose",
    4373             :                 .close_on_break = false,
    4374             :                 .share_access   = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
    4375             :         },
    4376             : };
    4377             : 
    4378           0 : static bool torture_oplock_handler_hold(struct smb2_transport *transport,
    4379             :                                         const struct smb2_handle *handle,
    4380             :                                         uint8_t level, void *private_data)
    4381             : {
    4382           0 :         struct hold_oplock_info *info;
    4383           0 :         int i;
    4384             : 
    4385           0 :         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
    4386           0 :                 if (smb2_util_handle_equal(hold_info[i].handle, *handle))
    4387           0 :                         break;
    4388             :         }
    4389             : 
    4390           0 :         if (i == ARRAY_SIZE(hold_info)) {
    4391           0 :                 printf("oplock break for unknown handle 0x%llx%llx\n",
    4392           0 :                        (unsigned long long) handle->data[0],
    4393           0 :                        (unsigned long long) handle->data[1]);
    4394           0 :                 return false;
    4395             :         }
    4396             : 
    4397           0 :         info = &hold_info[i];
    4398             : 
    4399           0 :         if (info->close_on_break) {
    4400           0 :                 printf("oplock break on %s - closing\n", info->fname);
    4401           0 :                 torture_oplock_handler_close(transport, handle,
    4402             :                                              level, private_data);
    4403           0 :                 return true;
    4404             :         }
    4405             : 
    4406           0 :         printf("oplock break on %s - acking break\n", info->fname);
    4407           0 :         printf("Acking to none in oplock handler\n");
    4408             : 
    4409           0 :         torture_oplock_handler_ack_to_none(transport, handle,
    4410             :                                            level, private_data);
    4411           0 :         return true;
    4412             : }
    4413             : 
    4414             : /*
    4415             :    used for manual testing of oplocks - especially interaction with
    4416             :    other filesystems (such as NFS and local access)
    4417             : */
    4418           0 : bool test_smb2_hold_oplock(struct torture_context *tctx,
    4419             :                            struct smb2_tree *tree)
    4420             : {
    4421           0 :         struct torture_context *mem_ctx = talloc_new(tctx);
    4422           0 :         struct tevent_context *ev = tctx->ev;
    4423           0 :         int i;
    4424           0 :         struct smb2_handle h;
    4425           0 :         NTSTATUS status;
    4426             : 
    4427           0 :         torture_comment(tctx, "Setting up open files with oplocks in %s\n",
    4428             :                         BASEDIR);
    4429             : 
    4430           0 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    4431           0 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    4432             : 
    4433           0 :         tree->session->transport->oplock.handler = torture_oplock_handler_hold;
    4434           0 :         tree->session->transport->oplock.private_data = tree;
    4435             : 
    4436             :         /* setup the files */
    4437           0 :         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
    4438           0 :                 union smb_open io;
    4439           0 :                 char c = 1;
    4440             : 
    4441           0 :                 ZERO_STRUCT(io.smb2);
    4442           0 :                 io.generic.level = RAW_OPEN_SMB2;
    4443           0 :                 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4444           0 :                 io.smb2.in.alloc_size = 0;
    4445           0 :                 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4446           0 :                 io.smb2.in.share_access = hold_info[i].share_access;
    4447           0 :                 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4448           0 :                 io.smb2.in.create_options = 0;
    4449           0 :                 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4450           0 :                 io.smb2.in.security_flags = 0;
    4451           0 :                 io.smb2.in.fname = hold_info[i].fname;
    4452           0 :                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    4453           0 :                 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    4454             : 
    4455           0 :                 torture_comment(tctx, "opening %s\n", hold_info[i].fname);
    4456             : 
    4457           0 :                 status = smb2_create(tree, mem_ctx, &(io.smb2));
    4458           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4459           0 :                         torture_comment(tctx, "Failed to open %s - %s\n",
    4460             :                                hold_info[i].fname, nt_errstr(status));
    4461           0 :                         return false;
    4462             :                 }
    4463             : 
    4464           0 :                 if (io.smb2.out.oplock_level != SMB2_OPLOCK_LEVEL_BATCH) {
    4465           0 :                         torture_comment(tctx, "Oplock not granted for %s - "
    4466             :                                         "expected %d but got %d\n",
    4467             :                                         hold_info[i].fname,
    4468             :                                         SMB2_OPLOCK_LEVEL_BATCH,
    4469           0 :                                         io.smb2.out.oplock_level);
    4470           0 :                         return false;
    4471             :                 }
    4472           0 :                 hold_info[i].handle = io.smb2.out.file.handle;
    4473             : 
    4474             :                 /* make the file non-zero size */
    4475           0 :                 status = smb2_util_write(tree, hold_info[i].handle, &c, 0, 1);
    4476           0 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
    4477           0 :                         torture_comment(tctx, "Failed to write to file\n");
    4478           0 :                         return false;
    4479             :                 }
    4480             :         }
    4481             : 
    4482           0 :         torture_comment(tctx, "Waiting for oplock events\n");
    4483           0 :         tevent_loop_wait(ev);
    4484           0 :         smb2_deltree(tree, BASEDIR);
    4485           0 :         talloc_free(mem_ctx);
    4486           0 :         return true;
    4487             : }
    4488             : 
    4489             : 
    4490           1 : static bool test_smb2_kernel_oplocks1(struct torture_context *tctx,
    4491             :                                       struct smb2_tree *tree)
    4492             : {
    4493           1 :         const char *fname = "test_kernel_oplock1.dat";
    4494           0 :         NTSTATUS status;
    4495           1 :         bool ret = true;
    4496           0 :         struct smb2_create create;
    4497           1 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4498             : 
    4499           1 :         smb2_util_unlink(tree, fname);
    4500             : 
    4501           1 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4502           1 :         tree->session->transport->oplock.private_data = tree;
    4503           1 :         ZERO_STRUCT(break_info);
    4504             : 
    4505           1 :         ZERO_STRUCT(create);
    4506           1 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4507           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4508           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    4509           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4510           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4511           1 :         create.in.fname = fname;
    4512           1 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    4513             : 
    4514           1 :         status = smb2_create(tree, tctx, &create);
    4515           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4516           1 :         h1 = create.out.file.handle;
    4517             : 
    4518           1 :         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done,
    4519             :                             "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n");
    4520             : 
    4521           1 :         ZERO_STRUCT(create);
    4522           1 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4523           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4524           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4525           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4526           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4527           1 :         create.in.fname = fname;
    4528             : 
    4529           1 :         status = smb2_create(tree, tctx, &create);
    4530           1 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done,
    4531             :                                            "Open didn't return NT_STATUS_SHARING_VIOLATION\n");
    4532           1 :         h2 = create.out.file.handle;
    4533             : 
    4534           1 :         torture_wait_for_oplock_break(tctx);
    4535           1 :         if (break_info.count != 0) {
    4536           1 :                 torture_warning(tctx, "Open caused oplock break\n");
    4537             :         }
    4538             : 
    4539           1 :         smb2_util_close(tree, h1);
    4540           1 :         smb2_util_close(tree, h2);
    4541             : 
    4542           1 : done:
    4543           1 :         if (!smb2_util_handle_empty(h1)) {
    4544           1 :                 smb2_util_close(tree, h1);
    4545             :         }
    4546           1 :         if (!smb2_util_handle_empty(h2)) {
    4547           0 :                 smb2_util_close(tree, h2);
    4548             :         }
    4549           1 :         smb2_util_unlink(tree, fname);
    4550           1 :         return ret;
    4551             : }
    4552             : 
    4553           1 : static bool test_smb2_kernel_oplocks2(struct torture_context *tctx,
    4554             :                                       struct smb2_tree *tree)
    4555             : {
    4556           1 :         const char *fname = "test_kernel_oplock2.dat";
    4557           1 :         const char *sname = "test_kernel_oplock2.dat:foo";
    4558           0 :         NTSTATUS status;
    4559           1 :         bool ret = true;
    4560           0 :         struct smb2_create create;
    4561           1 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4562             : 
    4563           1 :         smb2_util_unlink(tree, fname);
    4564             : 
    4565           1 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4566           1 :         tree->session->transport->oplock.private_data = tree;
    4567           1 :         ZERO_STRUCT(break_info);
    4568             : 
    4569           1 :         ZERO_STRUCT(create);
    4570           1 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4571           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4572           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    4573           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4574           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4575           1 :         create.in.fname = fname;
    4576           1 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    4577             : 
    4578           1 :         status = smb2_create(tree, tctx, &create);
    4579           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4580           1 :         h1 = create.out.file.handle;
    4581             : 
    4582           1 :         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done,
    4583             :                             "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n");
    4584             : 
    4585           1 :         ZERO_STRUCT(create);
    4586           1 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4587           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4588           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4589           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4590           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4591           1 :         create.in.fname = sname;
    4592             : 
    4593           1 :         status = smb2_create(tree, tctx, &create);
    4594           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4595           1 :         h2 = create.out.file.handle;
    4596             : 
    4597           1 :         torture_wait_for_oplock_break(tctx);
    4598           1 :         if (break_info.count != 0) {
    4599           0 :                 torture_warning(tctx, "Stream open caused oplock break\n");
    4600             :         }
    4601             : 
    4602           1 :         smb2_util_close(tree, h1);
    4603           1 :         smb2_util_close(tree, h2);
    4604             : 
    4605           1 : done:
    4606           1 :         if (!smb2_util_handle_empty(h1)) {
    4607           1 :                 smb2_util_close(tree, h1);
    4608             :         }
    4609           1 :         if (!smb2_util_handle_empty(h2)) {
    4610           1 :                 smb2_util_close(tree, h2);
    4611             :         }
    4612           1 :         smb2_util_unlink(tree, fname);
    4613           1 :         return ret;
    4614             : }
    4615             : 
    4616             : /**
    4617             :  * 1. 1st client opens file with oplock
    4618             :  * 2. 2nd client opens file
    4619             :  *
    4620             :  * Verify 2 triggers an oplock break
    4621             :  **/
    4622           1 : static bool test_smb2_kernel_oplocks3(struct torture_context *tctx,
    4623             :                                       struct smb2_tree *tree,
    4624             :                                       struct smb2_tree *tree2)
    4625             : {
    4626           1 :         const char *fname = "test_kernel_oplock3.dat";
    4627           0 :         NTSTATUS status;
    4628           1 :         bool ret = true;
    4629           0 :         struct smb2_create create;
    4630           1 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4631             : 
    4632           1 :         smb2_util_unlink(tree, fname);
    4633           1 :         status = torture_smb2_testfile(tree, fname, &h1);
    4634           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4635             :                                         "Error creating testfile\n");
    4636           1 :         smb2_util_close(tree, h1);
    4637           1 :         ZERO_STRUCT(h1);
    4638             : 
    4639           1 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4640           1 :         tree->session->transport->oplock.private_data = tree;
    4641           1 :         ZERO_STRUCT(break_info);
    4642             : 
    4643             :         /* 1 */
    4644           1 :         ZERO_STRUCT(create);
    4645           1 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4646           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4647           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4648           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4649           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4650           1 :         create.in.fname = fname;
    4651           1 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    4652             : 
    4653           1 :         status = smb2_create(tree, tctx, &create);
    4654           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4655           1 :         h1 = create.out.file.handle;
    4656             : 
    4657           1 :         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done,
    4658             :                             "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n");
    4659             : 
    4660             :         /* 2 */
    4661           1 :         ZERO_STRUCT(create);
    4662           1 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4663           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4664           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4665           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    4666           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4667           1 :         create.in.fname = fname;
    4668             : 
    4669           1 :         status = smb2_create(tree2, tctx, &create);
    4670           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4671           1 :         h2 = create.out.file.handle;
    4672             : 
    4673           1 :         torture_wait_for_oplock_break(tctx);
    4674           1 :         torture_assert_goto(tctx, break_info.count == 1, ret, done, "Expected 1 oplock break\n");
    4675             : 
    4676           1 : done:
    4677           1 :         if (!smb2_util_handle_empty(h1)) {
    4678           1 :                 smb2_util_close(tree, h1);
    4679             :         }
    4680           1 :         if (!smb2_util_handle_empty(h2)) {
    4681           1 :                 smb2_util_close(tree, h2);
    4682             :         }
    4683           1 :         smb2_util_unlink(tree, fname);
    4684           1 :         return ret;
    4685             : }
    4686             : 
    4687             : /**
    4688             :  * 1) create testfile with stream
    4689             :  * 2) open file r/w with batch oplock, sharing read/delete
    4690             :  * 3) open stream on file for reading
    4691             :  *
    4692             :  * Verify 3) doesn't trigger an oplock break
    4693             :  **/
    4694           1 : static bool test_smb2_kernel_oplocks4(struct torture_context *tctx,
    4695             :                                       struct smb2_tree *tree)
    4696             : {
    4697           1 :         const char *fname = "test_kernel_oplock4.dat";
    4698           1 :         const char *sname = "test_kernel_oplock4.dat:foo";
    4699           0 :         NTSTATUS status;
    4700           1 :         bool ret = true;
    4701           0 :         struct smb2_create create;
    4702           1 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4703             : 
    4704           1 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4705           1 :         tree->session->transport->oplock.private_data = tree;
    4706           1 :         ZERO_STRUCT(break_info);
    4707           1 :         smb2_util_unlink(tree, fname);
    4708             : 
    4709             :         /* 1 */
    4710           1 :         status = torture_smb2_testfile(tree, fname, &h1);
    4711           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4712             :                                         "Error creating testfile\n");
    4713           1 :         smb2_util_close(tree, h1);
    4714           1 :         ZERO_STRUCT(h1);
    4715             : 
    4716           1 :         ZERO_STRUCT(create);
    4717           1 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4718           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4719           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4720           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4721           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4722           1 :         create.in.fname = sname;
    4723             : 
    4724           1 :         status = smb2_create(tree, tctx, &create);
    4725           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4726           1 :         h1 = create.out.file.handle;
    4727           1 :         smb2_util_close(tree, h1);
    4728           1 :         ZERO_STRUCT(h1);
    4729             : 
    4730             :         /* 2 */
    4731           1 :         ZERO_STRUCT(create);
    4732           1 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4733           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4734           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
    4735           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    4736           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4737           1 :         create.in.fname = fname;
    4738           1 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    4739             : 
    4740           1 :         status = smb2_create(tree, tctx, &create);
    4741           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4742           1 :         h1 = create.out.file.handle;
    4743             : 
    4744           1 :         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_BATCH, ret, done,
    4745             :                             "Oplock level is not SMB2_OPLOCK_LEVEL_BATCH\n");
    4746             : 
    4747           1 :         ZERO_STRUCT(create);
    4748           1 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4749           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4750           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
    4751           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    4752           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4753           1 :         create.in.fname = sname;
    4754             : 
    4755           1 :         status = smb2_create(tree, tctx, &create);
    4756           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4757           1 :         h2 = create.out.file.handle;
    4758             : 
    4759           1 :         torture_wait_for_oplock_break(tctx);
    4760           1 :         if (break_info.count != 0) {
    4761           0 :                 torture_warning(tctx, "Stream open caused oplock break\n");
    4762             :         }
    4763             : 
    4764           1 : done:
    4765           1 :         if (!smb2_util_handle_empty(h1)) {
    4766           1 :                 smb2_util_close(tree, h1);
    4767             :         }
    4768           1 :         if (!smb2_util_handle_empty(h2)) {
    4769           1 :                 smb2_util_close(tree, h2);
    4770             :         }
    4771           1 :         smb2_util_unlink(tree, fname);
    4772           1 :         return ret;
    4773             : }
    4774             : 
    4775             : /**
    4776             :  * 1) create testfile with stream
    4777             :  * 2) open stream r/w with batch oplock -> batch oplock granted
    4778             :  * 3) open stream r/o with batch oplock
    4779             :  *
    4780             :  * Verify 3) does trigger an oplock break
    4781             :  **/
    4782           1 : static bool test_smb2_kernel_oplocks5(struct torture_context *tctx,
    4783             :                                       struct smb2_tree *tree)
    4784             : {
    4785           1 :         const char *fname = "test_kernel_oplock4.dat";
    4786           1 :         const char *sname = "test_kernel_oplock4.dat:foo";
    4787           0 :         NTSTATUS status;
    4788           1 :         bool ret = true;
    4789           0 :         struct smb2_create create;
    4790           1 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4791             : 
    4792           1 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4793           1 :         tree->session->transport->oplock.private_data = tree;
    4794           1 :         ZERO_STRUCT(break_info);
    4795           1 :         smb2_util_unlink(tree, fname);
    4796             : 
    4797             :         /* 1 */
    4798           1 :         status = torture_smb2_testfile(tree, fname, &h1);
    4799           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4800             :                                         "Error creating testfile\n");
    4801           1 :         smb2_util_close(tree, h1);
    4802           1 :         ZERO_STRUCT(h1);
    4803             : 
    4804           1 :         ZERO_STRUCT(create);
    4805           1 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4806           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4807           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4808           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4809           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4810           1 :         create.in.fname = sname;
    4811             : 
    4812           1 :         status = smb2_create(tree, tctx, &create);
    4813           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4814           1 :         h1 = create.out.file.handle;
    4815           1 :         smb2_util_close(tree, h1);
    4816           1 :         ZERO_STRUCT(h1);
    4817             : 
    4818             :         /* 2 */
    4819           1 :         ZERO_STRUCT(create);
    4820           1 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4821           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4822           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4823           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    4824           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4825           1 :         create.in.fname = sname;
    4826           1 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    4827             : 
    4828           1 :         status = smb2_create(tree, tctx, &create);
    4829           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4830           1 :         h1 = create.out.file.handle;
    4831             : 
    4832           1 :         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_BATCH, ret, done,
    4833             :                             "Oplock level is not SMB2_OPLOCK_LEVEL_BATCH\n");
    4834             : 
    4835           1 :         ZERO_STRUCT(create);
    4836           1 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4837           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4838           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4839           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    4840           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4841           1 :         create.in.fname = sname;
    4842           1 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    4843             : 
    4844           1 :         status = smb2_create(tree, tctx, &create);
    4845           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4846           1 :         h2 = create.out.file.handle;
    4847             : 
    4848           1 :         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_NONE, ret, done,
    4849             :                             "Oplock level is not SMB2_OPLOCK_LEVEL_NONE\n");
    4850             : 
    4851           1 :         torture_wait_for_oplock_break(tctx);
    4852           1 :         if (break_info.count != 1) {
    4853           0 :                 torture_warning(tctx, "Stream open didn't cause oplock break\n");
    4854             :         }
    4855             : 
    4856           1 : done:
    4857           1 :         if (!smb2_util_handle_empty(h1)) {
    4858           1 :                 smb2_util_close(tree, h1);
    4859             :         }
    4860           1 :         if (!smb2_util_handle_empty(h2)) {
    4861           1 :                 smb2_util_close(tree, h2);
    4862             :         }
    4863           1 :         smb2_util_unlink(tree, fname);
    4864           1 :         return ret;
    4865             : }
    4866             : 
    4867             : /**
    4868             :  * 1) create testfile with stream
    4869             :  * 2) 1st client opens stream r/w with batch oplock -> batch oplock granted
    4870             :  * 3) 2nd client opens stream r/o with batch oplock
    4871             :  *
    4872             :  * Verify 3) does trigger an oplock break
    4873             :  **/
    4874           1 : static bool test_smb2_kernel_oplocks6(struct torture_context *tctx,
    4875             :                                       struct smb2_tree *tree,
    4876             :                                       struct smb2_tree *tree2)
    4877             : {
    4878           1 :         const char *fname = "test_kernel_oplock6.dat";
    4879           1 :         const char *sname = "test_kernel_oplock6.dat:foo";
    4880           0 :         NTSTATUS status;
    4881           1 :         bool ret = true;
    4882           0 :         struct smb2_create create;
    4883           1 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4884             : 
    4885           1 :         smb2_util_unlink(tree, fname);
    4886           1 :         status = torture_smb2_testfile(tree, fname, &h1);
    4887           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4888             :                                         "Error creating testfile\n");
    4889           1 :         smb2_util_close(tree, h1);
    4890           1 :         ZERO_STRUCT(h1);
    4891             : 
    4892           1 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4893           1 :         tree->session->transport->oplock.private_data = tree;
    4894           1 :         ZERO_STRUCT(break_info);
    4895             : 
    4896             :         /* 1 */
    4897           1 :         ZERO_STRUCT(create);
    4898           1 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4899           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4900           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4901           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4902           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4903           1 :         create.in.fname = sname;
    4904             : 
    4905           1 :         status = smb2_create(tree, tctx, &create);
    4906           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4907           1 :         h1 = create.out.file.handle;
    4908           1 :         smb2_util_close(tree, h1);
    4909           1 :         ZERO_STRUCT(h1);
    4910             : 
    4911             :         /* 2 */
    4912           1 :         ZERO_STRUCT(create);
    4913           1 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4914           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4915           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4916           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4917           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4918           1 :         create.in.fname = fname;
    4919           1 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    4920             : 
    4921           1 :         status = smb2_create(tree, tctx, &create);
    4922           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4923           1 :         h1 = create.out.file.handle;
    4924             : 
    4925           1 :         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done,
    4926             :                             "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n");
    4927             : 
    4928             :         /* 3 */
    4929           1 :         ZERO_STRUCT(create);
    4930           1 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4931           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4932           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4933           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    4934           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4935           1 :         create.in.fname = fname;
    4936             : 
    4937           1 :         status = smb2_create(tree2, tctx, &create);
    4938           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4939           1 :         h2 = create.out.file.handle;
    4940             : 
    4941           1 :         torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_NONE, ret, done,
    4942             :                             "Oplock level is not SMB2_OPLOCK_LEVEL_NONE\n");
    4943             : 
    4944           1 :         torture_wait_for_oplock_break(tctx);
    4945           1 :         torture_assert_goto(tctx, break_info.count == 1, ret, done, "Expected 1 oplock break\n");
    4946             : 
    4947           1 : done:
    4948           1 :         if (!smb2_util_handle_empty(h1)) {
    4949           1 :                 smb2_util_close(tree, h1);
    4950             :         }
    4951           1 :         if (!smb2_util_handle_empty(h2)) {
    4952           1 :                 smb2_util_close(tree, h2);
    4953             :         }
    4954           1 :         smb2_util_unlink(tree, fname);
    4955           1 :         return ret;
    4956             : }
    4957             : 
    4958             : /**
    4959             :  * Recreate regression test from bug:
    4960             :  *
    4961             :  * https://bugzilla.samba.org/show_bug.cgi?id=13058
    4962             :  *
    4963             :  * 1. smbd-1 opens the file and sets the oplock
    4964             :  * 2. smbd-2 tries to open the file. open() fails(EAGAIN) and open is deferred.
    4965             :  * 3. smbd-1 sends oplock break request to the client.
    4966             :  * 4. smbd-1 closes the file.
    4967             :  * 5. smbd-1 opens the file and sets the oplock.
    4968             :  * 6. smbd-2 calls defer_open_done(), and should re-break the oplock.
    4969             :  **/
    4970             : 
    4971           1 : static bool test_smb2_kernel_oplocks7(struct torture_context *tctx,
    4972             :                                       struct smb2_tree *tree,
    4973             :                                       struct smb2_tree *tree2)
    4974             : {
    4975           1 :         const char *fname = "test_kernel_oplock7.dat";
    4976           0 :         NTSTATUS status;
    4977           1 :         bool ret = true;
    4978           0 :         struct smb2_create create;
    4979           1 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4980           0 :         struct smb2_create create_2;
    4981           0 :         struct smb2_create io;
    4982           0 :         struct smb2_request *req;
    4983             : 
    4984           1 :         smb2_util_unlink(tree, fname);
    4985           1 :         status = torture_smb2_testfile(tree, fname, &h1);
    4986           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4987             :                                         "Error creating testfile\n");
    4988           1 :         smb2_util_close(tree, h1);
    4989           1 :         ZERO_STRUCT(h1);
    4990             : 
    4991             :         /* Close the open file on break. */
    4992           1 :         tree->session->transport->oplock.handler = torture_oplock_handler_close;
    4993           1 :         tree->session->transport->oplock.private_data = tree;
    4994           1 :         ZERO_STRUCT(break_info);
    4995             : 
    4996             :         /* 1 - open file with oplock */
    4997           1 :         ZERO_STRUCT(create);
    4998           1 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4999           1 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    5000           1 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    5001           1 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    5002           1 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    5003           1 :         create.in.fname = fname;
    5004           1 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    5005             : 
    5006           1 :         status = smb2_create(tree, tctx, &create);
    5007           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5008             :                         "Error opening the file\n");
    5009           1 :         CHECK_VAL(create.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
    5010             : 
    5011             :         /* 2 - open file to break oplock */
    5012           1 :         ZERO_STRUCT(create_2);
    5013           1 :         create_2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    5014           1 :         create_2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    5015           1 :         create_2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    5016           1 :         create_2.in.create_disposition = NTCREATEX_DISP_OPEN;
    5017           1 :         create_2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    5018           1 :         create_2.in.fname = fname;
    5019           1 :         create_2.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
    5020             : 
    5021             :         /* Open on tree2 - should cause a break on tree */
    5022           1 :         req = smb2_create_send(tree2, &create_2);
    5023           1 :         torture_assert(tctx, req != NULL, "smb2_create_send");
    5024             : 
    5025             :         /* The oplock break handler should close the file. */
    5026             :         /* Steps 3 & 4. */
    5027           1 :         torture_wait_for_oplock_break(tctx);
    5028             : 
    5029           1 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    5030             : 
    5031             :         /*
    5032             :          * 5 - re-open on tree. NB. There is a race here
    5033             :          * depending on which smbd goes first. We either get
    5034             :          * an oplock level of SMB2_OPLOCK_LEVEL_EXCLUSIVE if
    5035             :          * the close and re-open on tree is processed first, or
    5036             :          * SMB2_OPLOCK_LEVEL_NONE if the pending create on
    5037             :          * tree2 is processed first.
    5038             :          */
    5039           1 :         status = smb2_create(tree, tctx, &create);
    5040           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5041             :                         "Error opening the file\n");
    5042             : 
    5043           1 :         h1 = create.out.file.handle;
    5044           1 :         if (create.out.oplock_level != SMB2_OPLOCK_LEVEL_EXCLUSIVE &&
    5045           1 :             create.out.oplock_level != SMB2_OPLOCK_LEVEL_NONE) {
    5046           0 :                 torture_result(tctx,
    5047             :                         TORTURE_FAIL,
    5048             :                         "(%s): wrong value for oplock got 0x%x\n",
    5049             :                         __location__,
    5050           0 :                         (unsigned int)create.out.oplock_level);
    5051           0 :                 ret = false;
    5052           0 :                 goto done;
    5053             : 
    5054             :         }
    5055             : 
    5056             :         /* 6 - retrieve the second open. */
    5057           1 :         status = smb2_create_recv(req, tctx, &io);
    5058           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5059             :                         "Error opening the file\n");
    5060           1 :         h2 = io.out.file.handle;
    5061           1 :         CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
    5062             : 
    5063           1 : done:
    5064           1 :         if (!smb2_util_handle_empty(h1)) {
    5065           1 :                 smb2_util_close(tree, h1);
    5066             :         }
    5067           1 :         if (!smb2_util_handle_empty(h2)) {
    5068           1 :                 smb2_util_close(tree2, h2);
    5069             :         }
    5070           1 :         smb2_util_unlink(tree, fname);
    5071           1 :         return ret;
    5072             : }
    5073             : 
    5074             : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
    5075             : 
    5076             : #ifndef RT_SIGNAL_LEASE
    5077             : #define RT_SIGNAL_LEASE (SIGRTMIN+1)
    5078             : #endif
    5079             : 
    5080             : static int got_break;
    5081             : 
    5082             : /*
    5083             :  * Signal handler.
    5084             :  */
    5085             : 
    5086           0 : static void got_rt_break(int sig)
    5087             : {
    5088           0 :         got_break = 1;
    5089           0 : }
    5090             : 
    5091             : static int got_alarm;
    5092             : 
    5093             : /*
    5094             :  * Signal handler.
    5095             :  */
    5096             : 
    5097           0 : static void got_alarm_fn(int sig)
    5098             : {
    5099           0 :         got_alarm = 1;
    5100           0 : }
    5101             : 
    5102             : /*
    5103             :  * Child process function.
    5104             :  */
    5105             : 
    5106           0 : static int do_child_process(int pipefd, const char *name)
    5107             : {
    5108           0 :         int ret = 0;
    5109           0 :         int fd = -1;
    5110           0 :         char c = 0;
    5111           0 :         struct sigaction act;
    5112           0 :         sigset_t set;
    5113           0 :         sigset_t empty_set;
    5114             : 
    5115             :         /* Block RT_SIGNAL_LEASE and SIGALRM. */
    5116           0 :         sigemptyset(&set);
    5117           0 :         sigemptyset(&empty_set);
    5118           0 :         sigaddset(&set, RT_SIGNAL_LEASE);
    5119           0 :         sigaddset(&set, SIGALRM);
    5120           0 :         ret = sigprocmask(SIG_SETMASK, &set, NULL);
    5121           0 :         if (ret == -1) {
    5122           0 :                 return 11;
    5123             :         }
    5124             : 
    5125             :         /* Set up a signal handler for RT_SIGNAL_LEASE. */
    5126           0 :         ZERO_STRUCT(act);
    5127           0 :         act.sa_handler = got_rt_break;
    5128           0 :         ret = sigaction(RT_SIGNAL_LEASE, &act, NULL);
    5129           0 :         if (ret == -1) {
    5130           0 :                 return 1;
    5131             :         }
    5132             :         /* Set up a signal handler for SIGALRM. */
    5133           0 :         ZERO_STRUCT(act);
    5134           0 :         act.sa_handler = got_alarm_fn;
    5135           0 :         ret = sigaction(SIGALRM, &act, NULL);
    5136           0 :         if (ret == -1) {
    5137           0 :                 return 1;
    5138             :         }
    5139             :         /* Open the passed in file and get a kernel oplock. */
    5140           0 :         fd = open(name, O_RDWR, 0666);
    5141           0 :         if (fd == -1) {
    5142           0 :                 return 2;
    5143             :         }
    5144             : 
    5145           0 :         ret = fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE);
    5146           0 :         if (ret == -1) {
    5147           0 :                 close(fd);
    5148           0 :                 return 3;
    5149             :         }
    5150             : 
    5151           0 :         ret = fcntl(fd, F_SETLEASE, F_WRLCK);
    5152           0 :         if (ret == -1) {
    5153           0 :                 close(fd);
    5154           0 :                 return 4;
    5155             :         }
    5156             : 
    5157             :         /* Tell the parent we're ready. */
    5158           0 :         ret = sys_write(pipefd, &c, 1);
    5159           0 :         if (ret != 1) {
    5160           0 :                 close(fd);
    5161           0 :                 return 5;
    5162             :         }
    5163             : 
    5164             :         /* Ensure the pause doesn't hang forever. */
    5165           0 :         alarm(5);
    5166             : 
    5167             :         /* Wait for RT_SIGNAL_LEASE or SIGALRM. */
    5168           0 :         ret = sigsuspend(&empty_set);
    5169           0 :         if (ret != -1 || errno != EINTR) {
    5170           0 :                 close(fd);
    5171           0 :                 return 6;
    5172             :         }
    5173             : 
    5174           0 :         if (got_alarm == 1) {
    5175           0 :                 close(fd);
    5176           0 :                 return 10;
    5177             :         }
    5178             : 
    5179           0 :         if (got_break != 1) {
    5180           0 :                 close(fd);
    5181           0 :                 return 7;
    5182             :         }
    5183             : 
    5184             :         /* Cancel any pending alarm. */
    5185           0 :         alarm(0);
    5186             : 
    5187             :         /* Force the server to wait for 3 seconds. */
    5188           0 :         sleep(3);
    5189             : 
    5190             :         /* Remove our lease. */
    5191           0 :         ret = fcntl(fd, F_SETLEASE, F_UNLCK);
    5192           0 :         if (ret == -1) {
    5193           0 :                 close(fd);
    5194           0 :                 return 8;
    5195             :         }
    5196             : 
    5197           0 :         ret = close(fd);
    5198           0 :         if (ret == -1) {
    5199           0 :                 return 9;
    5200             :         }
    5201             : 
    5202             :         /* All is well. */
    5203           0 :         return 0;
    5204             : }
    5205             : 
    5206           1 : static bool wait_for_child_oplock(struct torture_context *tctx,
    5207             :                                 const char *localdir,
    5208             :                                 const char *fname)
    5209             : {
    5210           0 :         int fds[2];
    5211           0 :         int ret;
    5212           0 :         pid_t pid;
    5213           1 :         char *name = talloc_asprintf(tctx,
    5214             :                                 "%s/%s",
    5215             :                                 localdir,
    5216             :                                 fname);
    5217             : 
    5218           1 :         torture_assert(tctx, name != NULL, "talloc failed");
    5219             : 
    5220           1 :         ret = pipe(fds);
    5221           1 :         torture_assert(tctx, ret != -1, "pipe failed");
    5222             : 
    5223           1 :         pid = fork();
    5224           1 :         torture_assert(tctx, pid != (pid_t)-1, "fork failed");
    5225             : 
    5226           1 :         if (pid != (pid_t)0) {
    5227           0 :                 char c;
    5228             :                 /* Parent. */
    5229           1 :                 TALLOC_FREE(name);
    5230           1 :                 close(fds[1]);
    5231           1 :                 ret = sys_read(fds[0], &c, 1);
    5232           1 :                 torture_assert(tctx, ret == 1, "read failed");
    5233           1 :                 return true;
    5234             :         }
    5235             : 
    5236             :         /* Child process. */
    5237           0 :         close(fds[0]);
    5238           0 :         ret = do_child_process(fds[1], name);
    5239           0 :         _exit(ret);
    5240             :         /* Notreached. */
    5241             : }
    5242             : #else
    5243             : static bool wait_for_child_oplock(struct torture_context *tctx,
    5244             :                                 const char *localdir,
    5245             :                                 const char *fname)
    5246             : {
    5247             :         return false;
    5248             : }
    5249             : #endif
    5250             : 
    5251           1 : static void child_sig_term_handler(struct tevent_context *ev,
    5252             :                                 struct tevent_signal *se,
    5253             :                                 int signum,
    5254             :                                 int count,
    5255             :                                 void *siginfo,
    5256             :                                 void *private_data)
    5257             : {
    5258           1 :         int *pstatus = (int *)private_data;
    5259           1 :         int status = 0;
    5260             : 
    5261           1 :         wait(&status);
    5262           1 :         if (WIFEXITED(status)) {
    5263           1 :                 *pstatus = WEXITSTATUS(status);
    5264             :         } else {
    5265           0 :                 *pstatus = status;
    5266             :         }
    5267           1 : }
    5268             : 
    5269             : /*
    5270             :  * Deal with a non-smbd process holding a kernel oplock.
    5271             :  */
    5272             : 
    5273           1 : static bool test_smb2_kernel_oplocks8(struct torture_context *tctx,
    5274             :                                       struct smb2_tree *tree)
    5275             : {
    5276           1 :         const char *fname = "test_kernel_oplock8.dat";
    5277           1 :         const char *fname1 = "tmp_test_kernel_oplock8.dat";
    5278           0 :         NTSTATUS status;
    5279           1 :         bool ret = true;
    5280           0 :         struct smb2_create io;
    5281           1 :         struct smb2_request *req = NULL;
    5282           1 :         struct smb2_handle h1 = {{0}};
    5283           1 :         struct smb2_handle h2 = {{0}};
    5284           1 :         const char *localdir = torture_setting_string(tctx, "localdir", NULL);
    5285           1 :         struct tevent_signal *se = NULL;
    5286           1 :         int child_exit_code = -1;
    5287           0 :         time_t start;
    5288           0 :         time_t end;
    5289             : 
    5290             : #ifndef HAVE_KERNEL_OPLOCKS_LINUX
    5291             :         torture_skip(tctx, "Need kernel oplocks for test");
    5292             : #endif
    5293             : 
    5294           1 :         if (localdir == NULL) {
    5295           0 :                 torture_skip(tctx, "Need localdir for test");
    5296             :         }
    5297             : 
    5298           1 :         smb2_util_unlink(tree, fname);
    5299           1 :         smb2_util_unlink(tree, fname1);
    5300           1 :         status = torture_smb2_testfile(tree, fname, &h1);
    5301           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5302             :                                         "Error creating testfile\n");
    5303           1 :         smb2_util_close(tree, h1);
    5304           1 :         ZERO_STRUCT(h1);
    5305             : 
    5306           1 :         se = tevent_add_signal(tctx->ev,
    5307             :                                 tctx,
    5308             :                                 SIGCHLD,
    5309             :                                 0,
    5310             :                                 child_sig_term_handler,
    5311             :                                 &child_exit_code);
    5312           1 :         torture_assert(tctx, se != NULL, "tevent_add_signal failed\n");
    5313             : 
    5314             :         /* Take the oplock locally in a sub-process. */
    5315           1 :         ret = wait_for_child_oplock(tctx, localdir, fname);
    5316           1 :         torture_assert_goto(tctx, ret, ret, done,
    5317             :                 "Wait for child process failed.\n");
    5318             : 
    5319             :         /*
    5320             :          * Now try and open. This should block for 3 seconds.
    5321             :          * while the child process is still alive.
    5322             :          */
    5323             : 
    5324           1 :         ZERO_STRUCT(io);
    5325           1 :         io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
    5326           1 :         io.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
    5327           1 :         io.in.create_disposition = NTCREATEX_DISP_OPEN;
    5328           1 :         io.in.share_access =
    5329             :                 NTCREATEX_SHARE_ACCESS_DELETE|
    5330             :                 NTCREATEX_SHARE_ACCESS_READ|
    5331             :                 NTCREATEX_SHARE_ACCESS_WRITE;
    5332           1 :         io.in.create_options = 0;
    5333           1 :         io.in.fname = fname;
    5334             : 
    5335           1 :         req = smb2_create_send(tree, &io);
    5336           1 :         torture_assert_goto(tctx, req != NULL,
    5337             :                             ret, done, "smb2_create_send");
    5338             : 
    5339             :         /* Ensure while the open is blocked the smbd is
    5340             :            still serving other requests. */
    5341           1 :         io.in.fname = fname1;
    5342           1 :         io.in.create_disposition = NTCREATEX_DISP_CREATE;
    5343             : 
    5344             :         /* Time the start -> end of the request. */
    5345           1 :         start = time(NULL);
    5346           1 :         status = smb2_create(tree, tctx, &io);
    5347           1 :         end = time(NULL);
    5348             : 
    5349             :         /* Should succeed. */
    5350           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5351             :                         "Error opening the second file\n");
    5352           1 :         h1 = io.out.file.handle;
    5353             : 
    5354             :         /* in less than 2 seconds. Otherwise the server blocks. */
    5355           1 :         torture_assert_goto(tctx, end - start < 2,
    5356             :                             ret, done, "server was blocked !");
    5357             : 
    5358             :         /* Pick up the return for the initial blocking open. */
    5359           1 :         status = smb2_create_recv(req, tctx, &io);
    5360             : 
    5361             :         /* Which should also have succeeded. */
    5362           1 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5363             :                         "Error opening the file\n");
    5364           1 :         h2 = io.out.file.handle;
    5365             : 
    5366             :         /* Wait for the exit code from the child. */
    5367           1 :         while (child_exit_code == -1) {
    5368           0 :                 int rval = tevent_loop_once(tctx->ev);
    5369           0 :                 torture_assert_goto(tctx, rval == 0, ret,
    5370             :                                     done, "tevent_loop_once error\n");
    5371             :         }
    5372             : 
    5373           1 :         torture_assert_int_equal_goto(tctx, child_exit_code, 0,
    5374             :                                       ret, done, "Bad child exit code");
    5375             : 
    5376           1 : done:
    5377           1 :         if (!smb2_util_handle_empty(h1)) {
    5378           1 :                 smb2_util_close(tree, h1);
    5379             :         }
    5380           1 :         if (!smb2_util_handle_empty(h2)) {
    5381           1 :                 smb2_util_close(tree, h2);
    5382             :         }
    5383           1 :         smb2_util_unlink(tree, fname);
    5384           1 :         smb2_util_unlink(tree, fname1);
    5385           1 :         return ret;
    5386             : }
    5387             : 
    5388        2379 : struct torture_suite *torture_smb2_kernel_oplocks_init(TALLOC_CTX *ctx)
    5389             : {
    5390         125 :         struct torture_suite *suite =
    5391        2379 :             torture_suite_create(ctx, "kernel-oplocks");
    5392             : 
    5393        2379 :         torture_suite_add_1smb2_test(suite, "kernel_oplocks1", test_smb2_kernel_oplocks1);
    5394        2379 :         torture_suite_add_1smb2_test(suite, "kernel_oplocks2", test_smb2_kernel_oplocks2);
    5395        2379 :         torture_suite_add_2smb2_test(suite, "kernel_oplocks3", test_smb2_kernel_oplocks3);
    5396        2379 :         torture_suite_add_1smb2_test(suite, "kernel_oplocks4", test_smb2_kernel_oplocks4);
    5397        2379 :         torture_suite_add_1smb2_test(suite, "kernel_oplocks5", test_smb2_kernel_oplocks5);
    5398        2379 :         torture_suite_add_2smb2_test(suite, "kernel_oplocks6", test_smb2_kernel_oplocks6);
    5399        2379 :         torture_suite_add_2smb2_test(suite, "kernel_oplocks7", test_smb2_kernel_oplocks7);
    5400        2379 :         torture_suite_add_1smb2_test(suite, "kernel_oplocks8", test_smb2_kernel_oplocks8);
    5401             : 
    5402        2379 :         suite->description = talloc_strdup(suite, "SMB2-KERNEL-OPLOCK tests");
    5403             : 
    5404        2379 :         return suite;
    5405             : }

Generated by: LCOV version 1.14