LCOV - code coverage report
Current view: top level - source4/torture/smb2 - oplock.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 2834 3063 92.5 %
Date: 2021-09-23 10:06:22 Functions: 71 77 92.2 %

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

Generated by: LCOV version 1.13