LCOV - code coverage report
Current view: top level - source4/torture/smb2 - oplock.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 2259 3060 73.8 %
Date: 2024-06-13 04:01:37 Functions: 61 77 79.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          41 : static void torture_oplock_break_callback(struct smb2_request *req)
      80             : {
      81             :         NTSTATUS status;
      82             :         struct smb2_break br;
      83             : 
      84          41 :         ZERO_STRUCT(br);
      85          41 :         status = smb2_break_recv(req, &break_info.br);
      86          41 :         if (!NT_STATUS_IS_OK(status)) {
      87           0 :                 break_info.failures++;
      88           0 :                 break_info.failure_status = status;
      89             :         }
      90             : 
      91          41 :         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          32 : 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          32 :         struct smb2_tree *tree = private_data;
     102             :         const char *name;
     103             :         struct smb2_request *req;
     104          32 :         ZERO_STRUCT(break_info.br);
     105             : 
     106          32 :         break_info.handle       = *handle;
     107          32 :         break_info.level        = level;
     108          32 :         break_info.count++;
     109             : 
     110          32 :         switch (level) {
     111          32 :         case SMB2_OPLOCK_LEVEL_II:
     112          32 :                 name = "level II";
     113          32 :                 break;
     114           0 :         case SMB2_OPLOCK_LEVEL_NONE:
     115           0 :                 name = "none";
     116           0 :                 break;
     117           0 :         default:
     118           0 :                 name = "unknown";
     119           0 :                 break_info.failures++;
     120             :         }
     121          32 :         printf("Acking to %s [0x%02X] in oplock handler\n", name, level);
     122             : 
     123          32 :         break_info.br.in.file.handle    = *handle;
     124          32 :         break_info.br.in.oplock_level   = level;
     125          32 :         break_info.br.in.reserved       = 0;
     126          32 :         break_info.br.in.reserved2      = 0;
     127             : 
     128          32 :         req = smb2_break_send(tree, &break_info.br);
     129          32 :         req->async.fn = torture_oplock_break_callback;
     130          32 :         req->async.private_data = NULL;
     131          32 :         return true;
     132             : }
     133             : 
     134             : /*
     135             :   A handler function for oplock break notifications. Send a break to none
     136             :   request.
     137             : */
     138           1 : 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           1 :         struct smb2_tree *tree = private_data;
     144             :         struct smb2_request *req;
     145             : 
     146           1 :         break_info.handle = *handle;
     147           1 :         break_info.level = level;
     148           1 :         break_info.count++;
     149             : 
     150           1 :         printf("Acking to none in oplock handler\n");
     151             : 
     152           1 :         ZERO_STRUCT(break_info.br);
     153           1 :         break_info.br.in.file.handle    = *handle;
     154           1 :         break_info.br.in.oplock_level   = SMB2_OPLOCK_LEVEL_NONE;
     155           1 :         break_info.br.in.reserved       = 0;
     156           1 :         break_info.br.in.reserved2      = 0;
     157             : 
     158           1 :         req = smb2_break_send(tree, &break_info.br);
     159           1 :         req->async.fn = torture_oplock_break_callback;
     160           1 :         req->async.private_data = NULL;
     161             : 
     162           1 :         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           8 : 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           8 :         break_info.handle = *handle;
     177           8 :         break_info.level = level;
     178           8 :         break_info.count++;
     179             : 
     180           8 :         printf("Break from level II to none in oplock handler\n");
     181             : 
     182           8 :         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           8 : 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           8 :         struct smb2_tree *tree = private_data;
     194             :         const char *name;
     195             :         struct smb2_request *req;
     196           8 :         ZERO_STRUCT(break_info.br);
     197             : 
     198           8 :         break_info.handle       = *handle;
     199           8 :         break_info.level        = level;
     200           8 :         break_info.count++;
     201             : 
     202           8 :         switch (level) {
     203           8 :         case SMB2_OPLOCK_LEVEL_II:
     204           8 :                 name = "level II";
     205           8 :                 break;
     206           0 :         case SMB2_OPLOCK_LEVEL_NONE:
     207           0 :                 name = "none";
     208           0 :                 break;
     209           0 :         default:
     210           0 :                 name = "unknown";
     211           0 :                 break_info.failures++;
     212             :         }
     213           8 :         printf("Breaking to %s [0x%02X] in oplock handler\n", name, level);
     214             : 
     215           8 :         if (level == SMB2_OPLOCK_LEVEL_NONE)
     216           0 :                 return true;
     217             : 
     218           8 :         break_info.br.in.file.handle    = *handle;
     219           8 :         break_info.br.in.oplock_level   = level;
     220           8 :         break_info.br.in.reserved       = 0;
     221           8 :         break_info.br.in.reserved2      = 0;
     222             : 
     223           8 :         req = smb2_break_send(tree, &break_info.br);
     224           8 :         req->async.fn = torture_oplock_break_callback;
     225           8 :         req->async.private_data = NULL;
     226           8 :         return true;
     227             : }
     228           2 : static void torture_oplock_handler_close_recv(struct smb2_request *req)
     229             : {
     230           2 :         if (!smb2_request_receive(req)) {
     231           0 :                 printf("close failed in oplock_handler_close\n");
     232           0 :                 break_info.failures++;
     233             :         }
     234           2 : }
     235             : 
     236             : /*
     237             :   a handler function for oplock break requests - close the file
     238             : */
     239           2 : 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             :         struct smb2_close io;
     245           2 :         struct smb2_tree *tree = private_data;
     246             :         struct smb2_request *req;
     247             : 
     248           2 :         break_info.handle = *handle;
     249           2 :         break_info.level = level;
     250           2 :         break_info.count++;
     251             : 
     252           2 :         ZERO_STRUCT(io);
     253           2 :         io.in.file.handle       = *handle;
     254           2 :         io.in.flags          = RAW_CLOSE_SMB2;
     255           2 :         req = smb2_close_send(tree, &io);
     256           2 :         if (req == NULL) {
     257           0 :                 printf("failed to send close in oplock_handler_close\n");
     258           0 :                 return false;
     259             :         }
     260             : 
     261           2 :         req->async.fn = torture_oplock_handler_close_recv;
     262           2 :         req->async.private_data = NULL;
     263             : 
     264           2 :         return true;
     265             : }
     266             : 
     267             : /*
     268             :   a handler function for oplock break requests. Let it timeout
     269             : */
     270           1 : 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           1 :         break_info.handle = *handle;
     276           1 :         break_info.level = level;
     277           1 :         break_info.count++;
     278             : 
     279           1 :         printf("Let oplock break timeout\n");
     280           1 :         return true;
     281             : }
     282             : 
     283           2 : static bool open_smb2_connection_no_level2_oplocks(struct torture_context *tctx,
     284             :                                                    struct smb2_tree **tree)
     285             : {
     286             :         NTSTATUS status;
     287           2 :         const char *host = torture_setting_string(tctx, "host", NULL);
     288           2 :         const char *share = torture_setting_string(tctx, "share", NULL);
     289             :         struct smbcli_options options;
     290             : 
     291           2 :         lpcfg_smbcli_options(tctx->lp_ctx, &options);
     292           2 :         options.use_level2_oplocks = false;
     293             : 
     294           2 :         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           2 :         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           2 :         return true;
     308             : }
     309             : 
     310           1 : static bool test_smb2_oplock_exclusive1(struct torture_context *tctx,
     311             :                                         struct smb2_tree *tree1,
     312             :                                         struct smb2_tree *tree2)
     313             : {
     314           1 :         const char *fname = BASEDIR "\\test_exclusive1.dat";
     315             :         NTSTATUS status;
     316           1 :         bool ret = true;
     317             :         union smb_open io;
     318             :         struct smb2_handle h1;
     319             :         struct smb2_handle h;
     320             : 
     321           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     322           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     323             : 
     324             :         /* cleanup */
     325           1 :         smb2_util_unlink(tree1, fname);
     326             : 
     327           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     328           1 :         tree1->session->transport->oplock.private_data = tree1;
     329             : 
     330             :         /*
     331             :           base ntcreatex parms
     332             :         */
     333           1 :         ZERO_STRUCT(io.smb2);
     334           1 :         io.generic.level = RAW_OPEN_SMB2;
     335           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     336           1 :         io.smb2.in.alloc_size = 0;
     337           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     338           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     339           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     340           1 :         io.smb2.in.create_options = 0;
     341           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     342           1 :         io.smb2.in.security_flags = 0;
     343           1 :         io.smb2.in.fname = fname;
     344             : 
     345           1 :         torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive "
     346             :                         "oplock (share mode: none)\n");
     347           1 :         ZERO_STRUCT(break_info);
     348           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     349             : 
     350           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
     351           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     352           1 :         h1 = io.smb2.out.file.handle;
     353           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     354             : 
     355           1 :         torture_comment(tctx, "a 2nd open should not cause a break\n");
     356           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
     357           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     358             :                                       "Incorrect status");
     359           1 :         torture_wait_for_oplock_break(tctx);
     360           1 :         CHECK_VAL(break_info.count, 0);
     361           1 :         CHECK_VAL(break_info.failures, 0);
     362             : 
     363           1 :         torture_comment(tctx, "unlink it - should also be no break\n");
     364           1 :         status = smb2_util_unlink(tree2, fname);
     365           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     366             :                                       "Incorrect status");
     367           1 :         torture_wait_for_oplock_break(tctx);
     368           1 :         CHECK_VAL(break_info.count, 0);
     369           1 :         CHECK_VAL(break_info.failures, 0);
     370             : 
     371           1 :         smb2_util_close(tree1, h1);
     372           1 :         smb2_util_close(tree1, h);
     373             : 
     374           1 :         smb2_deltree(tree1, BASEDIR);
     375           1 :         return ret;
     376             : }
     377             : 
     378           1 : static bool test_smb2_oplock_exclusive2(struct torture_context *tctx,
     379             :                                         struct smb2_tree *tree1,
     380             :                                         struct smb2_tree *tree2)
     381             : {
     382           1 :         const char *fname = BASEDIR "\\test_exclusive2.dat";
     383             :         NTSTATUS status;
     384           1 :         bool ret = true;
     385             :         union smb_open io;
     386             :         struct smb2_handle h, h1, h2;
     387             : 
     388           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     389           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     390             : 
     391             :         /* cleanup */
     392           1 :         smb2_util_unlink(tree1, fname);
     393             : 
     394           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     395           1 :         tree1->session->transport->oplock.private_data = tree1;
     396             : 
     397             :         /*
     398             :           base ntcreatex parms
     399             :         */
     400           1 :         ZERO_STRUCT(io.smb2);
     401           1 :         io.generic.level = RAW_OPEN_SMB2;
     402           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     403           1 :         io.smb2.in.alloc_size = 0;
     404           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     405           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     406           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     407           1 :         io.smb2.in.create_options = 0;
     408           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     409           1 :         io.smb2.in.security_flags = 0;
     410           1 :         io.smb2.in.fname = fname;
     411             : 
     412           1 :         torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive "
     413             :                         "oplock (share mode: all)\n");
     414           1 :         ZERO_STRUCT(break_info);
     415           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     416           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
     417             :                 NTCREATEX_SHARE_ACCESS_WRITE|
     418             :                 NTCREATEX_SHARE_ACCESS_DELETE;
     419           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     420             : 
     421           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
     422           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     423           1 :         h1 = io.smb2.out.file.handle;
     424           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     425             : 
     426           1 :         torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
     427           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
     428           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     429           1 :         h2 = io.smb2.out.file.handle;
     430           1 :         torture_wait_for_oplock_break(tctx);
     431           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
     432           1 :         CHECK_VAL(break_info.count, 1);
     433           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
     434           1 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
     435           1 :         CHECK_VAL(break_info.failures, 0);
     436           1 :         ZERO_STRUCT(break_info);
     437             : 
     438             :         /* now we have 2 level II oplocks... */
     439           1 :         torture_comment(tctx, "try to unlink it - should cause a break\n");
     440           1 :         status = smb2_util_unlink(tree2, fname);
     441           1 :         torture_assert_ntstatus_ok(tctx, status, "Error unlinking the file");
     442           0 :         torture_wait_for_oplock_break(tctx);
     443           0 :         CHECK_VAL(break_info.count, 0);
     444           0 :         CHECK_VAL(break_info.failures, 0);
     445             : 
     446           0 :         torture_comment(tctx, "close both handles\n");
     447           0 :         smb2_util_close(tree1, h1);
     448           0 :         smb2_util_close(tree1, h2);
     449           0 :         smb2_util_close(tree1, h);
     450             : 
     451           0 :         smb2_deltree(tree1, BASEDIR);
     452           0 :         return ret;
     453             : }
     454             : 
     455           1 : static bool test_smb2_oplock_exclusive3(struct torture_context *tctx,
     456             :                                         struct smb2_tree *tree1,
     457             :                                         struct smb2_tree *tree2)
     458             : {
     459           1 :         const char *fname = BASEDIR "\\test_exclusive3.dat";
     460             :         NTSTATUS status;
     461           1 :         bool ret = true;
     462             :         union smb_open io;
     463             :         union smb_setfileinfo sfi;
     464             :         struct smb2_handle h, h1;
     465             : 
     466           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     467           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     468             : 
     469             :         /* cleanup */
     470           1 :         smb2_util_unlink(tree1, fname);
     471             : 
     472           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     473           1 :         tree1->session->transport->oplock.private_data = tree1;
     474             : 
     475             :         /*
     476             :           base ntcreatex parms
     477             :         */
     478           1 :         ZERO_STRUCT(io.smb2);
     479           1 :         io.generic.level = RAW_OPEN_SMB2;
     480           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     481           1 :         io.smb2.in.alloc_size = 0;
     482           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     483           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     484           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     485           1 :         io.smb2.in.create_options = 0;
     486           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     487           1 :         io.smb2.in.security_flags = 0;
     488           1 :         io.smb2.in.fname = fname;
     489             : 
     490           1 :         torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive "
     491             :                         "oplock (share mode: none)\n");
     492             : 
     493           1 :         ZERO_STRUCT(break_info);
     494           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     495           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     496             : 
     497           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
     498           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     499           1 :         h1 = io.smb2.out.file.handle;
     500           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     501             : 
     502           1 :         torture_comment(tctx, "setpathinfo EOF should trigger a break to "
     503             :                         "none\n");
     504           1 :         ZERO_STRUCT(sfi);
     505           1 :         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
     506           1 :         sfi.generic.in.file.path = fname;
     507           1 :         sfi.end_of_file_info.in.size = 100;
     508             : 
     509           1 :         status = smb2_composite_setpathinfo(tree2, &sfi);
     510             : 
     511           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     512             :                                       "Incorrect status");
     513           1 :         torture_wait_for_oplock_break(tctx);
     514           1 :         CHECK_VAL(break_info.count, 0);
     515           1 :         CHECK_VAL(break_info.failures, 0);
     516           1 :         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
     517             : 
     518           1 :         smb2_util_close(tree1, h1);
     519           1 :         smb2_util_close(tree1, h);
     520             : 
     521           1 :         smb2_deltree(tree1, BASEDIR);
     522           1 :         return ret;
     523             : }
     524             : 
     525           1 : static bool test_smb2_oplock_exclusive4(struct torture_context *tctx,
     526             :                                         struct smb2_tree *tree1,
     527             :                                         struct smb2_tree *tree2)
     528             : {
     529           1 :         const char *fname = BASEDIR "\\test_exclusive4.dat";
     530             :         NTSTATUS status;
     531           1 :         bool ret = true;
     532             :         union smb_open io;
     533             :         struct smb2_handle h, h1, h2;
     534             : 
     535           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     536           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     537             : 
     538             :         /* cleanup */
     539           1 :         smb2_util_unlink(tree1, fname);
     540             : 
     541           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     542           1 :         tree1->session->transport->oplock.private_data = tree1;
     543             : 
     544             :         /*
     545             :           base ntcreatex parms
     546             :         */
     547           1 :         ZERO_STRUCT(io.smb2);
     548           1 :         io.generic.level = RAW_OPEN_SMB2;
     549           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     550           1 :         io.smb2.in.alloc_size = 0;
     551           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     552           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     553           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     554           1 :         io.smb2.in.create_options = 0;
     555           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     556           1 :         io.smb2.in.security_flags = 0;
     557           1 :         io.smb2.in.fname = fname;
     558             : 
     559           1 :         torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
     560           1 :         ZERO_STRUCT(break_info);
     561             : 
     562           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     563           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     564           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
     565           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     566           1 :         h1 = io.smb2.out.file.handle;
     567           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     568             : 
     569           1 :         ZERO_STRUCT(break_info);
     570           1 :         torture_comment(tctx, "second open with attributes only shouldn't "
     571             :                         "cause oplock break\n");
     572             : 
     573           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     574           1 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
     575             :                                 SEC_FILE_WRITE_ATTRIBUTE |
     576             :                                 SEC_STD_SYNCHRONIZE;
     577           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     578           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
     579           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
     580           1 :         h2 = io.smb2.out.file.handle;
     581           1 :         CHECK_VAL(io.smb2.out.oplock_level, NO_OPLOCK_RETURN);
     582           1 :         torture_wait_for_oplock_break(tctx);
     583           1 :         CHECK_VAL(break_info.count, 0);
     584           1 :         CHECK_VAL(break_info.failures, 0);
     585             : 
     586           1 :         smb2_util_close(tree1, h1);
     587           1 :         smb2_util_close(tree2, h2);
     588           1 :         smb2_util_close(tree1, h);
     589             : 
     590           1 :         smb2_deltree(tree1, BASEDIR);
     591           1 :         return ret;
     592             : }
     593             : 
     594           1 : static bool test_smb2_oplock_exclusive5(struct torture_context *tctx,
     595             :                                         struct smb2_tree *tree1,
     596             :                                         struct smb2_tree *tree2)
     597             : {
     598           1 :         const char *fname = BASEDIR "\\test_exclusive5.dat";
     599             :         NTSTATUS status;
     600           1 :         bool ret = true;
     601             :         union smb_open io;
     602             :         struct smb2_handle h, h1, h2;
     603             : 
     604           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     605           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     606             : 
     607             :         /* cleanup */
     608           1 :         smb2_util_unlink(tree1, fname);
     609             : 
     610           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     611           1 :         tree1->session->transport->oplock.private_data = tree1;
     612             : 
     613           1 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
     614           1 :         tree2->session->transport->oplock.private_data = tree2;
     615             : 
     616             :         /*
     617             :           base ntcreatex parms
     618             :         */
     619           1 :         ZERO_STRUCT(io.smb2);
     620           1 :         io.generic.level = RAW_OPEN_SMB2;
     621           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     622           1 :         io.smb2.in.alloc_size = 0;
     623           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     624           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     625           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     626           1 :         io.smb2.in.create_options = 0;
     627           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     628           1 :         io.smb2.in.security_flags = 0;
     629           1 :         io.smb2.in.fname = fname;
     630             : 
     631           1 :         torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
     632           1 :         ZERO_STRUCT(break_info);
     633             : 
     634           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     635           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
     636             :                 NTCREATEX_SHARE_ACCESS_WRITE|
     637             :                 NTCREATEX_SHARE_ACCESS_DELETE;
     638           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     639           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
     640           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     641           1 :         h1 = io.smb2.out.file.handle;
     642           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     643             : 
     644           1 :         ZERO_STRUCT(break_info);
     645             : 
     646           1 :         torture_comment(tctx, "second open with attributes only and "
     647             :                         "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
     648             :                         "oplock break\n");
     649             : 
     650           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     651           1 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
     652             :                                 SEC_FILE_WRITE_ATTRIBUTE |
     653             :                                 SEC_STD_SYNCHRONIZE;
     654           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
     655           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
     656           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
     657           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
     658           1 :         h2 = io.smb2.out.file.handle;
     659           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
     660           1 :         torture_wait_for_oplock_break(tctx);
     661           1 :         CHECK_VAL(break_info.count, 1);
     662           1 :         CHECK_VAL(break_info.failures, 0);
     663             : 
     664           1 :         smb2_util_close(tree1, h1);
     665           1 :         smb2_util_close(tree2, h2);
     666           1 :         smb2_util_close(tree1, h);
     667             : 
     668           1 :         smb2_deltree(tree1, BASEDIR);
     669           1 :         return ret;
     670             : }
     671             : 
     672           1 : static bool test_smb2_oplock_exclusive6(struct torture_context *tctx,
     673             :                                         struct smb2_tree *tree1,
     674             :                                         struct smb2_tree *tree2)
     675             : {
     676           1 :         const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
     677           1 :         const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
     678             :         NTSTATUS status;
     679           1 :         bool ret = true;
     680             :         union smb_open io;
     681             :         union smb_setfileinfo sinfo;
     682             :         struct smb2_close closeio;
     683             :         struct smb2_handle h, h1;
     684             : 
     685           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     686           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     687             : 
     688             :         /* cleanup */
     689           1 :         smb2_util_unlink(tree1, fname1);
     690           1 :         smb2_util_unlink(tree2, fname2);
     691             : 
     692           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     693           1 :         tree1->session->transport->oplock.private_data = tree1;
     694             : 
     695             :         /*
     696             :           base ntcreatex parms
     697             :         */
     698           1 :         ZERO_STRUCT(io.smb2);
     699           1 :         io.generic.level = RAW_OPEN_SMB2;
     700           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     701           1 :         io.smb2.in.alloc_size = 0;
     702           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     703           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     704           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     705           1 :         io.smb2.in.create_options = 0;
     706           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     707           1 :         io.smb2.in.security_flags = 0;
     708           1 :         io.smb2.in.fname = fname1;
     709             : 
     710           1 :         torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
     711             :                         "oplock (share mode: none)\n");
     712           1 :         ZERO_STRUCT(break_info);
     713           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     714           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     715             : 
     716           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
     717           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     718           1 :         h1 = io.smb2.out.file.handle;
     719           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     720             : 
     721           1 :         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           1 :         ZERO_STRUCT(sinfo);
     725           1 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     726           1 :         sinfo.rename_information.in.file.handle = h1;
     727           1 :         sinfo.rename_information.in.overwrite = true;
     728           1 :         sinfo.rename_information.in.new_name = fname2;
     729           1 :         status = smb2_setinfo_file(tree1, &sinfo);
     730             : 
     731           1 :         torture_comment(tctx, "trying rename while parent handle open for delete.\n");
     732           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     733             :                                       "Incorrect status");
     734           0 :         torture_wait_for_oplock_break(tctx);
     735           0 :         CHECK_VAL(break_info.count, 0);
     736           0 :         CHECK_VAL(break_info.failures, 0);
     737             : 
     738             :         /* Close the parent directory handle. */
     739           0 :         ZERO_STRUCT(closeio);
     740           0 :         closeio.in.file.handle = h;
     741           0 :         status = smb2_close(tree1, &closeio);
     742           0 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
     743             :                                       "Incorrect status");
     744             : 
     745             :         /* Re-open without DELETE access. */
     746           0 :         ZERO_STRUCT(io);
     747           0 :         io.smb2.in.oplock_level = 0;
     748           0 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL & (~SEC_STD_DELETE);
     749           0 :         io.smb2.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
     750           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
     751           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
     752           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     753           0 :         io.smb2.in.fname = BASEDIR;
     754             : 
     755           0 :         status = smb2_create(tree1, tctx, &(io.smb2));
     756           0 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the base directory");
     757             : 
     758           0 :         torture_comment(tctx, "rename with the parent directory handle open "
     759             :                         "without DELETE should succeed without a break\n");
     760           0 :         ZERO_STRUCT(sinfo);
     761           0 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     762           0 :         sinfo.rename_information.in.file.handle = h1;
     763           0 :         sinfo.rename_information.in.overwrite = true;
     764           0 :         sinfo.rename_information.in.new_name = fname2;
     765           0 :         status = smb2_setinfo_file(tree1, &sinfo);
     766             : 
     767           0 :         torture_comment(tctx, "trying rename while parent handle open without delete\n");
     768           0 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
     769             :                                       "Incorrect status");
     770           0 :         torture_wait_for_oplock_break(tctx);
     771           0 :         CHECK_VAL(break_info.count, 0);
     772           0 :         CHECK_VAL(break_info.failures, 0);
     773             : 
     774           0 :         smb2_util_close(tree1, h1);
     775           0 :         smb2_util_close(tree1, h);
     776             : 
     777           0 :         smb2_deltree(tree1, BASEDIR);
     778           0 :         return ret;
     779             : }
     780             : 
     781           1 : static bool test_smb2_oplock_exclusive9(struct torture_context *tctx,
     782             :                                         struct smb2_tree *tree1,
     783             :                                         struct smb2_tree *tree2)
     784             : {
     785           1 :         const char *fname = BASEDIR "\\test_exclusive9.dat";
     786             :         NTSTATUS status;
     787           1 :         bool ret = true;
     788             :         union smb_open io;
     789             :         struct smb2_handle h1, h2;
     790             :         int i;
     791             : 
     792             :         struct {
     793             :                 uint32_t create_disposition;
     794             :                 uint32_t break_level;
     795           1 :         } 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           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h1);
     804           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     805           1 :         smb2_util_close(tree1, h1);
     806             : 
     807             :         /* cleanup */
     808           1 :         smb2_util_unlink(tree1, fname);
     809             : 
     810           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     811           1 :         tree1->session->transport->oplock.private_data = tree1;
     812             : 
     813             :         /*
     814             :           base ntcreatex parms
     815             :         */
     816           1 :         ZERO_STRUCT(io.smb2);
     817           1 :         io.generic.level = RAW_OPEN_SMB2;
     818           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     819           1 :         io.smb2.in.alloc_size = 0;
     820           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     821           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     822             :                 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
     823           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     824           1 :         io.smb2.in.create_options = 0;
     825           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     826           1 :         io.smb2.in.security_flags = 0;
     827           1 :         io.smb2.in.fname = fname;
     828             : 
     829           5 :         for (i=0; i<ARRAY_SIZE(levels); i++) {
     830             : 
     831           4 :                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     832           4 :                 io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     833             : 
     834           4 :                 status = smb2_create(tree1, tctx, &(io.smb2));
     835           4 :                 torture_assert_ntstatus_ok(tctx, status,
     836             :                                            "Error opening the file");
     837           4 :                 h1 = io.smb2.out.file.handle;
     838           4 :                 CHECK_VAL(io.smb2.out.oplock_level,
     839             :                           SMB2_OPLOCK_LEVEL_EXCLUSIVE);
     840             : 
     841           4 :                 ZERO_STRUCT(break_info);
     842             : 
     843           4 :                 io.smb2.in.create_disposition = levels[i].create_disposition;
     844           4 :                 status = smb2_create(tree2, tctx, &(io.smb2));
     845           4 :                 torture_assert_ntstatus_ok(tctx, status,
     846             :                                            "Error opening the file");
     847           4 :                 h2 = io.smb2.out.file.handle;
     848           4 :                 CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
     849             : 
     850           4 :                 CHECK_VAL(break_info.count, 1);
     851           4 :                 CHECK_VAL(break_info.level, levels[i].break_level);
     852           4 :                 CHECK_VAL(break_info.failures, 0);
     853             : 
     854           4 :                 smb2_util_close(tree2, h2);
     855           4 :                 smb2_util_close(tree1, h1);
     856             :         }
     857             : 
     858           1 :         smb2_deltree(tree1, BASEDIR);
     859           1 :         return ret;
     860             : }
     861             : 
     862           1 : static bool test_smb2_oplock_batch1(struct torture_context *tctx,
     863             :                                     struct smb2_tree *tree1,
     864             :                                     struct smb2_tree *tree2)
     865             : {
     866           1 :         const char *fname = BASEDIR "\\test_batch1.dat";
     867             :         NTSTATUS status;
     868           1 :         bool ret = true;
     869             :         union smb_open io;
     870             :         struct smb2_handle h, h1;
     871           1 :         char c = 0;
     872             : 
     873           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     874           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     875             : 
     876             :         /* cleanup */
     877           1 :         smb2_util_unlink(tree1, fname);
     878             : 
     879           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     880           1 :         tree1->session->transport->oplock.private_data = tree1;
     881             : 
     882             :         /*
     883             :           base ntcreatex parms
     884             :         */
     885           1 :         ZERO_STRUCT(io.smb2);
     886           1 :         io.generic.level = RAW_OPEN_SMB2;
     887           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     888           1 :         io.smb2.in.alloc_size = 0;
     889           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     890           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     891           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     892           1 :         io.smb2.in.create_options = 0;
     893           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     894           1 :         io.smb2.in.security_flags = 0;
     895           1 :         io.smb2.in.fname = fname;
     896             : 
     897             :         /*
     898             :           with a batch oplock we get a break
     899             :         */
     900           1 :         torture_comment(tctx, "BATCH1: open with batch oplock\n");
     901           1 :         ZERO_STRUCT(break_info);
     902           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     903           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
     904           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
     905           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     906           1 :         h1 = io.smb2.out.file.handle;
     907           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
     908             : 
     909           1 :         torture_comment(tctx, "unlink should generate a break\n");
     910           1 :         status = smb2_util_unlink(tree2, fname);
     911           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     912             :                                       "Incorrect status");
     913             : 
     914           1 :         torture_wait_for_oplock_break(tctx);
     915           1 :         CHECK_VAL(break_info.count, 1);
     916           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
     917           1 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
     918           1 :         CHECK_VAL(break_info.failures, 0);
     919             : 
     920           1 :         torture_comment(tctx, "2nd unlink should not generate a break\n");
     921           1 :         ZERO_STRUCT(break_info);
     922           1 :         status = smb2_util_unlink(tree2, fname);
     923           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     924             :                                       "Incorrect status");
     925             : 
     926           1 :         torture_wait_for_oplock_break(tctx);
     927           1 :         CHECK_VAL(break_info.count, 0);
     928             : 
     929           1 :         torture_comment(tctx, "writing should generate a self break to none\n");
     930           1 :         tree1->session->transport->oplock.handler =
     931             :             torture_oplock_handler_level2_to_none;
     932           1 :         smb2_util_write(tree1, h1, &c, 0, 1);
     933             : 
     934           1 :         torture_wait_for_oplock_break(tctx);
     935             : 
     936           1 :         CHECK_VAL(break_info.count, 1);
     937           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
     938           1 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
     939           1 :         CHECK_VAL(break_info.failures, 0);
     940             : 
     941           1 :         smb2_util_close(tree1, h1);
     942           1 :         smb2_util_close(tree1, h);
     943             : 
     944           1 :         smb2_deltree(tree1, BASEDIR);
     945           1 :         return ret;
     946             : }
     947             : 
     948           1 : static bool test_smb2_oplock_batch2(struct torture_context *tctx,
     949             :                                     struct smb2_tree *tree1,
     950             :                                     struct smb2_tree *tree2)
     951             : {
     952           1 :         const char *fname = BASEDIR "\\test_batch2.dat";
     953             :         NTSTATUS status;
     954           1 :         bool ret = true;
     955             :         union smb_open io;
     956           1 :         char c = 0;
     957             :         struct smb2_handle h, h1;
     958             : 
     959           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
     960           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
     961             : 
     962             :         /* cleanup */
     963           1 :         smb2_util_unlink(tree1, fname);
     964             : 
     965           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
     966           1 :         tree1->session->transport->oplock.private_data = tree1;
     967             : 
     968             :         /*
     969             :           base ntcreatex parms
     970             :         */
     971           1 :         ZERO_STRUCT(io.smb2);
     972           1 :         io.generic.level = RAW_OPEN_SMB2;
     973           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     974           1 :         io.smb2.in.alloc_size = 0;
     975           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     976           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     977           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     978           1 :         io.smb2.in.create_options = 0;
     979           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     980           1 :         io.smb2.in.security_flags = 0;
     981           1 :         io.smb2.in.fname = fname;
     982             : 
     983           1 :         torture_comment(tctx, "BATCH2: open with batch oplock\n");
     984           1 :         ZERO_STRUCT(break_info);
     985           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     986           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
     987           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
     988           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     989           1 :         h1 = io.smb2.out.file.handle;
     990           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
     991             : 
     992           1 :         torture_comment(tctx, "unlink should generate a break, which we ack "
     993             :                         "as break to none\n");
     994           1 :         tree1->session->transport->oplock.handler =
     995             :                                 torture_oplock_handler_ack_to_none;
     996           1 :         tree1->session->transport->oplock.private_data = tree1;
     997           1 :         status = smb2_util_unlink(tree2, fname);
     998           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
     999             :                                      "Incorrect status");
    1000             : 
    1001           1 :         torture_wait_for_oplock_break(tctx);
    1002           1 :         CHECK_VAL(break_info.count, 1);
    1003           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    1004           1 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    1005           1 :         CHECK_VAL(break_info.failures, 0);
    1006             : 
    1007           1 :         torture_comment(tctx, "2nd unlink should not generate a break\n");
    1008           1 :         ZERO_STRUCT(break_info);
    1009           1 :         status = smb2_util_unlink(tree2, fname);
    1010           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
    1011             :                                       "Incorrect status");
    1012             : 
    1013           1 :         torture_wait_for_oplock_break(tctx);
    1014           1 :         CHECK_VAL(break_info.count, 0);
    1015             : 
    1016           1 :         torture_comment(tctx, "writing should not generate a break\n");
    1017           1 :         smb2_util_write(tree1, h1, &c, 0, 1);
    1018             : 
    1019           1 :         torture_wait_for_oplock_break(tctx);
    1020           1 :         CHECK_VAL(break_info.count, 0);
    1021             : 
    1022           1 :         smb2_util_close(tree1, h1);
    1023           1 :         smb2_util_close(tree1, h);
    1024             : 
    1025           1 :         smb2_deltree(tree1, BASEDIR);
    1026           1 :         return ret;
    1027             : }
    1028             : 
    1029           1 : static bool test_smb2_oplock_batch3(struct torture_context *tctx,
    1030             :                                     struct smb2_tree *tree1,
    1031             :                                     struct smb2_tree *tree2)
    1032             : {
    1033           1 :         const char *fname = BASEDIR "\\test_batch3.dat";
    1034             :         NTSTATUS status;
    1035           1 :         bool ret = true;
    1036             :         union smb_open io;
    1037             :         struct smb2_handle h, h1;
    1038             : 
    1039           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1040           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1041             : 
    1042             :         /* cleanup */
    1043           1 :         smb2_util_unlink(tree1, fname);
    1044           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1045           1 :         tree1->session->transport->oplock.private_data = tree1;
    1046             : 
    1047             :         /*
    1048             :           base ntcreatex parms
    1049             :         */
    1050           1 :         ZERO_STRUCT(io.smb2);
    1051           1 :         io.generic.level = RAW_OPEN_SMB2;
    1052           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1053           1 :         io.smb2.in.alloc_size = 0;
    1054           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1055           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1056           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1057           1 :         io.smb2.in.create_options = 0;
    1058           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1059           1 :         io.smb2.in.security_flags = 0;
    1060           1 :         io.smb2.in.fname = fname;
    1061             : 
    1062           1 :         torture_comment(tctx, "BATCH3: if we close on break then the unlink "
    1063             :                         "can succeed\n");
    1064           1 :         ZERO_STRUCT(break_info);
    1065           1 :         tree1->session->transport->oplock.handler =
    1066             :                                         torture_oplock_handler_close;
    1067           1 :         tree1->session->transport->oplock.private_data = tree1;
    1068             : 
    1069           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1070           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1071           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1072           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1073           1 :         h1 = io.smb2.out.file.handle;
    1074           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1075             : 
    1076           1 :         ZERO_STRUCT(break_info);
    1077           1 :         status = smb2_util_unlink(tree2, fname);
    1078           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1079             : 
    1080           1 :         torture_wait_for_oplock_break(tctx);
    1081           1 :         CHECK_VAL(break_info.count, 1);
    1082           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    1083           1 :         CHECK_VAL(break_info.level, 1);
    1084           1 :         CHECK_VAL(break_info.failures, 0);
    1085             : 
    1086           1 :         smb2_util_close(tree1, h1);
    1087           1 :         smb2_util_close(tree1, h);
    1088             : 
    1089           1 :         smb2_deltree(tree1, BASEDIR);
    1090           1 :         return ret;
    1091             : }
    1092             : 
    1093           1 : static bool test_smb2_oplock_batch4(struct torture_context *tctx,
    1094             :                                     struct smb2_tree *tree1,
    1095             :                                     struct smb2_tree *tree2)
    1096             : {
    1097           1 :         const char *fname = BASEDIR "\\test_batch4.dat";
    1098             :         NTSTATUS status;
    1099           1 :         bool ret = true;
    1100             :         union smb_open io;
    1101             :         struct smb2_read r;
    1102             :         struct smb2_handle h, h1;
    1103             : 
    1104           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1105           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1106             : 
    1107             :         /* cleanup */
    1108           1 :         smb2_util_unlink(tree1, fname);
    1109             : 
    1110           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1111           1 :         tree1->session->transport->oplock.private_data = tree1;
    1112             : 
    1113             :         /*
    1114             :           base ntcreatex parms
    1115             :         */
    1116           1 :         ZERO_STRUCT(io.smb2);
    1117           1 :         io.generic.level = RAW_OPEN_SMB2;
    1118           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1119           1 :         io.smb2.in.alloc_size = 0;
    1120           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1121           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1122           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1123           1 :         io.smb2.in.create_options = 0;
    1124           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1125           1 :         io.smb2.in.security_flags = 0;
    1126           1 :         io.smb2.in.fname = fname;
    1127             : 
    1128           1 :         torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
    1129           1 :         ZERO_STRUCT(break_info);
    1130             : 
    1131           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1132           1 :         tree1->session->transport->oplock.private_data = tree1;
    1133             : 
    1134           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1135           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1136           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1137           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1138           1 :         h1 = io.smb2.out.file.handle;
    1139           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1140             : 
    1141           1 :         ZERO_STRUCT(r);
    1142           1 :         r.in.file.handle = h1;
    1143           1 :         r.in.offset      = 0;
    1144             : 
    1145           1 :         status = smb2_read(tree1, tree1, &r);
    1146           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1147           1 :         torture_wait_for_oplock_break(tctx);
    1148           1 :         CHECK_VAL(break_info.count, 0);
    1149           1 :         CHECK_VAL(break_info.failures, 0);
    1150             : 
    1151           1 :         smb2_util_close(tree1, h1);
    1152           1 :         smb2_util_close(tree1, h);
    1153             : 
    1154           1 :         smb2_deltree(tree1, BASEDIR);
    1155           1 :         return ret;
    1156             : }
    1157             : 
    1158           1 : static bool test_smb2_oplock_batch5(struct torture_context *tctx,
    1159             :                                     struct smb2_tree *tree1,
    1160             :                                     struct smb2_tree *tree2)
    1161             : {
    1162           1 :         const char *fname = BASEDIR "\\test_batch5.dat";
    1163             :         NTSTATUS status;
    1164           1 :         bool ret = true;
    1165             :         union smb_open io;
    1166             :         struct smb2_handle h, h1;
    1167             : 
    1168           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1169           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1170             : 
    1171             :         /* cleanup */
    1172           1 :         smb2_util_unlink(tree1, fname);
    1173             : 
    1174           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1175           1 :         tree1->session->transport->oplock.private_data = tree1;
    1176             : 
    1177             :         /*
    1178             :           base ntcreatex parms
    1179             :         */
    1180           1 :         ZERO_STRUCT(io.smb2);
    1181           1 :         io.generic.level = RAW_OPEN_SMB2;
    1182           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1183           1 :         io.smb2.in.alloc_size = 0;
    1184           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1185           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1186           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1187           1 :         io.smb2.in.create_options = 0;
    1188           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1189           1 :         io.smb2.in.security_flags = 0;
    1190           1 :         io.smb2.in.fname = fname;
    1191             : 
    1192           1 :         torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
    1193           1 :         ZERO_STRUCT(break_info);
    1194             : 
    1195           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1196           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1197           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1198           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1199           1 :         h1 = io.smb2.out.file.handle;
    1200           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1201             : 
    1202           1 :         ZERO_STRUCT(break_info);
    1203             : 
    1204           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1205           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1206           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
    1207             :                                       "Incorrect status");
    1208             : 
    1209           1 :         torture_wait_for_oplock_break(tctx);
    1210           1 :         CHECK_VAL(break_info.count, 1);
    1211           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    1212           1 :         CHECK_VAL(break_info.level, 1);
    1213           1 :         CHECK_VAL(break_info.failures, 0);
    1214             : 
    1215           1 :         smb2_util_close(tree1, h1);
    1216           1 :         smb2_util_close(tree1, h);
    1217             : 
    1218           1 :         smb2_deltree(tree1, BASEDIR);
    1219           1 :         return ret;
    1220             : }
    1221             : 
    1222           1 : static bool test_smb2_oplock_batch6(struct torture_context *tctx,
    1223             :                                     struct smb2_tree *tree1,
    1224             :                                     struct smb2_tree *tree2)
    1225             : {
    1226           1 :         const char *fname = BASEDIR "\\test_batch6.dat";
    1227             :         NTSTATUS status;
    1228           1 :         bool ret = true;
    1229             :         union smb_open io;
    1230             :         struct smb2_handle h, h1, h2;
    1231           1 :         char c = 0;
    1232             : 
    1233           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1234           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1235             : 
    1236             :         /* cleanup */
    1237           1 :         smb2_util_unlink(tree1, fname);
    1238             : 
    1239           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1240           1 :         tree1->session->transport->oplock.private_data = tree1;
    1241             : 
    1242             :         /*
    1243             :           base ntcreatex parms
    1244             :         */
    1245           1 :         ZERO_STRUCT(io.smb2);
    1246           1 :         io.generic.level = RAW_OPEN_SMB2;
    1247           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1248           1 :         io.smb2.in.alloc_size = 0;
    1249           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1250           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1251           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1252           1 :         io.smb2.in.create_options = 0;
    1253           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1254           1 :         io.smb2.in.security_flags = 0;
    1255           1 :         io.smb2.in.fname = fname;
    1256             : 
    1257           1 :         torture_comment(tctx, "BATCH6: a 2nd open should give a break to "
    1258             :                         "level II if the first open allowed shared read\n");
    1259           1 :         ZERO_STRUCT(break_info);
    1260           1 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    1261           1 :         tree2->session->transport->oplock.private_data = tree2;
    1262             : 
    1263           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    1264             :                                 SEC_RIGHTS_FILE_WRITE;
    1265           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1266             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1267           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1268           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1269           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1270           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1271           1 :         h1 = io.smb2.out.file.handle;
    1272           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1273             : 
    1274           1 :         ZERO_STRUCT(break_info);
    1275             : 
    1276           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1277           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1278           1 :         h2 = io.smb2.out.file.handle;
    1279           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    1280             : 
    1281           1 :         torture_wait_for_oplock_break(tctx);
    1282           1 :         CHECK_VAL(break_info.count, 1);
    1283           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    1284           1 :         CHECK_VAL(break_info.level, 1);
    1285           1 :         CHECK_VAL(break_info.failures, 0);
    1286           1 :         ZERO_STRUCT(break_info);
    1287             : 
    1288           1 :         torture_comment(tctx, "write should trigger a break to none on both\n");
    1289           1 :         tree1->session->transport->oplock.handler =
    1290             :             torture_oplock_handler_level2_to_none;
    1291           1 :         tree2->session->transport->oplock.handler =
    1292             :             torture_oplock_handler_level2_to_none;
    1293           1 :         smb2_util_write(tree1, h1, &c, 0, 1);
    1294             : 
    1295             :         /* We expect two breaks */
    1296           1 :         torture_wait_for_oplock_break(tctx);
    1297           1 :         torture_wait_for_oplock_break(tctx);
    1298             : 
    1299           1 :         CHECK_VAL(break_info.count, 2);
    1300           1 :         CHECK_VAL(break_info.level, 0);
    1301           1 :         CHECK_VAL(break_info.failures, 0);
    1302             : 
    1303           1 :         smb2_util_close(tree1, h1);
    1304           1 :         smb2_util_close(tree2, h2);
    1305           1 :         smb2_util_close(tree1, h);
    1306             : 
    1307           1 :         smb2_deltree(tree1, BASEDIR);
    1308           1 :         return ret;
    1309             : }
    1310             : 
    1311           1 : static bool test_smb2_oplock_batch7(struct torture_context *tctx,
    1312             :                                     struct smb2_tree *tree1,
    1313             :                                     struct smb2_tree *tree2)
    1314             : {
    1315           1 :         const char *fname = BASEDIR "\\test_batch7.dat";
    1316             :         NTSTATUS status;
    1317           1 :         bool ret = true;
    1318             :         union smb_open io;
    1319             :         struct smb2_handle h, h1, h2;
    1320             : 
    1321           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1322           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1323             : 
    1324             :         /* cleanup */
    1325           1 :         smb2_util_unlink(tree1, fname);
    1326             : 
    1327           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1328           1 :         tree1->session->transport->oplock.private_data = tree1;
    1329             : 
    1330             :         /*
    1331             :           base ntcreatex parms
    1332             :         */
    1333           1 :         ZERO_STRUCT(io.smb2);
    1334           1 :         io.generic.level = RAW_OPEN_SMB2;
    1335           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1336           1 :         io.smb2.in.alloc_size = 0;
    1337           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1338           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1339           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1340           1 :         io.smb2.in.create_options = 0;
    1341           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1342           1 :         io.smb2.in.security_flags = 0;
    1343           1 :         io.smb2.in.fname = fname;
    1344             : 
    1345           1 :         torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when "
    1346             :                         "we close instead of ack\n");
    1347           1 :         ZERO_STRUCT(break_info);
    1348           1 :         tree1->session->transport->oplock.handler =
    1349             :                         torture_oplock_handler_close;
    1350           1 :         tree1->session->transport->oplock.private_data = tree1;
    1351             : 
    1352           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1353           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1354           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1355           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1356           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1357           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1358           1 :         h2 = io.smb2.out.file.handle;
    1359           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1360             : 
    1361           1 :         ZERO_STRUCT(break_info);
    1362             : 
    1363           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1364           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1365           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1366           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1367           1 :         h1 = io.smb2.out.file.handle;
    1368           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1369             : 
    1370           1 :         torture_wait_for_oplock_break(tctx);
    1371           1 :         CHECK_VAL(break_info.count, 1);
    1372           1 :         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
    1373           1 :         CHECK_VAL(break_info.level, 1);
    1374           1 :         CHECK_VAL(break_info.failures, 0);
    1375             : 
    1376           1 :         smb2_util_close(tree2, h1);
    1377           1 :         smb2_util_close(tree2, h);
    1378             : 
    1379           1 :         smb2_deltree(tree1, BASEDIR);
    1380           1 :         return ret;
    1381             : }
    1382             : 
    1383           1 : static bool test_smb2_oplock_batch8(struct torture_context *tctx,
    1384             :                                     struct smb2_tree *tree1,
    1385             :                                     struct smb2_tree *tree2)
    1386             : {
    1387           1 :         const char *fname = BASEDIR "\\test_batch8.dat";
    1388             :         NTSTATUS status;
    1389           1 :         bool ret = true;
    1390             :         union smb_open io;
    1391             :         struct smb2_handle h, h1, h2;
    1392             : 
    1393           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1394           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1395             : 
    1396             :         /* cleanup */
    1397           1 :         smb2_util_unlink(tree1, fname);
    1398             : 
    1399           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1400           1 :         tree1->session->transport->oplock.private_data = tree1;
    1401             : 
    1402             :         /*
    1403             :           base ntcreatex parms
    1404             :         */
    1405           1 :         ZERO_STRUCT(io.smb2);
    1406           1 :         io.generic.level = RAW_OPEN_SMB2;
    1407           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1408           1 :         io.smb2.in.alloc_size = 0;
    1409           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1410           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1411           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1412           1 :         io.smb2.in.create_options = 0;
    1413           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1414           1 :         io.smb2.in.security_flags = 0;
    1415           1 :         io.smb2.in.fname = fname;
    1416             : 
    1417           1 :         torture_comment(tctx, "BATCH8: open with batch oplock\n");
    1418           1 :         ZERO_STRUCT(break_info);
    1419             : 
    1420           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1421           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1422           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1423           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1424           1 :         h1 = io.smb2.out.file.handle;
    1425           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1426             : 
    1427           1 :         ZERO_STRUCT(break_info);
    1428           1 :         torture_comment(tctx, "second open with attributes only shouldn't "
    1429             :                         "cause oplock break\n");
    1430             : 
    1431           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1432           1 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    1433             :                                 SEC_FILE_WRITE_ATTRIBUTE |
    1434             :                                 SEC_STD_SYNCHRONIZE;
    1435           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1436           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1437           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1438           1 :         h2 = io.smb2.out.file.handle;
    1439           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
    1440           1 :         torture_wait_for_oplock_break(tctx);
    1441           1 :         CHECK_VAL(break_info.count, 0);
    1442           1 :         CHECK_VAL(break_info.failures, 0);
    1443             : 
    1444           1 :         smb2_util_close(tree1, h1);
    1445           1 :         smb2_util_close(tree2, h2);
    1446           1 :         smb2_util_close(tree1, h);
    1447             : 
    1448           1 :         smb2_deltree(tree1, BASEDIR);
    1449           1 :         return ret;
    1450             : }
    1451             : 
    1452           1 : static bool test_smb2_oplock_batch9(struct torture_context *tctx,
    1453             :                                      struct smb2_tree *tree1,
    1454             :                                      struct smb2_tree *tree2)
    1455             : {
    1456           1 :         const char *fname = BASEDIR "\\test_batch9.dat";
    1457             :         NTSTATUS status;
    1458           1 :         bool ret = true;
    1459             :         union smb_open io;
    1460             :         struct smb2_handle h, h1, h2;
    1461           1 :         char c = 0;
    1462             : 
    1463           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1464           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1465             : 
    1466             :         /* cleanup */
    1467           1 :         smb2_util_unlink(tree1, fname);
    1468             : 
    1469           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1470           1 :         tree1->session->transport->oplock.private_data = tree1;
    1471             : 
    1472             :         /*
    1473             :           base ntcreatex parms
    1474             :         */
    1475           1 :         ZERO_STRUCT(io.smb2);
    1476           1 :         io.generic.level = RAW_OPEN_SMB2;
    1477           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1478           1 :         io.smb2.in.alloc_size = 0;
    1479           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1480           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1481           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1482           1 :         io.smb2.in.create_options = 0;
    1483           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1484           1 :         io.smb2.in.security_flags = 0;
    1485           1 :         io.smb2.in.fname = fname;
    1486             : 
    1487           1 :         torture_comment(tctx, "BATCH9: open with attributes only can create "
    1488             :                         "file\n");
    1489             : 
    1490           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1491           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1492           1 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    1493             :                                 SEC_FILE_WRITE_ATTRIBUTE |
    1494             :                                 SEC_STD_SYNCHRONIZE;
    1495           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1496           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1497           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1498           1 :         h1 = io.smb2.out.file.handle;
    1499           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1500             : 
    1501           1 :         torture_comment(tctx, "Subsequent normal open should break oplock on "
    1502             :                         "attribute only open to level II\n");
    1503             : 
    1504           1 :         ZERO_STRUCT(break_info);
    1505             : 
    1506           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1507           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1508           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1509           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1510           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1511           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1512           1 :         h2 = io.smb2.out.file.handle;
    1513           1 :         torture_wait_for_oplock_break(tctx);
    1514           1 :         CHECK_VAL(break_info.count, 1);
    1515           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    1516           1 :         CHECK_VAL(break_info.failures, 0);
    1517           1 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    1518           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    1519           1 :         smb2_util_close(tree2, h2);
    1520             : 
    1521           1 :         torture_comment(tctx, "third oplocked open should grant level2 without "
    1522             :                         "break\n");
    1523           1 :         ZERO_STRUCT(break_info);
    1524             : 
    1525           1 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    1526           1 :         tree2->session->transport->oplock.private_data = tree2;
    1527             : 
    1528           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1529           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1530           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1531           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1532           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1533           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1534           1 :         h2 = io.smb2.out.file.handle;
    1535           1 :         torture_wait_for_oplock_break(tctx);
    1536           1 :         CHECK_VAL(break_info.count, 0);
    1537           1 :         CHECK_VAL(break_info.failures, 0);
    1538           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    1539             : 
    1540           1 :         ZERO_STRUCT(break_info);
    1541             : 
    1542           1 :         torture_comment(tctx, "write should trigger a break to none on both\n");
    1543           1 :         tree1->session->transport->oplock.handler =
    1544             :             torture_oplock_handler_level2_to_none;
    1545           1 :         tree2->session->transport->oplock.handler =
    1546             :             torture_oplock_handler_level2_to_none;
    1547           1 :         smb2_util_write(tree2, h2, &c, 0, 1);
    1548             : 
    1549             :         /* We expect two breaks */
    1550           1 :         torture_wait_for_oplock_break(tctx);
    1551           1 :         torture_wait_for_oplock_break(tctx);
    1552             : 
    1553           1 :         CHECK_VAL(break_info.count, 2);
    1554           1 :         CHECK_VAL(break_info.level, 0);
    1555           1 :         CHECK_VAL(break_info.failures, 0);
    1556             : 
    1557           1 :         smb2_util_close(tree1, h1);
    1558           1 :         smb2_util_close(tree2, h2);
    1559           1 :         smb2_util_close(tree1, h);
    1560             : 
    1561           1 :         smb2_deltree(tree1, BASEDIR);
    1562           1 :         return ret;
    1563             : }
    1564             : 
    1565           1 : static bool test_smb2_oplock_batch9a(struct torture_context *tctx,
    1566             :                                      struct smb2_tree *tree1,
    1567             :                                      struct smb2_tree *tree2)
    1568             : {
    1569           1 :         const char *fname = BASEDIR "\\test_batch9a.dat";
    1570             :         NTSTATUS status;
    1571           1 :         bool ret = true;
    1572             :         union smb_open io;
    1573             :         struct smb2_handle h, h1, h2, h3;
    1574           1 :         char c = 0;
    1575             : 
    1576           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1577           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1578             : 
    1579             :         /* cleanup */
    1580           1 :         smb2_util_unlink(tree1, fname);
    1581             : 
    1582           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1583           1 :         tree1->session->transport->oplock.private_data = tree1;
    1584             : 
    1585             :         /*
    1586             :           base ntcreatex parms
    1587             :         */
    1588           1 :         ZERO_STRUCT(io.smb2);
    1589           1 :         io.generic.level = RAW_OPEN_SMB2;
    1590           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1591           1 :         io.smb2.in.alloc_size = 0;
    1592           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1593           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1594           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1595           1 :         io.smb2.in.create_options = 0;
    1596           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1597           1 :         io.smb2.in.security_flags = 0;
    1598           1 :         io.smb2.in.fname = fname;
    1599             : 
    1600           1 :         torture_comment(tctx, "BATCH9: open with attributes only can create "
    1601             :                         "file\n");
    1602             : 
    1603           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1604           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1605           1 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    1606             :                                 SEC_FILE_WRITE_ATTRIBUTE |
    1607             :                                 SEC_STD_SYNCHRONIZE;
    1608           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1609           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating the file");
    1610           1 :         h1 = io.smb2.out.file.handle;
    1611           1 :         CHECK_VAL(io.smb2.out.create_action, FILE_WAS_CREATED);
    1612           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1613             : 
    1614           1 :         torture_comment(tctx, "Subsequent attributes open should not break\n");
    1615             : 
    1616           1 :         ZERO_STRUCT(break_info);
    1617             : 
    1618           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1619           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1620           1 :         h3 = io.smb2.out.file.handle;
    1621           1 :         torture_wait_for_oplock_break(tctx);
    1622           1 :         CHECK_VAL(break_info.count, 0);
    1623           1 :         CHECK_VAL(io.smb2.out.create_action, FILE_WAS_OPENED);
    1624           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
    1625           1 :         smb2_util_close(tree2, h3);
    1626             : 
    1627           1 :         torture_comment(tctx, "Subsequent normal open should break oplock on "
    1628             :                         "attribute only open to level II\n");
    1629             : 
    1630           1 :         ZERO_STRUCT(break_info);
    1631             : 
    1632           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1633           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1634           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1635           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1636           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1637           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1638           1 :         h2 = io.smb2.out.file.handle;
    1639           1 :         torture_wait_for_oplock_break(tctx);
    1640           1 :         CHECK_VAL(break_info.count, 1);
    1641           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    1642           1 :         CHECK_VAL(break_info.failures, 0);
    1643           1 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    1644           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    1645           1 :         smb2_util_close(tree2, h2);
    1646             : 
    1647           1 :         torture_comment(tctx, "third oplocked open should grant level2 without "
    1648             :                         "break\n");
    1649           1 :         ZERO_STRUCT(break_info);
    1650             : 
    1651           1 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    1652           1 :         tree2->session->transport->oplock.private_data = tree2;
    1653             : 
    1654           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1655           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1656           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1657           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1658           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1659           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1660           1 :         h2 = io.smb2.out.file.handle;
    1661           1 :         torture_wait_for_oplock_break(tctx);
    1662           1 :         CHECK_VAL(break_info.count, 0);
    1663           1 :         CHECK_VAL(break_info.failures, 0);
    1664           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    1665             : 
    1666           1 :         ZERO_STRUCT(break_info);
    1667             : 
    1668           1 :         torture_comment(tctx, "write should trigger a break to none on both\n");
    1669           1 :         tree1->session->transport->oplock.handler =
    1670             :             torture_oplock_handler_level2_to_none;
    1671           1 :         tree2->session->transport->oplock.handler =
    1672             :             torture_oplock_handler_level2_to_none;
    1673           1 :         smb2_util_write(tree2, h2, &c, 0, 1);
    1674             : 
    1675             :         /* We expect two breaks */
    1676           1 :         torture_wait_for_oplock_break(tctx);
    1677           1 :         torture_wait_for_oplock_break(tctx);
    1678             : 
    1679           1 :         CHECK_VAL(break_info.count, 2);
    1680           1 :         CHECK_VAL(break_info.level, 0);
    1681           1 :         CHECK_VAL(break_info.failures, 0);
    1682             : 
    1683           1 :         smb2_util_close(tree1, h1);
    1684           1 :         smb2_util_close(tree2, h2);
    1685           1 :         smb2_util_close(tree1, h);
    1686             : 
    1687           1 :         smb2_deltree(tree1, BASEDIR);
    1688           1 :         return ret;
    1689             : }
    1690             : 
    1691             : 
    1692           1 : static bool test_smb2_oplock_batch10(struct torture_context *tctx,
    1693             :                                      struct smb2_tree *tree1,
    1694             :                                      struct smb2_tree *tree2)
    1695             : {
    1696           1 :         const char *fname = BASEDIR "\\test_batch10.dat";
    1697             :         NTSTATUS status;
    1698           1 :         bool ret = true;
    1699             :         union smb_open io;
    1700             :         struct smb2_handle h, h1, h2;
    1701             : 
    1702           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1703           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1704             : 
    1705             :         /* cleanup */
    1706           1 :         smb2_util_unlink(tree1, fname);
    1707             : 
    1708           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1709           1 :         tree1->session->transport->oplock.private_data = tree1;
    1710             : 
    1711             :         /*
    1712             :           base ntcreatex parms
    1713             :         */
    1714           1 :         ZERO_STRUCT(io.smb2);
    1715           1 :         io.generic.level = RAW_OPEN_SMB2;
    1716           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1717           1 :         io.smb2.in.alloc_size = 0;
    1718           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1719           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1720           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1721           1 :         io.smb2.in.create_options = 0;
    1722           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1723           1 :         io.smb2.in.security_flags = 0;
    1724           1 :         io.smb2.in.fname = fname;
    1725             : 
    1726           1 :         torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock "
    1727             :                         "open should grant level2\n");
    1728           1 :         ZERO_STRUCT(break_info);
    1729           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1730           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1731           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1732             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1733             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1734           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1735           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1736           1 :         h1 = io.smb2.out.file.handle;
    1737           1 :         torture_wait_for_oplock_break(tctx);
    1738           1 :         CHECK_VAL(break_info.count, 0);
    1739           1 :         CHECK_VAL(break_info.failures, 0);
    1740           1 :         CHECK_VAL(io.smb2.out.oplock_level, 0);
    1741             : 
    1742           1 :         tree2->session->transport->oplock.handler =
    1743             :             torture_oplock_handler_level2_to_none;
    1744           1 :         tree2->session->transport->oplock.private_data = tree2;
    1745             : 
    1746           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1747           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1748           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1749           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1750             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1751             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1752           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1753           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    1754           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1755           1 :         h2 = io.smb2.out.file.handle;
    1756           1 :         torture_wait_for_oplock_break(tctx);
    1757           1 :         CHECK_VAL(break_info.count, 0);
    1758           1 :         CHECK_VAL(break_info.failures, 0);
    1759           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    1760             : 
    1761           1 :         torture_comment(tctx, "write should trigger a break to none\n");
    1762             :         {
    1763             :                 struct smb2_write wr;
    1764             :                 DATA_BLOB data;
    1765           1 :                 data = data_blob_talloc_zero(tree1, UINT16_MAX);
    1766           1 :                 data.data[0] = (const uint8_t)'x';
    1767           1 :                 ZERO_STRUCT(wr);
    1768           1 :                 wr.in.file.handle = h1;
    1769           1 :                 wr.in.offset      = 0;
    1770           1 :                 wr.in.data        = data;
    1771           1 :                 status = smb2_write(tree1, &wr);
    1772           1 :                 torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1773             :         }
    1774             : 
    1775           1 :         torture_wait_for_oplock_break(tctx);
    1776             : 
    1777           1 :         CHECK_VAL(break_info.count, 1);
    1778           1 :         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
    1779           1 :         CHECK_VAL(break_info.level, 0);
    1780           1 :         CHECK_VAL(break_info.failures, 0);
    1781             : 
    1782           1 :         smb2_util_close(tree1, h1);
    1783           1 :         smb2_util_close(tree2, h2);
    1784           1 :         smb2_util_close(tree1, h);
    1785             : 
    1786           1 :         smb2_deltree(tree1, BASEDIR);
    1787           1 :         return ret;
    1788             : }
    1789             : 
    1790           1 : static bool test_smb2_oplock_batch11(struct torture_context *tctx,
    1791             :                                      struct smb2_tree *tree1,
    1792             :                                      struct smb2_tree *tree2)
    1793             : {
    1794           1 :         const char *fname = BASEDIR "\\test_batch11.dat";
    1795             :         NTSTATUS status;
    1796           1 :         bool ret = true;
    1797             :         union smb_open io;
    1798             :         union smb_setfileinfo sfi;
    1799             :         struct smb2_handle h, h1;
    1800             : 
    1801           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1802           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1803             : 
    1804             :         /* cleanup */
    1805           1 :         smb2_util_unlink(tree1, fname);
    1806             : 
    1807           1 :         tree1->session->transport->oplock.handler =
    1808             :             torture_oplock_handler_two_notifications;
    1809           1 :         tree1->session->transport->oplock.private_data = tree1;
    1810             : 
    1811             :         /*
    1812             :           base ntcreatex parms
    1813             :         */
    1814           1 :         ZERO_STRUCT(io.smb2);
    1815           1 :         io.generic.level = RAW_OPEN_SMB2;
    1816           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1817           1 :         io.smb2.in.alloc_size = 0;
    1818           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1819           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1820           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1821           1 :         io.smb2.in.create_options = 0;
    1822           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1823           1 :         io.smb2.in.security_flags = 0;
    1824           1 :         io.smb2.in.fname = fname;
    1825             : 
    1826             :         /* Test if a set-eof on pathname breaks an exclusive oplock. */
    1827           1 :         torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks "
    1828             :                         "oplocks.\n");
    1829             : 
    1830           1 :         ZERO_STRUCT(break_info);
    1831             : 
    1832           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1833           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1834           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1835           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1836             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    1837             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1838           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1839           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1840           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1841           1 :         h1 = io.smb2.out.file.handle;
    1842           1 :         torture_wait_for_oplock_break(tctx);
    1843           1 :         CHECK_VAL(break_info.count, 0);
    1844           1 :         CHECK_VAL(break_info.failures, 0);
    1845           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1846             : 
    1847           1 :         ZERO_STRUCT(sfi);
    1848           1 :         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
    1849           1 :         sfi.generic.in.file.path = fname;
    1850           1 :         sfi.end_of_file_info.in.size = 100;
    1851             : 
    1852           1 :         status = smb2_composite_setpathinfo(tree2, &sfi);
    1853           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1854             : 
    1855             :         /* We expect two breaks */
    1856           1 :         torture_wait_for_oplock_break(tctx);
    1857           1 :         torture_wait_for_oplock_break(tctx);
    1858             : 
    1859           1 :         CHECK_VAL(break_info.count, 2);
    1860           1 :         CHECK_VAL(break_info.failures, 0);
    1861           1 :         CHECK_VAL(break_info.level, 0);
    1862             : 
    1863           1 :         smb2_util_close(tree1, h1);
    1864           1 :         smb2_util_close(tree1, h);
    1865             : 
    1866           1 :         smb2_deltree(tree1, BASEDIR);
    1867           1 :         return ret;
    1868             : }
    1869             : 
    1870           1 : static bool test_smb2_oplock_batch12(struct torture_context *tctx,
    1871             :                                      struct smb2_tree *tree1,
    1872             :                                      struct smb2_tree *tree2)
    1873             : {
    1874           1 :         const char *fname = BASEDIR "\\test_batch12.dat";
    1875             :         NTSTATUS status;
    1876           1 :         bool ret = true;
    1877             :         union smb_open io;
    1878             :         union smb_setfileinfo sfi;
    1879             :         struct smb2_handle h, h1;
    1880             : 
    1881           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1882           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1883             : 
    1884             :         /* cleanup */
    1885           1 :         smb2_util_unlink(tree1, fname);
    1886             : 
    1887           1 :         tree1->session->transport->oplock.handler =
    1888             :             torture_oplock_handler_two_notifications;
    1889           1 :         tree1->session->transport->oplock.private_data = tree1;
    1890             : 
    1891             :         /*
    1892             :           base ntcreatex parms
    1893             :         */
    1894           1 :         ZERO_STRUCT(io.smb2);
    1895           1 :         io.generic.level = RAW_OPEN_SMB2;
    1896           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1897           1 :         io.smb2.in.alloc_size = 0;
    1898           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1899           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1900           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1901           1 :         io.smb2.in.create_options = 0;
    1902           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1903           1 :         io.smb2.in.security_flags = 0;
    1904           1 :         io.smb2.in.fname = fname;
    1905             : 
    1906             :         /* Test if a set-allocation size on pathname breaks an exclusive
    1907             :          * oplock. */
    1908           1 :         torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size "
    1909             :                         "breaks oplocks.\n");
    1910             : 
    1911           1 :         ZERO_STRUCT(break_info);
    1912             : 
    1913           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1914           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1915           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1916           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1917             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    1918             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1919           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1920           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1921           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1922           1 :         h1 = io.smb2.out.file.handle;
    1923           1 :         torture_wait_for_oplock_break(tctx);
    1924           1 :         CHECK_VAL(break_info.count, 0);
    1925           1 :         CHECK_VAL(break_info.failures, 0);
    1926           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1927             : 
    1928           1 :         ZERO_STRUCT(sfi);
    1929           1 :         sfi.generic.level = RAW_SFILEINFO_ALLOCATION_INFORMATION;
    1930           1 :         sfi.generic.in.file.path = fname;
    1931           1 :         sfi.allocation_info.in.alloc_size = 65536 * 8;
    1932             : 
    1933           1 :         status = smb2_composite_setpathinfo(tree2, &sfi);
    1934           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    1935             : 
    1936             :         /* We expect two breaks */
    1937           1 :         torture_wait_for_oplock_break(tctx);
    1938           1 :         torture_wait_for_oplock_break(tctx);
    1939             : 
    1940           1 :         CHECK_VAL(break_info.count, 2);
    1941           1 :         CHECK_VAL(break_info.failures, 0);
    1942           1 :         CHECK_VAL(break_info.level, 0);
    1943             : 
    1944           1 :         smb2_util_close(tree1, h1);
    1945           1 :         smb2_util_close(tree1, h);
    1946             : 
    1947           1 :         smb2_deltree(tree1, BASEDIR);
    1948           1 :         return ret;
    1949             : }
    1950             : 
    1951           1 : static bool test_smb2_oplock_batch13(struct torture_context *tctx,
    1952             :                                      struct smb2_tree *tree1,
    1953             :                                      struct smb2_tree *tree2)
    1954             : {
    1955           1 :         const char *fname = BASEDIR "\\test_batch13.dat";
    1956             :         NTSTATUS status;
    1957           1 :         bool ret = true;
    1958             :         union smb_open io;
    1959             :         struct smb2_handle h, h1, h2;
    1960             : 
    1961           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    1962           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    1963             : 
    1964             :         /* cleanup */
    1965           1 :         smb2_util_unlink(tree1, fname);
    1966             : 
    1967           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    1968           1 :         tree1->session->transport->oplock.private_data = tree1;
    1969             : 
    1970           1 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    1971           1 :         tree2->session->transport->oplock.private_data = tree2;
    1972             : 
    1973             :         /*
    1974             :           base ntcreatex parms
    1975             :         */
    1976           1 :         ZERO_STRUCT(io.smb2);
    1977           1 :         io.generic.level = RAW_OPEN_SMB2;
    1978           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1979           1 :         io.smb2.in.alloc_size = 0;
    1980           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1981           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1982           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1983           1 :         io.smb2.in.create_options = 0;
    1984           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1985           1 :         io.smb2.in.security_flags = 0;
    1986           1 :         io.smb2.in.fname = fname;
    1987             : 
    1988           1 :         torture_comment(tctx, "BATCH13: open with batch oplock\n");
    1989           1 :         ZERO_STRUCT(break_info);
    1990             : 
    1991           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1992           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    1993           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1994             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1995             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1996           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    1997           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    1998           1 :         h1 = io.smb2.out.file.handle;
    1999           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2000             : 
    2001           1 :         ZERO_STRUCT(break_info);
    2002             : 
    2003           1 :         torture_comment(tctx, "second open with attributes only and "
    2004             :                         "NTCREATEX_DISP_OVERWRITE dispostion causes "
    2005             :                         "oplock break\n");
    2006             : 
    2007           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2008           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2009           1 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    2010             :                                 SEC_FILE_WRITE_ATTRIBUTE |
    2011             :                                 SEC_STD_SYNCHRONIZE;
    2012           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2013             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    2014             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    2015           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
    2016           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2017           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2018           1 :         h2 = io.smb2.out.file.handle;
    2019           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2020           1 :         torture_wait_for_oplock_break(tctx);
    2021           1 :         CHECK_VAL(break_info.count, 1);
    2022           1 :         CHECK_VAL(break_info.failures, 0);
    2023             : 
    2024           1 :         smb2_util_close(tree1, h1);
    2025           1 :         smb2_util_close(tree2, h2);
    2026           1 :         smb2_util_close(tree1, h);
    2027             : 
    2028           1 :         smb2_deltree(tree1, BASEDIR);
    2029             : 
    2030           1 :         return ret;
    2031             : }
    2032             : 
    2033           1 : static bool test_smb2_oplock_batch14(struct torture_context *tctx,
    2034             :                                      struct smb2_tree *tree1,
    2035             :                                      struct smb2_tree *tree2)
    2036             : {
    2037           1 :         const char *fname = BASEDIR "\\test_batch14.dat";
    2038             :         NTSTATUS status;
    2039           1 :         bool ret = true;
    2040             :         union smb_open io;
    2041             :         struct smb2_handle h, h1, h2;
    2042             : 
    2043           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2044           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2045             : 
    2046             :         /* cleanup */
    2047           1 :         smb2_util_unlink(tree1, fname);
    2048             : 
    2049           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2050           1 :         tree1->session->transport->oplock.private_data = tree1;
    2051             : 
    2052             :         /*
    2053             :           base ntcreatex parms
    2054             :         */
    2055           1 :         ZERO_STRUCT(io.smb2);
    2056           1 :         io.generic.level = RAW_OPEN_SMB2;
    2057           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2058           1 :         io.smb2.in.alloc_size = 0;
    2059           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2060           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2061           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2062           1 :         io.smb2.in.create_options = 0;
    2063           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2064           1 :         io.smb2.in.security_flags = 0;
    2065           1 :         io.smb2.in.fname = fname;
    2066             : 
    2067           1 :         torture_comment(tctx, "BATCH14: open with batch oplock\n");
    2068           1 :         ZERO_STRUCT(break_info);
    2069             : 
    2070           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2071           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2072           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2073             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    2074             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    2075           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2076           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2077           1 :         h1 = io.smb2.out.file.handle;
    2078           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2079             : 
    2080           1 :         ZERO_STRUCT(break_info);
    2081             : 
    2082           1 :         torture_comment(tctx, "second open with attributes only and "
    2083             :                         "NTCREATEX_DISP_SUPERSEDE dispostion causes "
    2084             :                         "oplock break\n");
    2085             : 
    2086           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2087           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2088           1 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    2089             :                                 SEC_FILE_WRITE_ATTRIBUTE |
    2090             :                                 SEC_STD_SYNCHRONIZE;
    2091           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2092             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    2093             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    2094           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
    2095           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2096           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2097           1 :         h2 = io.smb2.out.file.handle;
    2098           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2099             : 
    2100           1 :         torture_wait_for_oplock_break(tctx);
    2101           1 :         CHECK_VAL(break_info.count, 1);
    2102           1 :         CHECK_VAL(break_info.failures, 0);
    2103             : 
    2104           1 :         smb2_util_close(tree1, h1);
    2105           1 :         smb2_util_close(tree2, h2);
    2106           1 :         smb2_util_close(tree1, h);
    2107             : 
    2108           1 :         smb2_deltree(tree1, BASEDIR);
    2109           1 :         return ret;
    2110             : }
    2111             : 
    2112           1 : static bool test_smb2_oplock_batch15(struct torture_context *tctx,
    2113             :                                      struct smb2_tree *tree1,
    2114             :                                      struct smb2_tree *tree2)
    2115             : {
    2116           1 :         const char *fname = BASEDIR "\\test_batch15.dat";
    2117             :         NTSTATUS status;
    2118           1 :         bool ret = true;
    2119             :         union smb_open io;
    2120             :         union smb_fileinfo qfi;
    2121             :         struct smb2_handle h, h1;
    2122             : 
    2123           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2124           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2125             : 
    2126             :         /* cleanup */
    2127           1 :         smb2_util_unlink(tree1, fname);
    2128             : 
    2129           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2130           1 :         tree1->session->transport->oplock.private_data = tree1;
    2131             : 
    2132             :         /*
    2133             :           base ntcreatex parms
    2134             :         */
    2135           1 :         ZERO_STRUCT(io.smb2);
    2136           1 :         io.generic.level = RAW_OPEN_SMB2;
    2137           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2138           1 :         io.smb2.in.alloc_size = 0;
    2139           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2140           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2141           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2142           1 :         io.smb2.in.create_options = 0;
    2143           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2144           1 :         io.smb2.in.security_flags = 0;
    2145           1 :         io.smb2.in.fname = fname;
    2146             : 
    2147             :         /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
    2148           1 :         torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks "
    2149             :                         "a batch oplock (should not).\n");
    2150             : 
    2151           1 :         ZERO_STRUCT(break_info);
    2152             : 
    2153           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2154           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2155           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2156           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2157             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    2158             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    2159           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    2160           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2161           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2162           1 :         h1 = io.smb2.out.file.handle;
    2163             : 
    2164           1 :         torture_wait_for_oplock_break(tctx);
    2165           1 :         CHECK_VAL(break_info.count, 0);
    2166           1 :         CHECK_VAL(break_info.failures, 0);
    2167           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2168             : 
    2169           1 :         ZERO_STRUCT(qfi);
    2170           1 :         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
    2171           1 :         qfi.generic.in.file.handle = h1;
    2172           1 :         status = smb2_getinfo_file(tree2, tctx, &qfi);
    2173             : 
    2174           1 :         torture_wait_for_oplock_break(tctx);
    2175           1 :         CHECK_VAL(break_info.count, 0);
    2176             : 
    2177           1 :         smb2_util_close(tree1, h1);
    2178           1 :         smb2_util_close(tree1, h);
    2179             : 
    2180           1 :         smb2_deltree(tree1, BASEDIR);
    2181           1 :         return ret;
    2182             : }
    2183             : 
    2184           1 : static bool test_smb2_oplock_batch16(struct torture_context *tctx,
    2185             :                                      struct smb2_tree *tree1,
    2186             :                                      struct smb2_tree *tree2)
    2187             : {
    2188           1 :         const char *fname = BASEDIR "\\test_batch16.dat";
    2189             :         NTSTATUS status;
    2190           1 :         bool ret = true;
    2191             :         union smb_open io;
    2192             :         struct smb2_handle h, h1, h2;
    2193             : 
    2194           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2195           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2196             : 
    2197             :         /* cleanup */
    2198           1 :         smb2_util_unlink(tree1, fname);
    2199             : 
    2200           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2201           1 :         tree1->session->transport->oplock.private_data = tree1;
    2202             : 
    2203           1 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    2204           1 :         tree2->session->transport->oplock.private_data = tree2;
    2205             : 
    2206             :         /*
    2207             :           base ntcreatex parms
    2208             :         */
    2209           1 :         ZERO_STRUCT(io.smb2);
    2210           1 :         io.generic.level = RAW_OPEN_SMB2;
    2211           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2212           1 :         io.smb2.in.alloc_size = 0;
    2213           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2214           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2215           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2216           1 :         io.smb2.in.create_options = 0;
    2217           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2218           1 :         io.smb2.in.security_flags = 0;
    2219           1 :         io.smb2.in.fname = fname;
    2220             : 
    2221           1 :         torture_comment(tctx, "BATCH16: open with batch oplock\n");
    2222           1 :         ZERO_STRUCT(break_info);
    2223             : 
    2224           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2225           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2226           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2227             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    2228             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    2229           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2230           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2231           1 :         h1 = io.smb2.out.file.handle;
    2232           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2233             : 
    2234           1 :         ZERO_STRUCT(break_info);
    2235             : 
    2236           1 :         torture_comment(tctx, "second open with attributes only and "
    2237             :                         "NTCREATEX_DISP_OVERWRITE_IF dispostion causes "
    2238             :                         "oplock break\n");
    2239             : 
    2240           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2241           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2242           1 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    2243             :                                 SEC_FILE_WRITE_ATTRIBUTE |
    2244             :                                 SEC_STD_SYNCHRONIZE;
    2245           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2246             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    2247             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    2248           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
    2249           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2250           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2251           1 :         h2 = io.smb2.out.file.handle;
    2252           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2253             : 
    2254           1 :         torture_wait_for_oplock_break(tctx);
    2255           1 :         CHECK_VAL(break_info.count, 1);
    2256           1 :         CHECK_VAL(break_info.failures, 0);
    2257             : 
    2258           1 :         smb2_util_close(tree1, h1);
    2259           1 :         smb2_util_close(tree2, h2);
    2260           1 :         smb2_util_close(tree1, h);
    2261             : 
    2262           1 :         smb2_deltree(tree1, BASEDIR);
    2263           1 :         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           1 : static bool test_smb2_oplock_batch19(struct torture_context *tctx,
    2293             :                                      struct smb2_tree *tree1)
    2294             : {
    2295           1 :         const char *fname1 = BASEDIR "\\test_batch19_1.dat";
    2296           1 :         const char *fname2 = BASEDIR "\\test_batch19_2.dat";
    2297             :         NTSTATUS status;
    2298           1 :         bool ret = true;
    2299             :         union smb_open io;
    2300             :         union smb_fileinfo qfi;
    2301             :         union smb_setfileinfo sfi;
    2302             :         struct smb2_handle h, h1;
    2303             : 
    2304           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2305           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2306             : 
    2307             :         /* cleanup */
    2308           1 :         smb2_util_unlink(tree1, fname1);
    2309           1 :         smb2_util_unlink(tree1, fname2);
    2310             : 
    2311           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2312           1 :         tree1->session->transport->oplock.private_data = tree1;
    2313             : 
    2314             :         /*
    2315             :           base ntcreatex parms
    2316             :         */
    2317           1 :         ZERO_STRUCT(io.smb2);
    2318           1 :         io.generic.level = RAW_OPEN_SMB2;
    2319           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2320           1 :         io.smb2.in.alloc_size = 0;
    2321           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2322           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2323           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2324           1 :         io.smb2.in.create_options = 0;
    2325           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2326           1 :         io.smb2.in.security_flags = 0;
    2327           1 :         io.smb2.in.fname = fname1;
    2328             : 
    2329           1 :         torture_comment(tctx, "BATCH19: open a file with an batch oplock "
    2330             :                         "(share mode: none)\n");
    2331           1 :         ZERO_STRUCT(break_info);
    2332           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2333           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2334           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2335           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2336           1 :         h1 = io.smb2.out.file.handle;
    2337           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2338             : 
    2339           1 :         torture_comment(tctx, "setfileinfo rename info should not trigger "
    2340             :                         "a break but should cause a sharing violation\n");
    2341           1 :         ZERO_STRUCT(sfi);
    2342           1 :         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
    2343           1 :         sfi.generic.in.file.path = fname1;
    2344           1 :         sfi.rename_information.in.file.handle   = h1;
    2345           1 :         sfi.rename_information.in.overwrite     = 0;
    2346           1 :         sfi.rename_information.in.root_fid      = 0;
    2347           1 :         sfi.rename_information.in.new_name      = fname2;
    2348             : 
    2349           1 :         status = smb2_setinfo_file(tree1, &sfi);
    2350             : 
    2351           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
    2352             :                                       "Incorrect status");
    2353             : 
    2354           0 :         torture_wait_for_oplock_break(tctx);
    2355           0 :         CHECK_VAL(break_info.count, 0);
    2356             : 
    2357           0 :         ZERO_STRUCT(qfi);
    2358           0 :         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
    2359           0 :         qfi.generic.in.file.handle = h1;
    2360             : 
    2361           0 :         status = smb2_getinfo_file(tree1, tctx, &qfi);
    2362           0 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2363           0 :         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
    2364             : 
    2365           0 :         smb2_util_close(tree1, h1);
    2366           0 :         smb2_util_close(tree1, h);
    2367             : 
    2368           0 :         smb2_deltree(tree1, fname1);
    2369           0 :         smb2_deltree(tree1, fname2);
    2370           0 :         return ret;
    2371             : }
    2372             : 
    2373           1 : static bool test_smb2_oplock_batch20(struct torture_context *tctx,
    2374             :                                      struct smb2_tree *tree1,
    2375             :                                      struct smb2_tree *tree2)
    2376             : {
    2377           1 :         const char *fname1 = BASEDIR "\\test_batch20_1.dat";
    2378           1 :         const char *fname2 = BASEDIR "\\test_batch20_2.dat";
    2379             :         NTSTATUS status;
    2380           1 :         bool ret = true;
    2381             :         union smb_open io;
    2382             :         union smb_fileinfo qfi;
    2383             :         union smb_setfileinfo sfi;
    2384             :         struct smb2_handle h, h1, h2;
    2385             : 
    2386           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2387           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2388             : 
    2389             :         /* cleanup */
    2390           1 :         smb2_util_unlink(tree1, fname1);
    2391           1 :         smb2_util_unlink(tree1, fname2);
    2392             : 
    2393           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2394           1 :         tree1->session->transport->oplock.private_data = tree1;
    2395             : 
    2396             :         /*
    2397             :           base ntcreatex parms
    2398             :         */
    2399           1 :         ZERO_STRUCT(io.smb2);
    2400           1 :         io.generic.level = RAW_OPEN_SMB2;
    2401           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2402           1 :         io.smb2.in.alloc_size = 0;
    2403           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2404           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2405           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2406           1 :         io.smb2.in.create_options = 0;
    2407           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2408           1 :         io.smb2.in.security_flags = 0;
    2409           1 :         io.smb2.in.fname = fname1;
    2410             : 
    2411           1 :         torture_comment(tctx, "BATCH20: open a file with an batch oplock "
    2412             :                         "(share mode: all)\n");
    2413           1 :         ZERO_STRUCT(break_info);
    2414           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2415           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2416           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2417             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    2418             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    2419           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2420           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2421           1 :         h1 = io.smb2.out.file.handle;
    2422           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2423             : 
    2424           1 :         torture_comment(tctx, "setfileinfo rename info should not trigger "
    2425             :                         "a break but should cause a sharing violation\n");
    2426           1 :         ZERO_STRUCT(sfi);
    2427           1 :         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
    2428           1 :         sfi.rename_information.in.file.handle   = h1;
    2429           1 :         sfi.rename_information.in.overwrite     = 0;
    2430           1 :         sfi.rename_information.in.new_name      = fname2;
    2431             : 
    2432           1 :         status = smb2_setinfo_file(tree1, &sfi);
    2433           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_SHARING_VIOLATION,
    2434             :                                       "Incorrect status");
    2435             : 
    2436           0 :         torture_wait_for_oplock_break(tctx);
    2437           0 :         CHECK_VAL(break_info.count, 0);
    2438             : 
    2439           0 :         ZERO_STRUCT(qfi);
    2440           0 :         qfi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
    2441           0 :         qfi.generic.in.file.handle = h1;
    2442             : 
    2443           0 :         status = smb2_getinfo_file(tree1, tctx, &qfi);
    2444           0 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2445           0 :         CHECK_STRMATCH(qfi.all_info2.out.fname.s, fname1);
    2446             : 
    2447           0 :         torture_comment(tctx, "open the file a second time requesting batch "
    2448             :                         "(share mode: all)\n");
    2449           0 :         ZERO_STRUCT(break_info);
    2450           0 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2451           0 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2452           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2453             :                                 NTCREATEX_SHARE_ACCESS_WRITE|
    2454             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    2455           0 :         io.smb2.in.fname = fname1;
    2456           0 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2457           0 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2458           0 :         h2 = io.smb2.out.file.handle;
    2459           0 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2460             : 
    2461           0 :         torture_wait_for_oplock_break(tctx);
    2462           0 :         CHECK_VAL(break_info.count, 1);
    2463           0 :         CHECK_VAL(break_info.failures, 0);
    2464           0 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    2465             : 
    2466           0 :         torture_comment(tctx, "setfileinfo rename info should not trigger "
    2467             :                         "a break but should cause a sharing violation\n");
    2468           0 :         ZERO_STRUCT(break_info);
    2469           0 :         ZERO_STRUCT(sfi);
    2470           0 :         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
    2471           0 :         sfi.rename_information.in.file.handle   = h2;
    2472           0 :         sfi.rename_information.in.overwrite     = 0;
    2473           0 :         sfi.rename_information.in.new_name      = fname2;
    2474             : 
    2475           0 :         status = smb2_setinfo_file(tree2, &sfi);
    2476           0 :         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           1 : static bool test_smb2_oplock_batch21(struct torture_context *tctx,
    2507             :                                      struct smb2_tree *tree1)
    2508             : {
    2509           1 :         const char *fname = BASEDIR "\\test_batch21.dat";
    2510             :         NTSTATUS status;
    2511           1 :         bool ret = true;
    2512             :         union smb_open io;
    2513             :         struct smb2_handle h, h1;
    2514           1 :         char c = 0;
    2515             : 
    2516           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2517           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2518             : 
    2519             :         /* cleanup */
    2520           1 :         smb2_util_unlink(tree1, fname);
    2521             : 
    2522           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2523           1 :         tree1->session->transport->oplock.private_data = tree1;
    2524             : 
    2525             :         /*
    2526             :           base ntcreatex parms
    2527             :         */
    2528           1 :         ZERO_STRUCT(io.smb2);
    2529           1 :         io.generic.level = RAW_OPEN_SMB2;
    2530           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2531           1 :         io.smb2.in.alloc_size = 0;
    2532           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2533           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2534           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2535           1 :         io.smb2.in.create_options = 0;
    2536           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2537           1 :         io.smb2.in.security_flags = 0;
    2538           1 :         io.smb2.in.fname = fname;
    2539             : 
    2540             :         /*
    2541             :           with a batch oplock we get a break
    2542             :         */
    2543           1 :         torture_comment(tctx, "BATCH21: open with batch oplock\n");
    2544           1 :         ZERO_STRUCT(break_info);
    2545           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2546           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2547           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2548           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2549           1 :         h1 = io.smb2.out.file.handle;
    2550           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2551             : 
    2552           1 :         torture_comment(tctx, "writing should not generate a break\n");
    2553           1 :         status = smb2_util_write(tree1, h1, &c, 0, 1);
    2554           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2555             : 
    2556           1 :         torture_wait_for_oplock_break(tctx);
    2557           1 :         CHECK_VAL(break_info.count, 0);
    2558             : 
    2559           1 :         smb2_util_close(tree1, h1);
    2560           1 :         smb2_util_close(tree1, h);
    2561             : 
    2562           1 :         smb2_deltree(tree1, BASEDIR);
    2563           1 :         return ret;
    2564             : }
    2565             : 
    2566           1 : static bool test_smb2_oplock_batch22a(struct torture_context *tctx,
    2567             :                                       struct smb2_tree *tree1)
    2568             : {
    2569           1 :         const char *fname = BASEDIR "\\test_batch22a.dat";
    2570             :         NTSTATUS status;
    2571           1 :         bool ret = true;
    2572             :         union smb_open io;
    2573             :         struct smb2_handle h, h1, h2;
    2574             :         struct timeval tv;
    2575           1 :         int timeout = torture_setting_int(tctx, "oplocktimeout", 35);
    2576             :         int te;
    2577             : 
    2578           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2579           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2580             : 
    2581             :         /* cleanup */
    2582           1 :         smb2_util_unlink(tree1, fname);
    2583             : 
    2584           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2585           1 :         tree1->session->transport->oplock.private_data = tree1;
    2586             :         /*
    2587             :           base ntcreatex parms
    2588             :         */
    2589           1 :         ZERO_STRUCT(io.smb2);
    2590           1 :         io.generic.level = RAW_OPEN_SMB2;
    2591           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2592           1 :         io.smb2.in.alloc_size = 0;
    2593           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2594           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2595           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2596           1 :         io.smb2.in.create_options = 0;
    2597           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2598           1 :         io.smb2.in.security_flags = 0;
    2599           1 :         io.smb2.in.fname = fname;
    2600             : 
    2601             :         /*
    2602             :           with a batch oplock we get a break
    2603             :         */
    2604           1 :         torture_comment(tctx, "BATCH22: open with batch oplock\n");
    2605           1 :         ZERO_STRUCT(break_info);
    2606           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2607           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2608           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2609             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    2610             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    2611           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2612           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2613           1 :         h1 = io.smb2.out.file.handle;
    2614           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2615             : 
    2616           1 :         torture_comment(tctx, "a 2nd open should succeed after the oplock "
    2617             :                         "break timeout\n");
    2618           1 :         tv = timeval_current();
    2619           1 :         tree1->session->transport->oplock.handler =
    2620             :                                 torture_oplock_handler_timeout;
    2621           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2622           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2623           0 :         h2 = io.smb2.out.file.handle;
    2624           0 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2625             : 
    2626           0 :         torture_wait_for_oplock_break(tctx);
    2627           0 :         te = (int)timeval_elapsed(&tv);
    2628           0 :         CHECK_RANGE(te, timeout - 1, timeout + 15);
    2629           0 :         torture_comment(tctx, "waited %d seconds for oplock timeout\n", te);
    2630             : 
    2631           0 :         CHECK_VAL(break_info.count, 1);
    2632           0 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    2633           0 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    2634           0 :         CHECK_VAL(break_info.failures, 0);
    2635             : 
    2636           0 :         smb2_util_close(tree1, h1);
    2637           0 :         smb2_util_close(tree1, h2);
    2638           0 :         smb2_util_close(tree1, h);
    2639             : 
    2640           0 :         smb2_deltree(tree1, BASEDIR);
    2641           0 :         return ret;
    2642             : }
    2643             : 
    2644           1 : static bool test_smb2_oplock_batch22b(struct torture_context *tctx,
    2645             :                                       struct smb2_tree *tree1,
    2646             :                                       struct smb2_tree *tree2)
    2647             : {
    2648           1 :         const char *fname = BASEDIR "\\test_batch22b.dat";
    2649             :         NTSTATUS status;
    2650           1 :         bool ret = true;
    2651             :         union smb_open io;
    2652           1 :         struct smb2_handle h, h1, h2 = {{0}};
    2653             :         struct timeval tv;
    2654           1 :         int timeout = torture_setting_int(tctx, "oplocktimeout", 35);
    2655           1 :         struct smb2_transport *transport1 = tree1->session->transport;
    2656           1 :         bool block_setup = false;
    2657           1 :         bool block_ok = false;
    2658             :         int te;
    2659             : 
    2660           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2661           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2662             : 
    2663             :         /* cleanup */
    2664           1 :         smb2_util_unlink(tree1, fname);
    2665             : 
    2666           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2667           1 :         tree1->session->transport->oplock.private_data = tree1;
    2668             :         /*
    2669             :           base ntcreatex parms
    2670             :         */
    2671           1 :         ZERO_STRUCT(io.smb2);
    2672           1 :         io.generic.level = RAW_OPEN_SMB2;
    2673           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2674           1 :         io.smb2.in.alloc_size = 0;
    2675           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2676           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2677           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2678           1 :         io.smb2.in.create_options = 0;
    2679           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2680           1 :         io.smb2.in.security_flags = 0;
    2681           1 :         io.smb2.in.fname = fname;
    2682             : 
    2683             :         /*
    2684             :           with a batch oplock we get a break
    2685             :         */
    2686           1 :         torture_comment(tctx, "BATCH22: open with batch oplock\n");
    2687           1 :         ZERO_STRUCT(break_info);
    2688           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2689           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2690           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    2691             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    2692             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    2693           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2694           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2695           1 :         h1 = io.smb2.out.file.handle;
    2696           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2697             : 
    2698           1 :         torture_comment(tctx, "a 2nd open should succeed after the oplock "
    2699             :                         "break timeout\n");
    2700           1 :         tv = timeval_current();
    2701           1 :         tree1->session->transport->oplock.handler =
    2702             :                                 torture_oplock_handler_timeout;
    2703           1 :         block_setup = test_setup_blocked_transports(tctx);
    2704           1 :         torture_assert(tctx, block_setup, "test_setup_blocked_transports");
    2705           1 :         block_ok = test_block_smb2_transport(tctx, transport1);
    2706           1 :         torture_assert(tctx, block_ok, "test_block_smb2_transport");
    2707             : 
    2708           0 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2709           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Incorrect status");
    2710           0 :         h2 = io.smb2.out.file.handle;
    2711           0 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2712             : 
    2713           0 :         torture_wait_for_oplock_break(tctx);
    2714           0 :         te = (int)timeval_elapsed(&tv);
    2715           0 :         CHECK_RANGE(te, 0, timeout);
    2716           0 :         torture_comment(tctx, "waited %d seconds for oplock timeout\n", te);
    2717             : 
    2718           0 :         CHECK_VAL(break_info.count, 1);
    2719           0 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    2720           0 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    2721           0 :         CHECK_VAL(break_info.failures, 0);
    2722             : 
    2723           0 : done:
    2724           0 :         if (block_ok) {
    2725           0 :                 test_unblock_smb2_transport(tctx, transport1);
    2726             :         }
    2727           0 :         test_cleanup_blocked_transports(tctx);
    2728             : 
    2729           0 :         smb2_util_close(tree1, h1);
    2730           0 :         if (!smb2_util_handle_empty(h2)) {
    2731           0 :                 smb2_util_close(tree1, h2);
    2732             :         }
    2733           0 :         smb2_util_close(tree1, h);
    2734             : 
    2735           0 :         smb2_deltree(tree1, BASEDIR);
    2736           0 :         return ret;
    2737             : }
    2738             : 
    2739           1 : static bool test_smb2_oplock_batch23(struct torture_context *tctx,
    2740             :                                      struct smb2_tree *tree1,
    2741             :                                      struct smb2_tree *tree2)
    2742             : {
    2743           1 :         const char *fname = BASEDIR "\\test_batch23.dat";
    2744             :         NTSTATUS status;
    2745           1 :         bool ret = true;
    2746             :         union smb_open io;
    2747             :         struct smb2_handle h, h1, h2, h3;
    2748           1 :         struct smb2_tree *tree3 = NULL;
    2749             : 
    2750           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2751           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2752             : 
    2753             :         /* cleanup */
    2754           1 :         smb2_util_unlink(tree1, fname);
    2755             : 
    2756           1 :         ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
    2757           1 :         CHECK_VAL(ret, true);
    2758             : 
    2759           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2760           1 :         tree1->session->transport->oplock.private_data = tree1;
    2761             : 
    2762           1 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    2763           1 :         tree2->session->transport->oplock.private_data = tree2;
    2764             : 
    2765           1 :         tree3->session->transport->oplock.handler = torture_oplock_handler;
    2766           1 :         tree3->session->transport->oplock.private_data = tree3;
    2767             : 
    2768             :         /*
    2769             :           base ntcreatex parms
    2770             :         */
    2771           1 :         ZERO_STRUCT(io.smb2);
    2772           1 :         io.generic.level = RAW_OPEN_SMB2;
    2773           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2774           1 :         io.smb2.in.alloc_size = 0;
    2775           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2776           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2777           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2778           1 :         io.smb2.in.create_options = 0;
    2779           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2780           1 :         io.smb2.in.security_flags = 0;
    2781           1 :         io.smb2.in.fname = fname;
    2782             : 
    2783           1 :         torture_comment(tctx, "BATCH23: an open and ask for a batch oplock\n");
    2784           1 :         ZERO_STRUCT(break_info);
    2785             : 
    2786           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    2787             :                                 SEC_RIGHTS_FILE_WRITE;
    2788           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    2789             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    2790           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2791           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2792           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2793           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2794           1 :         h1 = io.smb2.out.file.handle;
    2795           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2796             : 
    2797           1 :         ZERO_STRUCT(break_info);
    2798             : 
    2799           1 :         torture_comment(tctx, "a 2nd open without level2 oplock support "
    2800             :                         "should generate a break to level2\n");
    2801           1 :         status = smb2_create(tree3, tctx, &(io.smb2));
    2802           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2803           1 :         h3 = io.smb2.out.file.handle;
    2804             : 
    2805           1 :         torture_wait_for_oplock_break(tctx);
    2806           1 :         CHECK_VAL(break_info.count, 1);
    2807           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    2808           1 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    2809           1 :         CHECK_VAL(break_info.failures, 0);
    2810             : 
    2811           1 :         ZERO_STRUCT(break_info);
    2812             : 
    2813           1 :         torture_comment(tctx, "a 3rd open with level2 oplock support should "
    2814             :                         "not generate a break\n");
    2815           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2816           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2817           1 :         h2 = io.smb2.out.file.handle;
    2818           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2819             : 
    2820           1 :         torture_wait_for_oplock_break(tctx);
    2821           1 :         CHECK_VAL(break_info.count, 0);
    2822             : 
    2823           1 :         smb2_util_close(tree1, h1);
    2824           1 :         smb2_util_close(tree2, h2);
    2825           1 :         smb2_util_close(tree3, h3);
    2826           1 :         smb2_util_close(tree1, h);
    2827             : 
    2828           1 :         smb2_deltree(tree1, BASEDIR);
    2829           1 :         return ret;
    2830             : }
    2831             : 
    2832           1 : static bool test_smb2_oplock_batch24(struct torture_context *tctx,
    2833             :                                      struct smb2_tree *tree1,
    2834             :                                      struct smb2_tree *tree2)
    2835             : {
    2836           1 :         const char *fname = BASEDIR "\\test_batch24.dat";
    2837             :         NTSTATUS status;
    2838           1 :         bool ret = true;
    2839             :         union smb_open io;
    2840             :         struct smb2_handle h, h1, h2;
    2841           1 :         struct smb2_tree *tree3 = NULL;
    2842             : 
    2843           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2844           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2845             : 
    2846             :         /* cleanup */
    2847           1 :         smb2_util_unlink(tree1, fname);
    2848             : 
    2849           1 :         ret = open_smb2_connection_no_level2_oplocks(tctx, &tree3);
    2850           1 :         CHECK_VAL(ret, true);
    2851             : 
    2852           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2853           1 :         tree1->session->transport->oplock.private_data = tree1;
    2854             : 
    2855           1 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    2856           1 :         tree2->session->transport->oplock.private_data = tree2;
    2857             : 
    2858           1 :         tree3->session->transport->oplock.handler = torture_oplock_handler;
    2859           1 :         tree3->session->transport->oplock.private_data = tree3;
    2860             : 
    2861             :         /*
    2862             :           base ntcreatex parms
    2863             :         */
    2864           1 :         ZERO_STRUCT(io.smb2);
    2865           1 :         io.generic.level = RAW_OPEN_SMB2;
    2866           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2867           1 :         io.smb2.in.alloc_size = 0;
    2868           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2869           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2870           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2871           1 :         io.smb2.in.create_options = 0;
    2872           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2873           1 :         io.smb2.in.security_flags = 0;
    2874           1 :         io.smb2.in.fname = fname;
    2875             : 
    2876           1 :         torture_comment(tctx, "BATCH24: a open without level support and "
    2877             :                         "ask for a batch oplock\n");
    2878           1 :         ZERO_STRUCT(break_info);
    2879             : 
    2880           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    2881             :                                 SEC_RIGHTS_FILE_WRITE;
    2882           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    2883             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    2884           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2885           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2886             : 
    2887           1 :         status = smb2_create(tree3, tctx, &(io.smb2));
    2888           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2889           1 :         h2 = io.smb2.out.file.handle;
    2890           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2891             : 
    2892           1 :         ZERO_STRUCT(break_info);
    2893             : 
    2894           1 :         torture_comment(tctx, "a 2nd open with level2 oplock support should "
    2895             :                         "generate a break\n");
    2896           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    2897           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    2898           1 :         h1 = io.smb2.out.file.handle;
    2899           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    2900             : 
    2901           1 :         torture_wait_for_oplock_break(tctx);
    2902           1 :         CHECK_VAL(break_info.count, 1);
    2903           1 :         CHECK_VAL(break_info.handle.data[0], h2.data[0]);
    2904           1 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    2905           1 :         CHECK_VAL(break_info.failures, 0);
    2906             : 
    2907           1 :         smb2_util_close(tree3, h2);
    2908           1 :         smb2_util_close(tree2, h1);
    2909           1 :         smb2_util_close(tree1, h);
    2910             : 
    2911           1 :         smb2_deltree(tree1, BASEDIR);
    2912           1 :         return ret;
    2913             : }
    2914             : 
    2915           1 : static bool test_smb2_oplock_batch25(struct torture_context *tctx,
    2916             :                                      struct smb2_tree *tree1)
    2917             : {
    2918           1 :         const char *fname = BASEDIR "\\test_batch25.dat";
    2919             :         NTSTATUS status;
    2920           1 :         bool ret = true;
    2921             :         union smb_open io;
    2922             :         struct smb2_handle h, h1;
    2923             : 
    2924           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2925           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2926             : 
    2927             :         /* cleanup */
    2928           1 :         smb2_util_unlink(tree1, fname);
    2929             : 
    2930           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2931           1 :         tree1->session->transport->oplock.private_data = tree1;
    2932             : 
    2933             :         /*
    2934             :           base ntcreatex parms
    2935             :         */
    2936           1 :         ZERO_STRUCT(io.smb2);
    2937           1 :         io.generic.level = RAW_OPEN_SMB2;
    2938           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2939           1 :         io.smb2.in.alloc_size = 0;
    2940           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2941           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2942           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2943           1 :         io.smb2.in.create_options = 0;
    2944           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2945           1 :         io.smb2.in.security_flags = 0;
    2946           1 :         io.smb2.in.fname = fname;
    2947             : 
    2948           1 :         torture_comment(tctx, "BATCH25: open a file with an batch oplock "
    2949             :                         "(share mode: none)\n");
    2950             : 
    2951           1 :         ZERO_STRUCT(break_info);
    2952           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    2953           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    2954             : 
    2955           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    2956           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    2957           1 :         h1 = io.smb2.out.file.handle;
    2958           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2959             : 
    2960           1 :         status = smb2_util_setatr(tree1, fname, FILE_ATTRIBUTE_HIDDEN);
    2961           1 :         torture_assert_ntstatus_ok(tctx, status, "Setting attributes "
    2962             :                                    "shouldn't trigger an oplock break");
    2963             : 
    2964           1 :         smb2_util_close(tree1, h1);
    2965           1 :         smb2_util_close(tree1, h);
    2966             : 
    2967           1 :         smb2_deltree(tree1, fname);
    2968           1 :         return ret;
    2969             : }
    2970             : 
    2971           1 : static bool test_smb2_oplock_batch26(struct torture_context *tctx,
    2972             :                                         struct smb2_tree *tree1)
    2973             : {
    2974             : 
    2975             :         NTSTATUS status;
    2976           1 :         bool ret = true;
    2977             :         union smb_open io;
    2978             :         struct smb2_handle h, h1, h2, h3;
    2979           1 :         const char *fname_base = BASEDIR "\\test_oplock.txt";
    2980           1 :         const char *stream = "Stream One:$DATA";
    2981             :         const char *fname_stream;
    2982             : 
    2983           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    2984           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    2985             : 
    2986           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    2987           1 :         tree1->session->transport->oplock.private_data = tree1;
    2988             : 
    2989           1 :         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
    2990             : 
    2991             :         /*
    2992             :           base ntcreatex parms
    2993             :         */
    2994           1 :         ZERO_STRUCT(io.smb2);
    2995           1 :         io.generic.level = RAW_OPEN_SMB2;
    2996           1 :         io.smb2.in.desired_access = 0x120089;
    2997           1 :         io.smb2.in.alloc_size = 0;
    2998           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2999           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_DELETE |
    3000             :                                   NTCREATEX_SHARE_ACCESS_WRITE;
    3001           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3002           1 :         io.smb2.in.create_options = 0;
    3003           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3004           1 :         io.smb2.in.security_flags = 0;
    3005           1 :         io.smb2.in.fname = fname_base;
    3006             : 
    3007             :         /*
    3008             :           Open base file with a batch oplock.
    3009             :         */
    3010           1 :         torture_comment(tctx, "Open the base file with batch oplock\n");
    3011           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3012           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3013             : 
    3014           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3015           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening base file");
    3016           1 :         h1 = io.smb2.out.file.handle;
    3017           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3018             : 
    3019           1 :         torture_comment(tctx, "Got batch oplock on base file\n");
    3020             : 
    3021           1 :         torture_comment(tctx, "Opening stream file with batch oplock..\n");
    3022             : 
    3023           1 :         io.smb2.in.fname = fname_stream;
    3024             : 
    3025           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3026           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening stream file");
    3027           1 :         h2 = io.smb2.out.file.handle;
    3028           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3029             : 
    3030           1 :         torture_comment(tctx, "Got batch oplock on stream file\n");
    3031             : 
    3032           1 :         torture_comment(tctx, "Open base file again with batch oplock\n");
    3033             : 
    3034           1 :         io.smb2.in.fname = fname_base;
    3035             : 
    3036           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3037           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    3038           1 :         h3 = io.smb2.out.file.handle;
    3039           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    3040             : 
    3041           1 :         smb2_util_close(tree1, h1);
    3042           1 :         smb2_util_close(tree1, h2);
    3043           1 :         smb2_util_close(tree1, h3);
    3044           1 :         smb2_util_close(tree1, h);
    3045           1 :         smb2_deltree(tree1, BASEDIR);
    3046           1 :         return ret;
    3047             : 
    3048             : }
    3049             : 
    3050             : /* Test how oplocks work on streams. */
    3051           1 : static bool test_raw_oplock_stream1(struct torture_context *tctx,
    3052             :                                     struct smb2_tree *tree1,
    3053             :                                     struct smb2_tree *tree2)
    3054             : {
    3055             :         NTSTATUS status;
    3056             :         union smb_open io;
    3057           1 :         const char *fname_base = BASEDIR "\\test_stream1.txt";
    3058             :         const char *fname_stream, *fname_default_stream;
    3059           1 :         const char *default_stream = "::$DATA";
    3060           1 :         const char *stream = "Stream One:$DATA";
    3061           1 :         bool ret = true;
    3062             :         struct smb2_handle h, h_base, h_stream;
    3063             :         int i;
    3064             : 
    3065             : #define NSTREAM_OPLOCK_RESULTS 8
    3066             :         struct {
    3067             :                 const char **fname;
    3068             :                 bool open_base_file;
    3069             :                 uint32_t oplock_req;
    3070             :                 uint32_t oplock_granted;
    3071           1 :         } 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           1 :         fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
    3086           1 :         fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
    3087             :                                                default_stream);
    3088             : 
    3089           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    3090           1 :         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           1 :         h_stream.data[0] = -1;
    3095             : 
    3096             :         /* cleanup */
    3097           1 :         smb2_util_unlink(tree1, fname_base);
    3098             : 
    3099           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    3100           1 :         tree1->session->transport->oplock.private_data = tree1;
    3101             : 
    3102           1 :         tree2->session->transport->oplock.handler = torture_oplock_handler;
    3103           1 :         tree2->session->transport->oplock.private_data = tree2;
    3104             : 
    3105             :         /* Setup generic open parameters. */
    3106           1 :         ZERO_STRUCT(io.smb2);
    3107           1 :         io.generic.level = RAW_OPEN_SMB2;
    3108           1 :         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           1 :         io.smb2.in.alloc_size = 0;
    3113           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3114           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3115             :                                   NTCREATEX_SHARE_ACCESS_WRITE;
    3116           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3117           1 :         io.smb2.in.create_options = 0;
    3118           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3119           1 :         io.smb2.in.security_flags = 0;
    3120             : 
    3121             :         /* Create the file with a stream */
    3122           1 :         io.smb2.in.fname = fname_stream;
    3123           1 :         io.smb2.in.create_flags = 0;
    3124           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    3125           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3126           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating file");
    3127           1 :         smb2_util_close(tree1, io.smb2.out.file.handle);
    3128             : 
    3129             :         /* Change the disposition to open now that the file has been created. */
    3130           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    3131             : 
    3132             :         /* Try some permutations of taking oplocks on streams. */
    3133           9 :         for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
    3134           8 :                 const char *fname = *stream_oplock_results[i].fname;
    3135           8 :                 bool open_base_file = stream_oplock_results[i].open_base_file;
    3136           8 :                 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
    3137           8 :                 uint32_t oplock_granted =
    3138             :                     stream_oplock_results[i].oplock_granted;
    3139             : 
    3140           8 :                 if (open_base_file) {
    3141           4 :                         torture_comment(tctx, "Opening base file: %s with "
    3142             :                             "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
    3143           4 :                         io.smb2.in.fname = fname_base;
    3144           4 :                         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3145           4 :                         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3146           4 :                         status = smb2_create(tree2, tctx, &(io.smb2));
    3147           4 :                         torture_assert_ntstatus_ok(tctx, status,
    3148             :                             "Error opening file");
    3149           4 :                         CHECK_VAL(io.smb2.out.oplock_level,
    3150             :                             SMB2_OPLOCK_LEVEL_BATCH);
    3151           4 :                         h_base = io.smb2.out.file.handle;
    3152             :                 }
    3153             : 
    3154           8 :                 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
    3155             :                     fname, oplock_req);
    3156           8 :                 io.smb2.in.fname = fname;
    3157           8 :                 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3158           8 :                 io.smb2.in.oplock_level = oplock_req;
    3159             : 
    3160             :                 /* Do the open with the desired oplock on the stream. */
    3161           8 :                 status = smb2_create(tree1, tctx, &(io.smb2));
    3162           8 :                 torture_assert_ntstatus_ok(tctx, status, "Error opening file");
    3163           8 :                 CHECK_VAL(io.smb2.out.oplock_level, oplock_granted);
    3164           8 :                 smb2_util_close(tree1, io.smb2.out.file.handle);
    3165             : 
    3166             :                 /* Cleanup the base file if it was opened. */
    3167           8 :                 if (open_base_file)
    3168           4 :                         smb2_util_close(tree2, h_base);
    3169             :         }
    3170             : 
    3171             :         /* Open the stream with an exclusive oplock. */
    3172           1 :         torture_comment(tctx, "Opening stream: %s with %d\n",
    3173             :             fname_stream, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
    3174           1 :         io.smb2.in.fname = fname_stream;
    3175           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3176           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    3177           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3178           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
    3179           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
    3180           1 :         h_stream = io.smb2.out.file.handle;
    3181             : 
    3182             :         /* Open the base file and see if it contends. */
    3183           1 :         ZERO_STRUCT(break_info);
    3184           1 :         torture_comment(tctx, "Opening base file: %s with %d\n",
    3185             :             fname_base, SMB2_OPLOCK_LEVEL_BATCH);
    3186           1 :         io.smb2.in.fname = fname_base;
    3187           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3188           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3189           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    3190           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
    3191           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3192           1 :         smb2_util_close(tree2, io.smb2.out.file.handle);
    3193             : 
    3194           1 :         torture_wait_for_oplock_break(tctx);
    3195           1 :         CHECK_VAL(break_info.count, 0);
    3196           1 :         CHECK_VAL(break_info.failures, 0);
    3197             : 
    3198             :         /* Open the stream again to see if it contends. */
    3199           1 :         ZERO_STRUCT(break_info);
    3200           1 :         torture_comment(tctx, "Opening stream again: %s with "
    3201             :             "%d\n", fname_base, SMB2_OPLOCK_LEVEL_BATCH);
    3202           1 :         io.smb2.in.fname = fname_stream;
    3203           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3204           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    3205           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    3206           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening file");
    3207           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    3208           1 :         smb2_util_close(tree2, io.smb2.out.file.handle);
    3209             : 
    3210           1 :         torture_wait_for_oplock_break(tctx);
    3211           1 :         CHECK_VAL(break_info.count, 1);
    3212           1 :         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
    3213           1 :         CHECK_VAL(break_info.failures, 0);
    3214             : 
    3215             :         /* Close the stream. */
    3216           1 :         if (h_stream.data[0] != -1) {
    3217           1 :                 smb2_util_close(tree1, h_stream);
    3218             :         }
    3219             : 
    3220           1 :         smb2_util_close(tree1, h);
    3221             : 
    3222           1 :         smb2_deltree(tree1, BASEDIR);
    3223           1 :         return ret;
    3224             : }
    3225             : 
    3226           1 : static bool test_smb2_oplock_doc(struct torture_context *tctx, struct smb2_tree *tree,
    3227             :                                  struct smb2_tree *tree2)
    3228             : {
    3229           1 :         const char *fname = BASEDIR "\\test_oplock_doc.dat";
    3230             :         NTSTATUS status;
    3231           1 :         bool ret = true;
    3232             :         union smb_open io;
    3233             :         struct smb2_handle h, h1;
    3234             :         union smb_setfileinfo sfinfo;
    3235             : 
    3236           1 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    3237           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3238           1 :         smb2_util_close(tree, h);
    3239             : 
    3240             :         /* cleanup */
    3241           1 :         smb2_util_unlink(tree, fname);
    3242           1 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    3243           1 :         tree->session->transport->oplock.private_data = tree;
    3244             : 
    3245             :         /*
    3246             :           base ntcreatex parms
    3247             :         */
    3248           1 :         ZERO_STRUCT(io.smb2);
    3249           1 :         io.generic.level = RAW_OPEN_SMB2;
    3250           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    3251           1 :         io.smb2.in.alloc_size = 0;
    3252           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3253           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    3254             :                 NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
    3255           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3256           1 :         io.smb2.in.create_options = 0;
    3257           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3258           1 :         io.smb2.in.security_flags = 0;
    3259           1 :         io.smb2.in.fname = fname;
    3260             : 
    3261           1 :         torture_comment(tctx, "open a file with a batch oplock\n");
    3262           1 :         ZERO_STRUCT(break_info);
    3263           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3264           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3265             : 
    3266           1 :         status = smb2_create(tree, tctx, &(io.smb2));
    3267           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3268           1 :         h1 = io.smb2.out.file.handle;
    3269           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3270             : 
    3271           1 :         torture_comment(tctx, "Set delete on close\n");
    3272           1 :         ZERO_STRUCT(sfinfo);
    3273           1 :         sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
    3274           1 :         sfinfo.generic.in.file.handle = h1;
    3275           1 :         sfinfo.disposition_info.in.delete_on_close = 1;
    3276           1 :         status = smb2_setinfo_file(tree, &sfinfo);
    3277           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3278             : 
    3279           1 :         torture_comment(tctx, "2nd open should not break and get "
    3280             :                         "DELETE_PENDING\n");
    3281           1 :         ZERO_STRUCT(break_info);
    3282           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    3283           1 :         io.smb2.in.create_options = 0;
    3284           1 :         io.smb2.in.desired_access = SEC_FILE_READ_DATA;
    3285           1 :         status = smb2_create(tree2, tctx, &io.smb2);
    3286           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DELETE_PENDING,
    3287             :                                       "Incorrect status");
    3288           1 :         CHECK_VAL(break_info.count, 0);
    3289             : 
    3290           1 :         smb2_util_close(tree, h1);
    3291             : 
    3292           1 :         smb2_util_unlink(tree, fname);
    3293           1 :         smb2_deltree(tree, BASEDIR);
    3294           1 :         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           1 : static bool test_smb2_oplock_brl1(struct torture_context *tctx,
    3302             :                                 struct smb2_tree *tree1,
    3303             :                                 struct smb2_tree *tree2)
    3304             : {
    3305           1 :         const char *fname = BASEDIR "\\test_batch_brl.dat";
    3306             :         /*int fname, f;*/
    3307           1 :         bool ret = true;
    3308             :         uint8_t buf[1000];
    3309             :         union smb_open io;
    3310             :         NTSTATUS status;
    3311             :         struct smb2_lock lck;
    3312             :         struct smb2_lock_element lock[1];
    3313             :         struct smb2_handle h, h1, h2;
    3314             : 
    3315           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    3316           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3317             : 
    3318             :         /* cleanup */
    3319           1 :         smb2_util_unlink(tree1, fname);
    3320             : 
    3321           1 :         tree1->session->transport->oplock.handler =
    3322             :             torture_oplock_handler_two_notifications;
    3323           1 :         tree1->session->transport->oplock.private_data = tree1;
    3324             : 
    3325             :         /*
    3326             :           base ntcreatex parms
    3327             :         */
    3328           1 :         ZERO_STRUCT(io.smb2);
    3329           1 :         io.generic.level = RAW_OPEN_SMB2;
    3330           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    3331             :                                     SEC_RIGHTS_FILE_WRITE;
    3332           1 :         io.smb2.in.alloc_size = 0;
    3333           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3334           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3335             :                                   NTCREATEX_SHARE_ACCESS_WRITE;
    3336           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3337           1 :         io.smb2.in.create_options = 0;
    3338           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3339           1 :         io.smb2.in.security_flags = 0;
    3340           1 :         io.smb2.in.fname = fname;
    3341             : 
    3342             :         /*
    3343             :           with a batch oplock we get a break
    3344             :         */
    3345           1 :         torture_comment(tctx, "open with batch oplock\n");
    3346           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3347           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3348             : 
    3349           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3350           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    3351           1 :         h1 = io.smb2.out.file.handle;
    3352           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3353             : 
    3354             :         /* create a file with bogus data */
    3355           1 :         memset(buf, 0, sizeof(buf));
    3356             : 
    3357           1 :         status = smb2_util_write(tree1, h1,buf, 0, sizeof(buf));
    3358           1 :         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           1 :         torture_comment(tctx, "a 2nd open should give a break\n");
    3365           1 :         ZERO_STRUCT(break_info);
    3366             : 
    3367           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3368           1 :         io.smb2.in.oplock_level = 0;
    3369           1 :         status = smb2_create(tree2, tctx, &(io.smb2));
    3370           1 :         h2 = io.smb2.out.file.handle;
    3371           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3372             : 
    3373           1 :         torture_wait_for_oplock_break(tctx);
    3374           1 :         CHECK_VAL(break_info.count, 1);
    3375           1 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    3376           1 :         CHECK_VAL(break_info.failures, 0);
    3377           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    3378             : 
    3379           1 :         ZERO_STRUCT(break_info);
    3380             : 
    3381           1 :         torture_comment(tctx, "a self BRL acquisition should break to none\n");
    3382             : 
    3383           1 :         ZERO_STRUCT(lock);
    3384             : 
    3385           1 :         lock[0].offset = 0;
    3386           1 :         lock[0].length = 4;
    3387           1 :         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
    3388             :                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3389             : 
    3390           1 :         ZERO_STRUCT(lck);
    3391           1 :         lck.in.file.handle = h1;
    3392           1 :         lck.in.locks = &lock[0];
    3393           1 :         lck.in.lock_count = 1;
    3394           1 :         status = smb2_lock(tree1, &lck);
    3395           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3396             : 
    3397           1 :         torture_wait_for_oplock_break(tctx);
    3398           1 :         CHECK_VAL(break_info.count, 1);
    3399           1 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
    3400           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    3401           1 :         CHECK_VAL(break_info.failures, 0);
    3402             : 
    3403             :         /* expect no oplock break */
    3404           1 :         ZERO_STRUCT(break_info);
    3405           1 :         lock[0].offset = 2;
    3406           1 :         status = smb2_lock(tree1, &lck);
    3407           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
    3408             :                                       "Incorrect status");
    3409             : 
    3410           1 :         torture_wait_for_oplock_break(tctx);
    3411           1 :         CHECK_VAL(break_info.count, 0);
    3412           1 :         CHECK_VAL(break_info.level, 0);
    3413           1 :         CHECK_VAL(break_info.failures, 0);
    3414             : 
    3415           1 :         smb2_util_close(tree1, h1);
    3416           1 :         smb2_util_close(tree2, h2);
    3417           1 :         smb2_util_close(tree1, h);
    3418             : 
    3419           1 : done:
    3420           1 :         smb2_deltree(tree1, BASEDIR);
    3421           1 :         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           1 : static bool test_smb2_oplock_brl2(struct torture_context *tctx, struct smb2_tree *tree1)
    3429             : {
    3430           1 :         const char *fname = BASEDIR "\\test_batch_brl.dat";
    3431             :         /*int fname, f;*/
    3432           1 :         bool ret = true;
    3433             :         uint8_t buf[1000];
    3434             :         union smb_open io;
    3435             :         NTSTATUS status;
    3436             :         struct smb2_handle h, h1;
    3437             :         struct smb2_lock lck;
    3438             :         struct smb2_lock_element lock[1];
    3439             : 
    3440           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    3441           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3442             : 
    3443             :         /* cleanup */
    3444           1 :         smb2_util_unlink(tree1, fname);
    3445             : 
    3446           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    3447           1 :         tree1->session->transport->oplock.private_data = tree1;
    3448             : 
    3449             :         /*
    3450             :           base ntcreatex parms
    3451             :         */
    3452           1 :         ZERO_STRUCT(io.smb2);
    3453           1 :         io.generic.level = RAW_OPEN_SMB2;
    3454           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    3455             :                                     SEC_RIGHTS_FILE_WRITE;
    3456           1 :         io.smb2.in.alloc_size = 0;
    3457           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3458           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3459             :                                   NTCREATEX_SHARE_ACCESS_WRITE;
    3460           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3461           1 :         io.smb2.in.create_options = 0;
    3462           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3463           1 :         io.smb2.in.security_flags = 0;
    3464           1 :         io.smb2.in.fname = fname;
    3465             : 
    3466             :         /*
    3467             :           with a batch oplock we get a break
    3468             :         */
    3469           1 :         torture_comment(tctx, "open with batch oplock\n");
    3470           1 :         ZERO_STRUCT(break_info);
    3471           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3472           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3473             : 
    3474           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3475           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    3476           1 :         h1 = io.smb2.out.file.handle;
    3477           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3478             : 
    3479             :         /* create a file with bogus data */
    3480           1 :         memset(buf, 0, sizeof(buf));
    3481             : 
    3482           1 :         status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
    3483           1 :         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           1 :         ZERO_STRUCT(break_info);
    3490             : 
    3491           1 :         torture_comment(tctx, "a self BRL acquisition should not break to "
    3492             :                         "none\n");
    3493             : 
    3494           1 :         ZERO_STRUCT(lock);
    3495             : 
    3496           1 :         lock[0].offset = 0;
    3497           1 :         lock[0].length = 4;
    3498           1 :         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
    3499             :                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3500             : 
    3501           1 :         ZERO_STRUCT(lck);
    3502           1 :         lck.in.file.handle = h1;
    3503           1 :         lck.in.locks = &lock[0];
    3504           1 :         lck.in.lock_count = 1;
    3505           1 :         status = smb2_lock(tree1, &lck);
    3506           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3507             : 
    3508           1 :         lock[0].offset = 2;
    3509           1 :         status = smb2_lock(tree1, &lck);
    3510           1 :         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           1 :         torture_wait_for_oplock_break(tctx);
    3517           1 :         CHECK_VAL(break_info.count, 0);
    3518           1 :         CHECK_VAL(break_info.level, 0);
    3519           1 :         CHECK_VAL(break_info.failures, 0);
    3520             : 
    3521           1 :         smb2_util_close(tree1, h1);
    3522           1 :         smb2_util_close(tree1, h);
    3523             : 
    3524           1 : done:
    3525           1 :         smb2_deltree(tree1, BASEDIR);
    3526           1 :         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           1 : static bool test_smb2_oplock_brl3(struct torture_context *tctx, struct smb2_tree *tree1)
    3533             : {
    3534           1 :         const char *fname = BASEDIR "\\test_batch_brl.dat";
    3535           1 :         bool ret = true;
    3536             :         uint8_t buf[1000];
    3537             :         union smb_open io;
    3538             :         NTSTATUS status;
    3539             :         struct smb2_handle h, h1, h2;
    3540             :         struct smb2_lock lck;
    3541             :         struct smb2_lock_element lock[1];
    3542             : 
    3543           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    3544           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3545             : 
    3546             :         /* cleanup */
    3547           1 :         smb2_util_unlink(tree1, fname);
    3548           1 :         tree1->session->transport->oplock.handler =
    3549             :             torture_oplock_handler_two_notifications;
    3550           1 :         tree1->session->transport->oplock.private_data = tree1;
    3551             : 
    3552             :         /*
    3553             :           base ntcreatex parms
    3554             :         */
    3555           1 :         ZERO_STRUCT(io.smb2);
    3556           1 :         io.generic.level = RAW_OPEN_SMB2;
    3557           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    3558             :                                     SEC_RIGHTS_FILE_WRITE;
    3559           1 :         io.smb2.in.alloc_size = 0;
    3560           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3561           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3562             :                                   NTCREATEX_SHARE_ACCESS_WRITE;
    3563           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3564           1 :         io.smb2.in.create_options = 0;
    3565           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3566           1 :         io.smb2.in.security_flags = 0;
    3567           1 :         io.smb2.in.fname = fname;
    3568             : 
    3569             :         /*
    3570             :           with a batch oplock we get a break
    3571             :         */
    3572           1 :         torture_comment(tctx, "open with batch oplock\n");
    3573           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3574           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    3575             : 
    3576           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3577           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    3578           1 :         h1 = io.smb2.out.file.handle;
    3579           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3580             : 
    3581             :         /* create a file with bogus data */
    3582           1 :         memset(buf, 0, sizeof(buf));
    3583           1 :         status = smb2_util_write(tree1, h1, buf, 0, sizeof(buf));
    3584             : 
    3585           1 :         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           1 :         torture_comment(tctx, "a 2nd open should give a break\n");
    3592           1 :         ZERO_STRUCT(break_info);
    3593             : 
    3594           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3595           1 :         io.smb2.in.oplock_level = 0;
    3596           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3597           1 :         h2 = io.smb2.out.file.handle;
    3598           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3599           1 :         CHECK_VAL(break_info.count, 1);
    3600           1 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    3601           1 :         CHECK_VAL(break_info.failures, 0);
    3602           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    3603             : 
    3604           1 :         ZERO_STRUCT(break_info);
    3605             : 
    3606           1 :         torture_comment(tctx, "a self BRL acquisition should break to none\n");
    3607             : 
    3608           1 :         ZERO_STRUCT(lock);
    3609             : 
    3610           1 :         lock[0].offset = 0;
    3611           1 :         lock[0].length = 4;
    3612           1 :         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
    3613             :                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3614             : 
    3615           1 :         ZERO_STRUCT(lck);
    3616           1 :         lck.in.file.handle = h1;
    3617           1 :         lck.in.locks = &lock[0];
    3618           1 :         lck.in.lock_count = 1;
    3619           1 :         status = smb2_lock(tree1, &lck);
    3620           1 :         torture_assert_ntstatus_ok(tctx, status, "Incorrect status");
    3621             : 
    3622           1 :         torture_wait_for_oplock_break(tctx);
    3623           1 :         CHECK_VAL(break_info.count, 1);
    3624           1 :         CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_NONE);
    3625           1 :         CHECK_VAL(break_info.handle.data[0], h1.data[0]);
    3626           1 :         CHECK_VAL(break_info.failures, 0);
    3627             : 
    3628             :         /* expect no oplock break */
    3629           1 :         ZERO_STRUCT(break_info);
    3630           1 :         lock[0].offset = 2;
    3631           1 :         status = smb2_lock(tree1, &lck);
    3632           1 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOCK_NOT_GRANTED,
    3633             :                                       "Incorrect status");
    3634             : 
    3635           1 :         torture_wait_for_oplock_break(tctx);
    3636           1 :         CHECK_VAL(break_info.count, 0);
    3637           1 :         CHECK_VAL(break_info.level, 0);
    3638           1 :         CHECK_VAL(break_info.failures, 0);
    3639             : 
    3640           1 :         smb2_util_close(tree1, h1);
    3641           1 :         smb2_util_close(tree1, h2);
    3642           1 :         smb2_util_close(tree1, h);
    3643             : 
    3644           1 : done:
    3645           1 :         smb2_deltree(tree1, BASEDIR);
    3646           1 :         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           1 : static bool test_smb2_oplock_levelII500(struct torture_context *tctx,
    3656             :                                       struct smb2_tree *tree1)
    3657             : {
    3658           1 :         const char *fname = BASEDIR "\\test_levelII500.dat";
    3659             :         NTSTATUS status;
    3660           1 :         bool ret = true;
    3661             :         union smb_open io;
    3662             :         struct smb2_handle h, h1;
    3663           1 :         char c = 0;
    3664             : 
    3665           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    3666           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3667             : 
    3668             :         /* cleanup */
    3669           1 :         smb2_util_unlink(tree1, fname);
    3670             : 
    3671           1 :         tree1->session->transport->oplock.handler = torture_oplock_handler;
    3672           1 :         tree1->session->transport->oplock.private_data = tree1;
    3673             : 
    3674             :         /*
    3675             :           base ntcreatex parms
    3676             :         */
    3677           1 :         ZERO_STRUCT(io.smb2);
    3678           1 :         io.generic.level = RAW_OPEN_SMB2;
    3679           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    3680           1 :         io.smb2.in.alloc_size = 0;
    3681           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3682           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3683           1 :         io.smb2.in.create_options = 0;
    3684           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3685           1 :         io.smb2.in.security_flags = 0;
    3686           1 :         io.smb2.in.fname = fname;
    3687             : 
    3688           1 :         torture_comment(tctx, "LEVELII500: acknowledging a break from II to "
    3689             :                         "none should return an error\n");
    3690           1 :         ZERO_STRUCT(break_info);
    3691             : 
    3692           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    3693             :                                 SEC_RIGHTS_FILE_WRITE;
    3694           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3695             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    3696           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3697           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
    3698           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    3699           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    3700           1 :         h1 = io.smb2.out.file.handle;
    3701           1 :         CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
    3702             : 
    3703           1 :         ZERO_STRUCT(break_info);
    3704             : 
    3705           1 :         torture_comment(tctx, "write should trigger a break to none and when "
    3706             :                         "we reply, an oplock break failure\n");
    3707           1 :         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           1 :         torture_wait_for_oplock_break(tctx);
    3712           1 :         torture_wait_for_oplock_break(tctx);
    3713           1 :         torture_wait_for_oplock_break(tctx);
    3714           1 :         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           1 :         CHECK_VAL(break_info.count, 1);
    3723           1 :         CHECK_VAL(break_info.level, 0);
    3724           1 :         CHECK_VAL(break_info.failures, 1);
    3725           1 :         torture_assert_ntstatus_equal(tctx, break_info.failure_status,
    3726             :                                       NT_STATUS_INVALID_OPLOCK_PROTOCOL,
    3727             :                                       "Incorrect status");
    3728             : 
    3729           0 :         smb2_util_close(tree1, h1);
    3730           0 :         smb2_util_close(tree1, h);
    3731             : 
    3732           0 :         smb2_deltree(tree1, BASEDIR);
    3733           0 :         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           1 : static bool test_smb2_oplock_levelII501(struct torture_context *tctx,
    3781             :                                         struct smb2_tree *tree1,
    3782             :                                         struct smb2_tree *tree2)
    3783             : {
    3784           1 :         const char *fname = BASEDIR "\\test_levelII501.dat";
    3785             :         NTSTATUS status;
    3786           1 :         bool ret = true;
    3787             :         struct levelII501_state *state;
    3788             :         struct smb2_request *req;
    3789             :         struct tevent_timer *te;
    3790             : 
    3791           1 :         state = talloc(tctx, struct levelII501_state);
    3792           1 :         state->tctx = tctx;
    3793           1 :         state->done = false;
    3794           1 :         state->tree1 = tree1;
    3795           1 :         state->tree2 = tree2;
    3796             : 
    3797           1 :         if (!torture_smb2_connection(tctx, &state->tree3)) {
    3798           0 :                 torture_fail(tctx, "Establishing SMB2 connection failed\n");
    3799             :                 return false;
    3800             :         }
    3801             : 
    3802           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &state->h);
    3803           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    3804             : 
    3805             :         /* cleanup */
    3806           1 :         smb2_util_unlink(tree1, fname);
    3807             : 
    3808             :         /*
    3809             :           base ntcreatex parms
    3810             :         */
    3811           1 :         ZERO_STRUCT(state->io.smb2);
    3812           1 :         state->io.generic.level = RAW_OPEN_SMB2;
    3813           1 :         state->io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    3814           1 :         state->io.smb2.in.alloc_size = 0;
    3815           1 :         state->io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    3816           1 :         state->io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    3817           1 :         state->io.smb2.in.create_options = 0;
    3818           1 :         state->io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3819           1 :         state->io.smb2.in.security_flags = 0;
    3820           1 :         state->io.smb2.in.fname = fname;
    3821             : 
    3822           1 :         torture_comment(tctx, "LEVELII501: Test double break sequence\n");
    3823           1 :         ZERO_STRUCT(break_info);
    3824             : 
    3825           1 :         state->io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    3826             :                                 SEC_RIGHTS_FILE_WRITE;
    3827           1 :         state->io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3828             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    3829           1 :         state->io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3830           1 :         state->io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    3831             : 
    3832           1 :         tree1->session->transport->oplock.handler = torture_oplock_break_delay;
    3833           1 :         tree1->session->transport->oplock.private_data = state;
    3834             : 
    3835           1 :         status = smb2_create(tree1, tctx, &(state->io.smb2));
    3836           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    3837           1 :         state->h1 = state->io.smb2.out.file.handle;
    3838           1 :         CHECK_VAL(state->io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
    3839             : 
    3840             :         /*
    3841             :          * Trigger a break to level2
    3842             :          */
    3843             : 
    3844           1 :         req = smb2_create_send(tree2, &state->io.smb2);
    3845           1 :         req->async.fn = levelII501_open1_done;
    3846           1 :         req->async.private_data = state;
    3847             : 
    3848           1 :         te = tevent_add_timer(
    3849             :                 tctx->ev, tctx, tevent_timeval_current_ofs(0, 200000),
    3850             :                 levelII501_2ndopen_cb, state);
    3851           1 :         torture_assert(tctx, te != NULL, "tevent_add_timer failed\n");
    3852             : 
    3853           1 :         te = tevent_add_timer(
    3854             :                 tctx->ev, tctx, tevent_timeval_current_ofs(2, 0),
    3855             :                 levelII501_timeout_cb, state);
    3856           1 :         torture_assert(tctx, te != NULL, "tevent_add_timer failed\n");
    3857             : 
    3858          26 :         while (!state->done) {
    3859          24 :                 if (tevent_loop_once(tctx->ev) != 0) {
    3860           0 :                         torture_comment(tctx, "tevent_loop_once failed\n");
    3861             :                 }
    3862             :         }
    3863             : 
    3864           1 :         return ret;
    3865             : }
    3866             : 
    3867             : /*
    3868             :  * Fire off a second open after a little timeout
    3869             :  */
    3870             : 
    3871           1 : 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           1 :         struct levelII501_state *state = talloc_get_type_abort(
    3877             :                 private_data, struct levelII501_state);
    3878             :         struct smb2_request *req;
    3879             : 
    3880           1 :         state->io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
    3881           1 :         req = smb2_create_send(state->tree3, &state->io.smb2);
    3882           1 :         req->async.fn = levelII501_open2_done;
    3883           1 :         req->async.private_data = state;
    3884           1 : }
    3885             : 
    3886             : /*
    3887             :  * Postpone the break response by 500 msec
    3888             :  */
    3889           1 : 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           1 :         struct levelII501_state *state = talloc_get_type_abort(
    3894             :                 private_data, struct levelII501_state);
    3895             :         const char *name;
    3896             :         struct tevent_timer *te;
    3897             : 
    3898           1 :         break_info.handle       = *handle;
    3899           1 :         break_info.level        = level;
    3900           1 :         break_info.count++;
    3901             : 
    3902           1 :         state->break_handle = *handle;
    3903           1 :         state->break_to = level;
    3904             : 
    3905           1 :         switch(level) {
    3906           1 :         case SMB2_OPLOCK_LEVEL_II:
    3907           1 :                 name = "level II";
    3908           1 :                 break;
    3909           0 :         case SMB2_OPLOCK_LEVEL_NONE:
    3910           0 :                 name = "none";
    3911           0 :                 break;
    3912           0 :         default:
    3913           0 :                 name = "unknown";
    3914           0 :                 break;
    3915             :         }
    3916           1 :         printf("Got break to %s [0x%02X] in oplock handler, postponing "
    3917             :                "break response for 500msec\n", name, level);
    3918             : 
    3919           1 :         te = tevent_add_timer(
    3920             :                 state->tctx->ev, state->tctx,
    3921             :                 tevent_timeval_current_ofs(0, 500000),
    3922             :                 levelII501_break_timeout_cb, state);
    3923           1 :         torture_assert(state->tctx, te != NULL, "tevent_add_timer failed\n");
    3924             : 
    3925           1 :         return true;
    3926             : }
    3927             : 
    3928           1 : 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           1 :         struct levelII501_state *state = talloc_get_type_abort(
    3934             :                 private_data, struct levelII501_state);
    3935             :         struct smb2_request *req;
    3936             : 
    3937           1 :         talloc_free(te);
    3938             : 
    3939           1 :         ZERO_STRUCT(state->br);
    3940           1 :         state->br.in.file.handle = state->break_handle;
    3941           1 :         state->br.in.oplock_level = state->break_to;
    3942             : 
    3943           1 :         req = smb2_break_send(state->tree1, &state->br);
    3944           1 :         req->async.fn = levelII501_break_done;
    3945           1 :         req->async.private_data = state;
    3946           1 : }
    3947             : 
    3948           1 : static void levelII501_break_done(struct smb2_request *req)
    3949             : {
    3950             :         struct smb2_break io;
    3951             :         NTSTATUS status;
    3952             : 
    3953           1 :         status = smb2_break_recv(req, &io);
    3954           1 :         printf("break done: %s\n", nt_errstr(status));
    3955           1 : }
    3956             : 
    3957           1 : static void levelII501_open1_done(struct smb2_request *req)
    3958             : {
    3959           1 :         struct levelII501_state *state = talloc_get_type_abort(
    3960             :                 req->async.private_data, struct levelII501_state);
    3961             :         struct smb2_create io;
    3962             :         NTSTATUS status;
    3963             : 
    3964           1 :         status = smb2_create_recv(req, state, &io);
    3965           1 :         printf("open1 done: %s\n", nt_errstr(status));
    3966           1 : }
    3967             : 
    3968           1 : static void levelII501_open2_done(struct smb2_request *req)
    3969             : {
    3970           1 :         struct levelII501_state *state = talloc_get_type_abort(
    3971             :                 req->async.private_data, struct levelII501_state);
    3972             :         struct smb2_create io;
    3973             :         NTSTATUS status;
    3974             : 
    3975           1 :         status = smb2_create_recv(req, state, &io);
    3976           1 :         printf("open2 done: %s\n", nt_errstr(status));
    3977           1 : }
    3978             : 
    3979           1 : 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           1 :         struct levelII501_state *state = talloc_get_type_abort(
    3985             :                 private_data, struct levelII501_state);
    3986           1 :         talloc_free(te);
    3987           1 :         state->done = true;
    3988           1 : }
    3989             : 
    3990           1 : static bool test_smb2_oplock_levelII502(struct torture_context *tctx,
    3991             :                                         struct smb2_tree *tree1,
    3992             :                                         struct smb2_tree *tree2)
    3993             : 
    3994             : {
    3995           1 :         const char *fname = BASEDIR "\\test_levelII502.dat";
    3996             :         NTSTATUS status;
    3997             :         union smb_open io;
    3998             :         struct smb2_close closeio;
    3999             :         struct smb2_handle h;
    4000             : 
    4001           1 :         status = torture_smb2_testdir(tree1, BASEDIR, &h);
    4002           1 :         torture_assert_ntstatus_ok(tctx, status, "Error creating directory");
    4003             : 
    4004             :         /* cleanup */
    4005           1 :         smb2_util_unlink(tree1, fname);
    4006             : 
    4007             :         /*
    4008             :           base ntcreatex parms
    4009             :         */
    4010           1 :         ZERO_STRUCT(io.smb2);
    4011           1 :         io.generic.level = RAW_OPEN_SMB2;
    4012           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4013           1 :         io.smb2.in.alloc_size = 0;
    4014           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4015           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4016           1 :         io.smb2.in.create_options = 0;
    4017           1 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4018           1 :         io.smb2.in.security_flags = 0;
    4019           1 :         io.smb2.in.fname = fname;
    4020             : 
    4021           1 :         torture_comment(
    4022             :                 tctx,
    4023             :                 "LEVELII502: Open a stale LEVEL2 oplock with OVERWRITE");
    4024             : 
    4025           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
    4026             :                                 SEC_RIGHTS_FILE_WRITE;
    4027           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    4028             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    4029           1 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    4030           1 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_II;
    4031           1 :         status = smb2_create(tree1, tctx, &(io.smb2));
    4032           1 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    4033           1 :         torture_assert(tctx,
    4034             :                        io.smb2.out.oplock_level==SMB2_OPLOCK_LEVEL_II,
    4035             :                        "Did not get LEVEL_II oplock\n");
    4036             : 
    4037           0 :         status = smbXcli_conn_samba_suicide(
    4038           0 :                 tree1->session->transport->conn, 93);
    4039           0 :         torture_assert_ntstatus_ok(tctx, status, "suicide failed");
    4040             : 
    4041           0 :         sleep(1);
    4042             : 
    4043           0 :         io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    4044           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
    4045             : 
    4046           0 :         status = smb2_create(tree2, tctx, &(io.smb2));
    4047           0 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
    4048           0 :         torture_assert(tctx,
    4049             :                        io.smb2.out.oplock_level==SMB2_OPLOCK_LEVEL_BATCH,
    4050             :                        "Did not get BATCH oplock\n");
    4051             : 
    4052           0 :         closeio = (struct smb2_close) {
    4053             :                 .in.file.handle = io.smb2.out.file.handle,
    4054             :         };
    4055           0 :         status = smb2_close(tree2, &closeio);
    4056           0 :         torture_assert_ntstatus_equal(
    4057             :                 tctx, status, NT_STATUS_OK, "close failed");
    4058             : 
    4059           0 :         return true;
    4060             : }
    4061             : 
    4062          12 : 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          12 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    4068             :         struct smb2_create cr;
    4069          12 :         struct smb2_handle h1 = {{0}};
    4070          12 :         struct smb2_handle h2 = {{0}};
    4071             :         NTSTATUS status;
    4072          12 :         const char *fname = "oplock_statopen1.dat";
    4073          12 :         bool ret = true;
    4074             : 
    4075             :         /* Open file with exclusive oplock. */
    4076          12 :         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          12 :         status = smb2_create(tree, mem_ctx, &cr);
    4086          12 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4087             :                                         "smb2_create failed\n");
    4088          12 :         h1 = cr.out.file.handle;
    4089          12 :         CHECK_VAL(cr.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    4090             : 
    4091             :         /* Stat open */
    4092          12 :         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          12 :         status = smb2_create(tree, mem_ctx, &cr);
    4101          12 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4102             :                                         "smb2_create failed\n");
    4103          11 :         h2 = cr.out.file.handle;
    4104             : 
    4105          11 :         if (expect_stat_open) {
    4106           2 :                 torture_wait_for_oplock_break(tctx);
    4107           2 :                 CHECK_VAL(break_info.count, 0);
    4108           2 :                 CHECK_VAL(break_info.level, 0);
    4109           2 :                 CHECK_VAL(break_info.failures, 0);
    4110           2 :                 if (!ret) {
    4111           0 :                         goto done;
    4112             :                 }
    4113             :         } else {
    4114           9 :                 CHECK_VAL(break_info.count, 1);
    4115             :         }
    4116             : 
    4117          21 : done:
    4118          12 :         if (!smb2_util_handle_empty(h2)) {
    4119          11 :                 smb2_util_close(tree, h2);
    4120             :         }
    4121          12 :         if (!smb2_util_handle_empty(h1)) {
    4122          12 :                 smb2_util_close(tree, h1);
    4123             :         }
    4124          12 :         talloc_free(mem_ctx);
    4125          12 :         return ret;
    4126             : }
    4127             : 
    4128           1 : static bool test_smb2_oplock_statopen1(struct torture_context *tctx,
    4129             :                                        struct smb2_tree *tree)
    4130             : {
    4131           1 :         const char *fname = "oplock_statopen1.dat";
    4132             :         size_t i;
    4133           1 :         bool ret = true;
    4134             :         struct {
    4135             :                 uint32_t access_mask;
    4136             :                 bool expect_stat_open;
    4137           1 :         } 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           1 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4189           1 :         tree->session->transport->oplock.private_data = tree;
    4190             : 
    4191          24 :         for (i = 0; i < ARRAY_SIZE(tests); i++) {
    4192          12 :                 ZERO_STRUCT(break_info);
    4193             : 
    4194          12 :                 ret = test_oplock_statopen1_do(tctx,
    4195             :                                                tree,
    4196             :                                                tests[i].access_mask,
    4197          12 :                                                tests[i].expect_stat_open);
    4198          12 :                 if (ret == true) {
    4199          11 :                         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           0 : done:
    4211           1 :         smb2_util_unlink(tree, fname);
    4212           1 :         return ret;
    4213             : }
    4214             : 
    4215         964 : struct torture_suite *torture_smb2_oplocks_init(TALLOC_CTX *ctx)
    4216             : {
    4217         738 :         struct torture_suite *suite =
    4218         226 :             torture_suite_create(ctx, "oplock");
    4219             : 
    4220         964 :         torture_suite_add_2smb2_test(suite, "exclusive1", test_smb2_oplock_exclusive1);
    4221         964 :         torture_suite_add_2smb2_test(suite, "exclusive2", test_smb2_oplock_exclusive2);
    4222         964 :         torture_suite_add_2smb2_test(suite, "exclusive3", test_smb2_oplock_exclusive3);
    4223         964 :         torture_suite_add_2smb2_test(suite, "exclusive4", test_smb2_oplock_exclusive4);
    4224         964 :         torture_suite_add_2smb2_test(suite, "exclusive5", test_smb2_oplock_exclusive5);
    4225         964 :         torture_suite_add_2smb2_test(suite, "exclusive6", test_smb2_oplock_exclusive6);
    4226         964 :         torture_suite_add_2smb2_test(suite, "exclusive9",
    4227             :                                      test_smb2_oplock_exclusive9);
    4228         964 :         torture_suite_add_2smb2_test(suite, "batch1", test_smb2_oplock_batch1);
    4229         964 :         torture_suite_add_2smb2_test(suite, "batch2", test_smb2_oplock_batch2);
    4230         964 :         torture_suite_add_2smb2_test(suite, "batch3", test_smb2_oplock_batch3);
    4231         964 :         torture_suite_add_2smb2_test(suite, "batch4", test_smb2_oplock_batch4);
    4232         964 :         torture_suite_add_2smb2_test(suite, "batch5", test_smb2_oplock_batch5);
    4233         964 :         torture_suite_add_2smb2_test(suite, "batch6", test_smb2_oplock_batch6);
    4234         964 :         torture_suite_add_2smb2_test(suite, "batch7", test_smb2_oplock_batch7);
    4235         964 :         torture_suite_add_2smb2_test(suite, "batch8", test_smb2_oplock_batch8);
    4236         964 :         torture_suite_add_2smb2_test(suite, "batch9", test_smb2_oplock_batch9);
    4237         964 :         torture_suite_add_2smb2_test(suite, "batch9a", test_smb2_oplock_batch9a);
    4238         964 :         torture_suite_add_2smb2_test(suite, "batch10", test_smb2_oplock_batch10);
    4239         964 :         torture_suite_add_2smb2_test(suite, "batch11", test_smb2_oplock_batch11);
    4240         964 :         torture_suite_add_2smb2_test(suite, "batch12", test_smb2_oplock_batch12);
    4241         964 :         torture_suite_add_2smb2_test(suite, "batch13", test_smb2_oplock_batch13);
    4242         964 :         torture_suite_add_2smb2_test(suite, "batch14", test_smb2_oplock_batch14);
    4243         964 :         torture_suite_add_2smb2_test(suite, "batch15", test_smb2_oplock_batch15);
    4244         964 :         torture_suite_add_2smb2_test(suite, "batch16", test_smb2_oplock_batch16);
    4245         964 :         torture_suite_add_1smb2_test(suite, "batch19", test_smb2_oplock_batch19);
    4246         964 :         torture_suite_add_2smb2_test(suite, "batch20", test_smb2_oplock_batch20);
    4247         964 :         torture_suite_add_1smb2_test(suite, "batch21", test_smb2_oplock_batch21);
    4248         964 :         torture_suite_add_1smb2_test(suite, "batch22a", test_smb2_oplock_batch22a);
    4249         964 :         torture_suite_add_2smb2_test(suite, "batch22b", test_smb2_oplock_batch22b);
    4250         964 :         torture_suite_add_2smb2_test(suite, "batch23", test_smb2_oplock_batch23);
    4251         964 :         torture_suite_add_2smb2_test(suite, "batch24", test_smb2_oplock_batch24);
    4252         964 :         torture_suite_add_1smb2_test(suite, "batch25", test_smb2_oplock_batch25);
    4253         964 :         torture_suite_add_1smb2_test(suite, "batch26", test_smb2_oplock_batch26);
    4254         964 :         torture_suite_add_2smb2_test(suite, "stream1", test_raw_oplock_stream1);
    4255         964 :         torture_suite_add_2smb2_test(suite, "doc", test_smb2_oplock_doc);
    4256         964 :         torture_suite_add_2smb2_test(suite, "brl1", test_smb2_oplock_brl1);
    4257         964 :         torture_suite_add_1smb2_test(suite, "brl2", test_smb2_oplock_brl2);
    4258         964 :         torture_suite_add_1smb2_test(suite, "brl3", test_smb2_oplock_brl3);
    4259         964 :         torture_suite_add_1smb2_test(suite, "levelii500", test_smb2_oplock_levelII500);
    4260         964 :         torture_suite_add_2smb2_test(suite, "levelii501",
    4261             :                                      test_smb2_oplock_levelII501);
    4262         964 :         torture_suite_add_2smb2_test(suite, "levelii502",
    4263             :                                      test_smb2_oplock_levelII502);
    4264         964 :         torture_suite_add_1smb2_test(suite, "statopen1", test_smb2_oplock_statopen1);
    4265         964 :         suite->description = talloc_strdup(suite, "SMB2-OPLOCK tests");
    4266             : 
    4267         964 :         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             :         struct smb2_tree **trees;
    4277           0 :         bool ret = true;
    4278             :         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             :         union smb_open io;
    4284             :         struct timeval tv;
    4285             :         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             :         struct hold_oplock_info *info;
    4383             :         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             :         int i;
    4424             :         struct smb2_handle h;
    4425             :         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             :                 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           0 : static bool test_smb2_kernel_oplocks1(struct torture_context *tctx,
    4491             :                                       struct smb2_tree *tree)
    4492             : {
    4493           0 :         const char *fname = "test_kernel_oplock1.dat";
    4494             :         NTSTATUS status;
    4495           0 :         bool ret = true;
    4496             :         struct smb2_create create;
    4497           0 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4498             : 
    4499           0 :         smb2_util_unlink(tree, fname);
    4500             : 
    4501           0 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4502           0 :         tree->session->transport->oplock.private_data = tree;
    4503           0 :         ZERO_STRUCT(break_info);
    4504             : 
    4505           0 :         ZERO_STRUCT(create);
    4506           0 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4507           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4508           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    4509           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4510           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4511           0 :         create.in.fname = fname;
    4512           0 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    4513             : 
    4514           0 :         status = smb2_create(tree, tctx, &create);
    4515           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4516           0 :         h1 = create.out.file.handle;
    4517             : 
    4518           0 :         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           0 :         ZERO_STRUCT(create);
    4522           0 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4523           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4524           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4525           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4526           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4527           0 :         create.in.fname = fname;
    4528             : 
    4529           0 :         status = smb2_create(tree, tctx, &create);
    4530           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done,
    4531             :                                            "Open didn't return NT_STATUS_SHARING_VIOLATION\n");
    4532           0 :         h2 = create.out.file.handle;
    4533             : 
    4534           0 :         torture_wait_for_oplock_break(tctx);
    4535           0 :         if (break_info.count != 0) {
    4536           0 :                 torture_warning(tctx, "Open caused oplock break\n");
    4537             :         }
    4538             : 
    4539           0 :         smb2_util_close(tree, h1);
    4540           0 :         smb2_util_close(tree, h2);
    4541             : 
    4542           0 : done:
    4543           0 :         if (!smb2_util_handle_empty(h1)) {
    4544           0 :                 smb2_util_close(tree, h1);
    4545             :         }
    4546           0 :         if (!smb2_util_handle_empty(h2)) {
    4547           0 :                 smb2_util_close(tree, h2);
    4548             :         }
    4549           0 :         smb2_util_unlink(tree, fname);
    4550           0 :         return ret;
    4551             : }
    4552             : 
    4553           0 : static bool test_smb2_kernel_oplocks2(struct torture_context *tctx,
    4554             :                                       struct smb2_tree *tree)
    4555             : {
    4556           0 :         const char *fname = "test_kernel_oplock2.dat";
    4557           0 :         const char *sname = "test_kernel_oplock2.dat:foo";
    4558             :         NTSTATUS status;
    4559           0 :         bool ret = true;
    4560             :         struct smb2_create create;
    4561           0 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4562             : 
    4563           0 :         smb2_util_unlink(tree, fname);
    4564             : 
    4565           0 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4566           0 :         tree->session->transport->oplock.private_data = tree;
    4567           0 :         ZERO_STRUCT(break_info);
    4568             : 
    4569           0 :         ZERO_STRUCT(create);
    4570           0 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4571           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4572           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    4573           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4574           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4575           0 :         create.in.fname = fname;
    4576           0 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    4577             : 
    4578           0 :         status = smb2_create(tree, tctx, &create);
    4579           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4580           0 :         h1 = create.out.file.handle;
    4581             : 
    4582           0 :         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           0 :         ZERO_STRUCT(create);
    4586           0 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4587           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4588           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4589           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4590           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4591           0 :         create.in.fname = sname;
    4592             : 
    4593           0 :         status = smb2_create(tree, tctx, &create);
    4594           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4595           0 :         h2 = create.out.file.handle;
    4596             : 
    4597           0 :         torture_wait_for_oplock_break(tctx);
    4598           0 :         if (break_info.count != 0) {
    4599           0 :                 torture_warning(tctx, "Stream open caused oplock break\n");
    4600             :         }
    4601             : 
    4602           0 :         smb2_util_close(tree, h1);
    4603           0 :         smb2_util_close(tree, h2);
    4604             : 
    4605           0 : done:
    4606           0 :         if (!smb2_util_handle_empty(h1)) {
    4607           0 :                 smb2_util_close(tree, h1);
    4608             :         }
    4609           0 :         if (!smb2_util_handle_empty(h2)) {
    4610           0 :                 smb2_util_close(tree, h2);
    4611             :         }
    4612           0 :         smb2_util_unlink(tree, fname);
    4613           0 :         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           0 : static bool test_smb2_kernel_oplocks3(struct torture_context *tctx,
    4623             :                                       struct smb2_tree *tree,
    4624             :                                       struct smb2_tree *tree2)
    4625             : {
    4626           0 :         const char *fname = "test_kernel_oplock3.dat";
    4627             :         NTSTATUS status;
    4628           0 :         bool ret = true;
    4629             :         struct smb2_create create;
    4630           0 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4631             : 
    4632           0 :         smb2_util_unlink(tree, fname);
    4633           0 :         status = torture_smb2_testfile(tree, fname, &h1);
    4634           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4635             :                                         "Error creating testfile\n");
    4636           0 :         smb2_util_close(tree, h1);
    4637           0 :         ZERO_STRUCT(h1);
    4638             : 
    4639           0 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4640           0 :         tree->session->transport->oplock.private_data = tree;
    4641           0 :         ZERO_STRUCT(break_info);
    4642             : 
    4643             :         /* 1 */
    4644           0 :         ZERO_STRUCT(create);
    4645           0 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4646           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4647           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4648           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4649           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4650           0 :         create.in.fname = fname;
    4651           0 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    4652             : 
    4653           0 :         status = smb2_create(tree, tctx, &create);
    4654           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4655           0 :         h1 = create.out.file.handle;
    4656             : 
    4657           0 :         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           0 :         ZERO_STRUCT(create);
    4662           0 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4663           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4664           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4665           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    4666           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4667           0 :         create.in.fname = fname;
    4668             : 
    4669           0 :         status = smb2_create(tree2, tctx, &create);
    4670           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4671           0 :         h2 = create.out.file.handle;
    4672             : 
    4673           0 :         torture_wait_for_oplock_break(tctx);
    4674           0 :         torture_assert_goto(tctx, break_info.count == 1, ret, done, "Expected 1 oplock break\n");
    4675             : 
    4676           0 : done:
    4677           0 :         if (!smb2_util_handle_empty(h1)) {
    4678           0 :                 smb2_util_close(tree, h1);
    4679             :         }
    4680           0 :         if (!smb2_util_handle_empty(h2)) {
    4681           0 :                 smb2_util_close(tree, h2);
    4682             :         }
    4683           0 :         smb2_util_unlink(tree, fname);
    4684           0 :         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           0 : static bool test_smb2_kernel_oplocks4(struct torture_context *tctx,
    4695             :                                       struct smb2_tree *tree)
    4696             : {
    4697           0 :         const char *fname = "test_kernel_oplock4.dat";
    4698           0 :         const char *sname = "test_kernel_oplock4.dat:foo";
    4699             :         NTSTATUS status;
    4700           0 :         bool ret = true;
    4701             :         struct smb2_create create;
    4702           0 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4703             : 
    4704           0 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4705           0 :         tree->session->transport->oplock.private_data = tree;
    4706           0 :         ZERO_STRUCT(break_info);
    4707           0 :         smb2_util_unlink(tree, fname);
    4708             : 
    4709             :         /* 1 */
    4710           0 :         status = torture_smb2_testfile(tree, fname, &h1);
    4711           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4712             :                                         "Error creating testfile\n");
    4713           0 :         smb2_util_close(tree, h1);
    4714           0 :         ZERO_STRUCT(h1);
    4715             : 
    4716           0 :         ZERO_STRUCT(create);
    4717           0 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4718           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4719           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4720           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4721           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4722           0 :         create.in.fname = sname;
    4723             : 
    4724           0 :         status = smb2_create(tree, tctx, &create);
    4725           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4726           0 :         h1 = create.out.file.handle;
    4727           0 :         smb2_util_close(tree, h1);
    4728           0 :         ZERO_STRUCT(h1);
    4729             : 
    4730             :         /* 2 */
    4731           0 :         ZERO_STRUCT(create);
    4732           0 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4733           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4734           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
    4735           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    4736           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4737           0 :         create.in.fname = fname;
    4738           0 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    4739             : 
    4740           0 :         status = smb2_create(tree, tctx, &create);
    4741           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4742           0 :         h1 = create.out.file.handle;
    4743             : 
    4744           0 :         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           0 :         ZERO_STRUCT(create);
    4748           0 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4749           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4750           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
    4751           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    4752           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4753           0 :         create.in.fname = sname;
    4754             : 
    4755           0 :         status = smb2_create(tree, tctx, &create);
    4756           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4757           0 :         h2 = create.out.file.handle;
    4758             : 
    4759           0 :         torture_wait_for_oplock_break(tctx);
    4760           0 :         if (break_info.count != 0) {
    4761           0 :                 torture_warning(tctx, "Stream open caused oplock break\n");
    4762             :         }
    4763             : 
    4764           0 : done:
    4765           0 :         if (!smb2_util_handle_empty(h1)) {
    4766           0 :                 smb2_util_close(tree, h1);
    4767             :         }
    4768           0 :         if (!smb2_util_handle_empty(h2)) {
    4769           0 :                 smb2_util_close(tree, h2);
    4770             :         }
    4771           0 :         smb2_util_unlink(tree, fname);
    4772           0 :         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           0 : static bool test_smb2_kernel_oplocks5(struct torture_context *tctx,
    4783             :                                       struct smb2_tree *tree)
    4784             : {
    4785           0 :         const char *fname = "test_kernel_oplock4.dat";
    4786           0 :         const char *sname = "test_kernel_oplock4.dat:foo";
    4787             :         NTSTATUS status;
    4788           0 :         bool ret = true;
    4789             :         struct smb2_create create;
    4790           0 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4791             : 
    4792           0 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4793           0 :         tree->session->transport->oplock.private_data = tree;
    4794           0 :         ZERO_STRUCT(break_info);
    4795           0 :         smb2_util_unlink(tree, fname);
    4796             : 
    4797             :         /* 1 */
    4798           0 :         status = torture_smb2_testfile(tree, fname, &h1);
    4799           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4800             :                                         "Error creating testfile\n");
    4801           0 :         smb2_util_close(tree, h1);
    4802           0 :         ZERO_STRUCT(h1);
    4803             : 
    4804           0 :         ZERO_STRUCT(create);
    4805           0 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4806           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4807           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4808           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4809           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4810           0 :         create.in.fname = sname;
    4811             : 
    4812           0 :         status = smb2_create(tree, tctx, &create);
    4813           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4814           0 :         h1 = create.out.file.handle;
    4815           0 :         smb2_util_close(tree, h1);
    4816           0 :         ZERO_STRUCT(h1);
    4817             : 
    4818             :         /* 2 */
    4819           0 :         ZERO_STRUCT(create);
    4820           0 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4821           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4822           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4823           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    4824           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4825           0 :         create.in.fname = sname;
    4826           0 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    4827             : 
    4828           0 :         status = smb2_create(tree, tctx, &create);
    4829           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4830           0 :         h1 = create.out.file.handle;
    4831             : 
    4832           0 :         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           0 :         ZERO_STRUCT(create);
    4836           0 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4837           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4838           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4839           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    4840           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4841           0 :         create.in.fname = sname;
    4842           0 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
    4843             : 
    4844           0 :         status = smb2_create(tree, tctx, &create);
    4845           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4846           0 :         h2 = create.out.file.handle;
    4847             : 
    4848           0 :         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           0 :         torture_wait_for_oplock_break(tctx);
    4852           0 :         if (break_info.count != 1) {
    4853           0 :                 torture_warning(tctx, "Stream open didn't cause oplock break\n");
    4854             :         }
    4855             : 
    4856           0 : done:
    4857           0 :         if (!smb2_util_handle_empty(h1)) {
    4858           0 :                 smb2_util_close(tree, h1);
    4859             :         }
    4860           0 :         if (!smb2_util_handle_empty(h2)) {
    4861           0 :                 smb2_util_close(tree, h2);
    4862             :         }
    4863           0 :         smb2_util_unlink(tree, fname);
    4864           0 :         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           0 : static bool test_smb2_kernel_oplocks6(struct torture_context *tctx,
    4875             :                                       struct smb2_tree *tree,
    4876             :                                       struct smb2_tree *tree2)
    4877             : {
    4878           0 :         const char *fname = "test_kernel_oplock6.dat";
    4879           0 :         const char *sname = "test_kernel_oplock6.dat:foo";
    4880             :         NTSTATUS status;
    4881           0 :         bool ret = true;
    4882             :         struct smb2_create create;
    4883           0 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4884             : 
    4885           0 :         smb2_util_unlink(tree, fname);
    4886           0 :         status = torture_smb2_testfile(tree, fname, &h1);
    4887           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4888             :                                         "Error creating testfile\n");
    4889           0 :         smb2_util_close(tree, h1);
    4890           0 :         ZERO_STRUCT(h1);
    4891             : 
    4892           0 :         tree->session->transport->oplock.handler = torture_oplock_handler;
    4893           0 :         tree->session->transport->oplock.private_data = tree;
    4894           0 :         ZERO_STRUCT(break_info);
    4895             : 
    4896             :         /* 1 */
    4897           0 :         ZERO_STRUCT(create);
    4898           0 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4899           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4900           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4901           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4902           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4903           0 :         create.in.fname = sname;
    4904             : 
    4905           0 :         status = smb2_create(tree, tctx, &create);
    4906           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4907           0 :         h1 = create.out.file.handle;
    4908           0 :         smb2_util_close(tree, h1);
    4909           0 :         ZERO_STRUCT(h1);
    4910             : 
    4911             :         /* 2 */
    4912           0 :         ZERO_STRUCT(create);
    4913           0 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4914           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4915           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4916           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    4917           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4918           0 :         create.in.fname = fname;
    4919           0 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    4920             : 
    4921           0 :         status = smb2_create(tree, tctx, &create);
    4922           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4923           0 :         h1 = create.out.file.handle;
    4924             : 
    4925           0 :         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           0 :         ZERO_STRUCT(create);
    4930           0 :         create.in.desired_access = SEC_RIGHTS_FILE_READ;
    4931           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    4932           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    4933           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    4934           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4935           0 :         create.in.fname = fname;
    4936             : 
    4937           0 :         status = smb2_create(tree2, tctx, &create);
    4938           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n");
    4939           0 :         h2 = create.out.file.handle;
    4940             : 
    4941           0 :         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           0 :         torture_wait_for_oplock_break(tctx);
    4945           0 :         torture_assert_goto(tctx, break_info.count == 1, ret, done, "Expected 1 oplock break\n");
    4946             : 
    4947           0 : done:
    4948           0 :         if (!smb2_util_handle_empty(h1)) {
    4949           0 :                 smb2_util_close(tree, h1);
    4950             :         }
    4951           0 :         if (!smb2_util_handle_empty(h2)) {
    4952           0 :                 smb2_util_close(tree, h2);
    4953             :         }
    4954           0 :         smb2_util_unlink(tree, fname);
    4955           0 :         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           0 : static bool test_smb2_kernel_oplocks7(struct torture_context *tctx,
    4972             :                                       struct smb2_tree *tree,
    4973             :                                       struct smb2_tree *tree2)
    4974             : {
    4975           0 :         const char *fname = "test_kernel_oplock7.dat";
    4976             :         NTSTATUS status;
    4977           0 :         bool ret = true;
    4978             :         struct smb2_create create;
    4979           0 :         struct smb2_handle h1 = {{0}}, h2 = {{0}};
    4980             :         struct smb2_create create_2;
    4981             :         struct smb2_create io;
    4982             :         struct smb2_request *req;
    4983             : 
    4984           0 :         smb2_util_unlink(tree, fname);
    4985           0 :         status = torture_smb2_testfile(tree, fname, &h1);
    4986           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4987             :                                         "Error creating testfile\n");
    4988           0 :         smb2_util_close(tree, h1);
    4989           0 :         ZERO_STRUCT(h1);
    4990             : 
    4991             :         /* Close the open file on break. */
    4992           0 :         tree->session->transport->oplock.handler = torture_oplock_handler_close;
    4993           0 :         tree->session->transport->oplock.private_data = tree;
    4994           0 :         ZERO_STRUCT(break_info);
    4995             : 
    4996             :         /* 1 - open file with oplock */
    4997           0 :         ZERO_STRUCT(create);
    4998           0 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    4999           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    5000           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    5001           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN;
    5002           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    5003           0 :         create.in.fname = fname;
    5004           0 :         create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
    5005             : 
    5006           0 :         status = smb2_create(tree, tctx, &create);
    5007           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5008             :                         "Error opening the file\n");
    5009           0 :         CHECK_VAL(create.out.oplock_level, SMB2_OPLOCK_LEVEL_EXCLUSIVE);
    5010             : 
    5011             :         /* 2 - open file to break oplock */
    5012           0 :         ZERO_STRUCT(create_2);
    5013           0 :         create_2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    5014           0 :         create_2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    5015           0 :         create_2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
    5016           0 :         create_2.in.create_disposition = NTCREATEX_DISP_OPEN;
    5017           0 :         create_2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    5018           0 :         create_2.in.fname = fname;
    5019           0 :         create_2.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
    5020             : 
    5021             :         /* Open on tree2 - should cause a break on tree */
    5022           0 :         req = smb2_create_send(tree2, &create_2);
    5023           0 :         torture_assert(tctx, req != NULL, "smb2_create_send");
    5024             : 
    5025             :         /* The oplock break handler should close the file. */
    5026             :         /* Steps 3 & 4. */
    5027           0 :         torture_wait_for_oplock_break(tctx);
    5028             : 
    5029           0 :         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           0 :         status = smb2_create(tree, tctx, &create);
    5040           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5041             :                         "Error opening the file\n");
    5042             : 
    5043           0 :         h1 = create.out.file.handle;
    5044           0 :         if (create.out.oplock_level != SMB2_OPLOCK_LEVEL_EXCLUSIVE &&
    5045           0 :             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           0 :         status = smb2_create_recv(req, tctx, &io);
    5058           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5059             :                         "Error opening the file\n");
    5060           0 :         h2 = io.out.file.handle;
    5061           0 :         CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
    5062             : 
    5063           0 : done:
    5064           0 :         if (!smb2_util_handle_empty(h1)) {
    5065           0 :                 smb2_util_close(tree, h1);
    5066             :         }
    5067           0 :         if (!smb2_util_handle_empty(h2)) {
    5068           0 :                 smb2_util_close(tree2, h2);
    5069             :         }
    5070           0 :         smb2_util_unlink(tree, fname);
    5071           0 :         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             :         struct sigaction act;
    5112             :         sigset_t set;
    5113             :         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           0 : static bool wait_for_child_oplock(struct torture_context *tctx,
    5207             :                                 const char *localdir,
    5208             :                                 const char *fname)
    5209             : {
    5210             :         int fds[2];
    5211             :         int ret;
    5212             :         pid_t pid;
    5213           0 :         char *name = talloc_asprintf(tctx,
    5214             :                                 "%s/%s",
    5215             :                                 localdir,
    5216             :                                 fname);
    5217             : 
    5218           0 :         torture_assert(tctx, name != NULL, "talloc failed");
    5219             : 
    5220           0 :         ret = pipe(fds);
    5221           0 :         torture_assert(tctx, ret != -1, "pipe failed");
    5222             : 
    5223           0 :         pid = fork();
    5224           0 :         torture_assert(tctx, pid != (pid_t)-1, "fork failed");
    5225             : 
    5226           0 :         if (pid != (pid_t)0) {
    5227             :                 char c;
    5228             :                 /* Parent. */
    5229           0 :                 TALLOC_FREE(name);
    5230           0 :                 close(fds[1]);
    5231           0 :                 ret = sys_read(fds[0], &c, 1);
    5232           0 :                 torture_assert(tctx, ret == 1, "read failed");
    5233           0 :                 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           0 : 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           0 :         int *pstatus = (int *)private_data;
    5259           0 :         int status = 0;
    5260             : 
    5261           0 :         wait(&status);
    5262           0 :         if (WIFEXITED(status)) {
    5263           0 :                 *pstatus = WEXITSTATUS(status);
    5264             :         } else {
    5265           0 :                 *pstatus = status;
    5266             :         }
    5267           0 : }
    5268             : 
    5269             : /*
    5270             :  * Deal with a non-smbd process holding a kernel oplock.
    5271             :  */
    5272             : 
    5273           0 : static bool test_smb2_kernel_oplocks8(struct torture_context *tctx,
    5274             :                                       struct smb2_tree *tree)
    5275             : {
    5276           0 :         const char *fname = "test_kernel_oplock8.dat";
    5277           0 :         const char *fname1 = "tmp_test_kernel_oplock8.dat";
    5278             :         NTSTATUS status;
    5279           0 :         bool ret = true;
    5280             :         struct smb2_create io;
    5281           0 :         struct smb2_request *req = NULL;
    5282           0 :         struct smb2_handle h1 = {{0}};
    5283           0 :         struct smb2_handle h2 = {{0}};
    5284           0 :         const char *localdir = torture_setting_string(tctx, "localdir", NULL);
    5285           0 :         struct tevent_signal *se = NULL;
    5286           0 :         int child_exit_code = -1;
    5287             :         time_t start;
    5288             :         time_t end;
    5289             : 
    5290             : #ifndef HAVE_KERNEL_OPLOCKS_LINUX
    5291             :         torture_skip(tctx, "Need kernel oplocks for test");
    5292             : #endif
    5293             : 
    5294           0 :         if (localdir == NULL) {
    5295           0 :                 torture_skip(tctx, "Need localdir for test");
    5296             :         }
    5297             : 
    5298           0 :         smb2_util_unlink(tree, fname);
    5299           0 :         smb2_util_unlink(tree, fname1);
    5300           0 :         status = torture_smb2_testfile(tree, fname, &h1);
    5301           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5302             :                                         "Error creating testfile\n");
    5303           0 :         smb2_util_close(tree, h1);
    5304           0 :         ZERO_STRUCT(h1);
    5305             : 
    5306           0 :         se = tevent_add_signal(tctx->ev,
    5307             :                                 tctx,
    5308             :                                 SIGCHLD,
    5309             :                                 0,
    5310             :                                 child_sig_term_handler,
    5311             :                                 &child_exit_code);
    5312           0 :         torture_assert(tctx, se != NULL, "tevent_add_signal failed\n");
    5313             : 
    5314             :         /* Take the oplock locally in a sub-process. */
    5315           0 :         ret = wait_for_child_oplock(tctx, localdir, fname);
    5316           0 :         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           0 :         ZERO_STRUCT(io);
    5325           0 :         io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
    5326           0 :         io.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
    5327           0 :         io.in.create_disposition = NTCREATEX_DISP_OPEN;
    5328           0 :         io.in.share_access =
    5329             :                 NTCREATEX_SHARE_ACCESS_DELETE|
    5330             :                 NTCREATEX_SHARE_ACCESS_READ|
    5331             :                 NTCREATEX_SHARE_ACCESS_WRITE;
    5332           0 :         io.in.create_options = 0;
    5333           0 :         io.in.fname = fname;
    5334             : 
    5335           0 :         req = smb2_create_send(tree, &io);
    5336           0 :         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           0 :         io.in.fname = fname1;
    5342           0 :         io.in.create_disposition = NTCREATEX_DISP_CREATE;
    5343             : 
    5344             :         /* Time the start -> end of the request. */
    5345           0 :         start = time(NULL);
    5346           0 :         status = smb2_create(tree, tctx, &io);
    5347           0 :         end = time(NULL);
    5348             : 
    5349             :         /* Should succeed. */
    5350           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5351             :                         "Error opening the second file\n");
    5352           0 :         h1 = io.out.file.handle;
    5353             : 
    5354             :         /* in less than 2 seconds. Otherwise the server blocks. */
    5355           0 :         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           0 :         status = smb2_create_recv(req, tctx, &io);
    5360             : 
    5361             :         /* Which should also have succeeded. */
    5362           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5363             :                         "Error opening the file\n");
    5364           0 :         h2 = io.out.file.handle;
    5365             : 
    5366             :         /* Wait for the exit code from the child. */
    5367           0 :         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           0 :         torture_assert_int_equal_goto(tctx, child_exit_code, 0,
    5374             :                                       ret, done, "Bad child exit code");
    5375             : 
    5376           0 : done:
    5377           0 :         if (!smb2_util_handle_empty(h1)) {
    5378           0 :                 smb2_util_close(tree, h1);
    5379             :         }
    5380           0 :         if (!smb2_util_handle_empty(h2)) {
    5381           0 :                 smb2_util_close(tree, h2);
    5382             :         }
    5383           0 :         smb2_util_unlink(tree, fname);
    5384           0 :         smb2_util_unlink(tree, fname1);
    5385           0 :         return ret;
    5386             : }
    5387             : 
    5388         964 : struct torture_suite *torture_smb2_kernel_oplocks_init(TALLOC_CTX *ctx)
    5389             : {
    5390         738 :         struct torture_suite *suite =
    5391         226 :             torture_suite_create(ctx, "kernel-oplocks");
    5392             : 
    5393         964 :         torture_suite_add_1smb2_test(suite, "kernel_oplocks1", test_smb2_kernel_oplocks1);
    5394         964 :         torture_suite_add_1smb2_test(suite, "kernel_oplocks2", test_smb2_kernel_oplocks2);
    5395         964 :         torture_suite_add_2smb2_test(suite, "kernel_oplocks3", test_smb2_kernel_oplocks3);
    5396         964 :         torture_suite_add_1smb2_test(suite, "kernel_oplocks4", test_smb2_kernel_oplocks4);
    5397         964 :         torture_suite_add_1smb2_test(suite, "kernel_oplocks5", test_smb2_kernel_oplocks5);
    5398         964 :         torture_suite_add_2smb2_test(suite, "kernel_oplocks6", test_smb2_kernel_oplocks6);
    5399         964 :         torture_suite_add_2smb2_test(suite, "kernel_oplocks7", test_smb2_kernel_oplocks7);
    5400         964 :         torture_suite_add_1smb2_test(suite, "kernel_oplocks8", test_smb2_kernel_oplocks8);
    5401             : 
    5402         964 :         suite->description = talloc_strdup(suite, "SMB2-KERNEL-OPLOCK tests");
    5403             : 
    5404         964 :         return suite;
    5405             : }

Generated by: LCOV version 1.13