r12542: Move some more prototypes out to seperate headers
[kai/samba-autobuild/.git] / source4 / torture / raw / oplock.c
index dc8c883f769cd9410a81ab50b39c0e87e281be7c..4b67ce5cac5336c16b764aaf8bbc2d66f33df02b 100644 (file)
 */
 
 #include "includes.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "libcli/raw/libcliraw.h"
 
 #define CHECK_VAL(v, correct) do { \
        if ((v) != (correct)) { \
-               printf("(%d) wrong value for %s  0x%x - 0x%x\n", \
+               printf("(%d) wrong value for %s  got 0x%x - should be 0x%x\n", \
                       __LINE__, #v, (int)v, (int)correct); \
                ret = False; \
        }} while (0)
 
 static struct {
        int fnum;
-       unsigned char level;
+       uint8_t level;
        int count;
 } break_info;
 
 /*
   a handler function for oplock break requests
 */
-static BOOL oplock_handler_ack(struct cli_transport *transport, uint16 tid, uint16 fnum, uint8 level, void *private)
+static BOOL oplock_handler_ack(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private)
 {
-       struct cli_tree *tree = private;
+       struct smbcli_tree *tree = private;
        break_info.fnum = fnum;
        break_info.level = level;
        break_info.count++;
 
        printf("Acking in oplock handler\n");
 
-       return cli_oplock_ack(tree, fnum, level == 1? 0x102 : 2);
+       return smbcli_oplock_ack(tree, fnum, level);
 }
 
 /*
   a handler function for oplock break requests - close the file
 */
-static BOOL oplock_handler_close(struct cli_transport *transport, uint16 tid, uint16 fnum, uint8 level, void *private)
+static BOOL oplock_handler_close(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private)
 {
        union smb_close io;
        NTSTATUS status;
-       struct cli_tree *tree = private;
+       struct smbcli_tree *tree = private;
 
        break_info.fnum = fnum;
        break_info.level = level;
@@ -87,7 +89,7 @@ static BOOL oplock_handler_close(struct cli_transport *transport, uint16 tid, ui
 /*
   test oplock ops
 */
-static BOOL test_oplock(struct cli_state *cli, TALLOC_CTX *mem_ctx)
+static BOOL test_oplock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
 {
        const char *fname = "\\test_oplock.dat";
        NTSTATUS status;
@@ -95,19 +97,19 @@ static BOOL test_oplock(struct cli_state *cli, TALLOC_CTX *mem_ctx)
        union smb_open io;
        struct smb_unlink unl;
        union smb_read rd;
-       uint16 fnum, fnum2;
+       uint16_t fnum=0, fnum2=0;
 
        /* cleanup */
-       cli_unlink(cli->tree, fname);
+       smbcli_unlink(cli->tree, fname);
 
-       cli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
+       smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
 
        /*
          base ntcreatex parms
        */
        io.generic.level = RAW_OPEN_NTCREATEX;
        io.ntcreatex.in.root_fid = 0;
-       io.ntcreatex.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
        io.ntcreatex.in.alloc_size = 0;
        io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
        io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
@@ -133,7 +135,7 @@ static BOOL test_oplock(struct cli_state *cli, TALLOC_CTX *mem_ctx)
        CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
        CHECK_VAL(break_info.count, 0);
 
-       cli_close(cli->tree, fnum);
+       smbcli_close(cli->tree, fnum);
 
        /*
          with a batch oplock we get a break
@@ -155,15 +157,15 @@ static BOOL test_oplock(struct cli_state *cli, TALLOC_CTX *mem_ctx)
        CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
 
        CHECK_VAL(break_info.fnum, fnum);
-       CHECK_VAL(break_info.level, 2);
+       CHECK_VAL(break_info.level, 1);
        CHECK_VAL(break_info.count, 1);
 
 
-       cli_close(cli->tree, fnum);
+       smbcli_close(cli->tree, fnum);
 
        printf("if we close on break then the unlink can succeed\n");
        ZERO_STRUCT(break_info);
-       cli_oplock_handler(cli->transport, oplock_handler_close, cli->tree);
+       smbcli_oplock_handler(cli->transport, oplock_handler_close, cli->tree);
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
                NTCREATEX_FLAGS_REQUEST_OPLOCK | 
                NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
@@ -179,13 +181,13 @@ static BOOL test_oplock(struct cli_state *cli, TALLOC_CTX *mem_ctx)
        CHECK_STATUS(status, NT_STATUS_OK);
 
        CHECK_VAL(break_info.fnum, fnum);
-       CHECK_VAL(break_info.level, 2);
+       CHECK_VAL(break_info.level, 1);
        CHECK_VAL(break_info.count, 1);
 
        printf("a self read should not cause a break\n");
        ZERO_STRUCT(break_info);
-       cli_close(cli->tree, fnum);
-       cli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
+       smbcli_close(cli->tree, fnum);
+       smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
 
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
                NTCREATEX_FLAGS_REQUEST_OPLOCK | 
@@ -207,8 +209,8 @@ static BOOL test_oplock(struct cli_state *cli, TALLOC_CTX *mem_ctx)
 
        printf("a 2nd open should give a break\n");
        ZERO_STRUCT(break_info);
-       cli_close(cli->tree, fnum);
-       cli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
+       smbcli_close(cli->tree, fnum);
+       smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
 
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
                NTCREATEX_FLAGS_REQUEST_OPLOCK | 
@@ -226,12 +228,12 @@ static BOOL test_oplock(struct cli_state *cli, TALLOC_CTX *mem_ctx)
 
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum);
-       CHECK_VAL(break_info.level, 2);
+       CHECK_VAL(break_info.level, 1);
 
        printf("a 2nd open should get an oplock when we close instead of ack\n");
        ZERO_STRUCT(break_info);
-       cli_close(cli->tree, fnum);
-       cli_oplock_handler(cli->transport, oplock_handler_close, cli->tree);
+       smbcli_close(cli->tree, fnum);
+       smbcli_oplock_handler(cli->transport, oplock_handler_close, cli->tree);
 
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
                NTCREATEX_FLAGS_REQUEST_OPLOCK | 
@@ -253,12 +255,192 @@ static BOOL test_oplock(struct cli_state *cli, TALLOC_CTX *mem_ctx)
 
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum2);
-       CHECK_VAL(break_info.level, 2);
+       CHECK_VAL(break_info.level, 1);
        
+       smbcli_close(cli->tree, fnum);
+
+       printf("open with batch oplock\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       ZERO_STRUCT(break_info);
+       printf("second open with attributes only shouldn't cause oplock break\n");
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.fnum, 0);
+       CHECK_VAL(break_info.level, 0);
+
+       smbcli_close(cli->tree, fnum);
+       smbcli_close(cli->tree, fnum2);
+       smbcli_unlink(cli->tree, fname);
+
+       printf("open with attributes only can create file\n");
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       printf("Subsequent normal open should break oplock on attribute only open to level II\n");
+
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.fnum;
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum);
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+       smbcli_close(cli->tree, fnum2);
+
+       printf("third oplocked open should grant level2 without break\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.fnum;
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+
+       ZERO_STRUCT(break_info);
+
+       printf("write should trigger a break to none on both\n");
+       {
+               union smb_write wr;
+               wr.write.level = RAW_WRITE_WRITE;
+               wr.write.in.fnum = fnum2;
+               wr.write.in.count = 1;
+               wr.write.in.offset = 0;
+               wr.write.in.remaining = 0;
+               wr.write.in.data = "x";
+               status = smb_raw_write(cli->tree, &wr);
+               CHECK_STATUS(status, NT_STATUS_OK);
+       }
+
+       /* Now the oplock break request comes in. But right now we can't
+        * answer it. Do another write */
+
+       msleep(100);
+       
+       {
+               union smb_write wr;
+               wr.write.level = RAW_WRITE_WRITE;
+               wr.write.in.fnum = fnum2;
+               wr.write.in.count = 1;
+               wr.write.in.offset = 0;
+               wr.write.in.remaining = 0;
+               wr.write.in.data = "x";
+               status = smb_raw_write(cli->tree, &wr);
+               CHECK_STATUS(status, NT_STATUS_OK);
+       }
+
+       CHECK_VAL(break_info.count, 2);
+       CHECK_VAL(break_info.level, 0);
+
+       smbcli_close(cli->tree, fnum);
+       smbcli_close(cli->tree, fnum2);
+
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
+
+       printf("Open with oplock after a on-oplock open should grant level2\n");
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.fnum;
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.fnum, 0);
+       CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.fnum;
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.fnum, 0);
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+
+       printf("write should trigger a break to none\n");
+       {
+               union smb_write wr;
+               wr.write.level = RAW_WRITE_WRITE;
+               wr.write.in.fnum = fnum;
+               wr.write.in.count = 1;
+               wr.write.in.offset = 0;
+               wr.write.in.remaining = 0;
+               wr.write.in.data = "x";
+               status = smb_raw_write(cli->tree, &wr);
+               CHECK_STATUS(status, NT_STATUS_OK);
+       }
+
+       /* Now the oplock break request comes in. But right now we can't
+        * answer it. Do another write */
+
+       msleep(100);
+       
+       {
+               union smb_write wr;
+               wr.write.level = RAW_WRITE_WRITE;
+               wr.write.in.fnum = fnum;
+               wr.write.in.count = 1;
+               wr.write.in.offset = 0;
+               wr.write.in.remaining = 0;
+               wr.write.in.data = "x";
+               status = smb_raw_write(cli->tree, &wr);
+               CHECK_STATUS(status, NT_STATUS_OK);
+       }
+
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum2);
+       CHECK_VAL(break_info.level, 0);
 
 done:
-       cli_close(cli->tree, fnum);
-       cli_unlink(cli->tree, fname);
+       smbcli_close(cli->tree, fnum);
+       smbcli_close(cli->tree, fnum2);
+       smbcli_unlink(cli->tree, fname);
        return ret;
 }
 
@@ -266,9 +448,9 @@ done:
 /* 
    basic testing of oplocks
 */
-BOOL torture_raw_oplock(int dummy)
+BOOL torture_raw_oplock(void)
 {
-       struct cli_state *cli1;
+       struct smbcli_state *cli1;
        BOOL ret = True;
        TALLOC_CTX *mem_ctx;
 
@@ -283,6 +465,6 @@ BOOL torture_raw_oplock(int dummy)
        }
 
        torture_close_connection(cli1);
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
        return ret;
 }