fixed SMB2 flush call, and added flush to gentest_smb2
[kai/samba.git] / source4 / torture / gentest_smb2.c
index 629c04d073caace10c7d01c6ce2d82525b691967..fc6dbcbb9ae0d7339bc6d43d1db6900f1f285b8f 100644 (file)
 
 /* global options */
 static struct gentest_options {
-       bool showall;
-       bool analyze;
-       bool analyze_always;
-       bool analyze_continuous;
+       int showall;
+       int analyze;
+       int analyze_always;
+       int analyze_continuous;
        uint_t max_open_handles;
        uint_t seed;
        uint_t numops;
-       bool use_oplocks;
+       int use_oplocks;
        char **ignore_patterns;
        const char *seeds_file;
-       bool use_preset_seeds;
-       bool fast_reconnect;
+       int use_preset_seeds;
+       int fast_reconnect;
 } options;
 
 /* mapping between open handles on the server and local handles */
@@ -349,8 +349,8 @@ static uint16_t gen_fnum(int instance)
 */
 static uint16_t gen_fnum_close(int instance)
 {
-       if (num_open_handles < 3) {
-               if (gen_chance(80)) return BAD_HANDLE;
+       if (num_open_handles < 5) {
+               if (gen_chance(90)) return BAD_HANDLE;
        }
 
        return gen_fnum(instance);
@@ -359,7 +359,7 @@ static uint16_t gen_fnum_close(int instance)
 /*
   generate an integer in a specified range
 */
-static int gen_int_range(uint_t min, uint_t max)
+static int gen_int_range(uint64_t min, uint64_t max)
 {
        uint_t r = random();
        return min + (r % (1+max-min));
@@ -381,6 +381,7 @@ static uint16_t gen_root_fid(int instance)
 static int gen_offset(void)
 {
        if (gen_chance(20)) return 0;
+//     if (gen_chance(5)) return gen_int_range(0, 0xFFFFFFFF);
        return gen_int_range(0, 1024*1024);
 }
 
@@ -390,6 +391,7 @@ static int gen_offset(void)
 static int gen_io_count(void)
 {
        if (gen_chance(20)) return 0;
+//     if (gen_chance(5)) return gen_int_range(0, 0xFFFFFFFF);
        return gen_int_range(0, 4096);
 }
 
@@ -528,13 +530,16 @@ static uint16_t gen_rename_flags(void)
 
 
 /*
-  return a lockingx lock mode
+  return a set of lock flags
 */
-static uint16_t gen_lock_mode(void)
+static uint16_t gen_lock_flags(void)
 {
        if (gen_chance(5))  return gen_bits_mask(0xFFFF);
        if (gen_chance(20)) return gen_bits_mask(0x1F);
-       return gen_bits_mask(LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES);
+       if (gen_chance(50)) return SMB2_LOCK_FLAG_UNLOCK;
+       return gen_bits_mask(SMB2_LOCK_FLAG_SHARED | 
+                            SMB2_LOCK_FLAG_EXCLUSIVE | 
+                            SMB2_LOCK_FLAG_FAIL_IMMEDIATELY);
 }
 
 /*
@@ -568,8 +573,8 @@ static uint32_t gen_ntcreatex_flags(void)
 */
 static uint32_t gen_access_mask(void)
 {
-       if (gen_chance(50)) return SEC_FLAG_MAXIMUM_ALLOWED;
-       if (gen_chance(20)) return SEC_FILE_ALL;
+       if (gen_chance(70)) return SEC_FLAG_MAXIMUM_ALLOWED;
+       if (gen_chance(70)) return SEC_FILE_ALL;
        return gen_bits_mask(0xFFFFFFFF);
 }
 
@@ -588,6 +593,7 @@ static uint32_t gen_create_options(void)
 */
 static uint32_t gen_open_disp(void)
 {
+       if (gen_chance(50)) return NTCREATEX_DISP_OPEN_IF;
        if (gen_chance(10)) return gen_bits_mask(0xFFFFFFFF);
        return gen_int_range(0, 5);
 }
@@ -997,20 +1003,20 @@ again:
 /*
   generate ntcreatex operations
 */
-static bool handler_ntcreatex(int instance)
+static bool handler_create(int instance)
 {
        struct smb2_create parm[NSERVERS];
        NTSTATUS status[NSERVERS];
 
        ZERO_STRUCT(parm[0]);
-       parm[0].in.security_flags             = gen_bits_levels(3, 70, 0x0, 70, 0x3, 100, 0xFF);
-       parm[0].in.oplock_level               = gen_bits_levels(3, 70, 0x0, 70, 0x9, 100, 0xFF);
-       parm[0].in.impersonation_level        = gen_bits_levels(3, 70, 0x0, 70, 0x3, 100, 0xFFFFFFFF);
-       parm[0].in.create_flags               = gen_bits_levels(2, 80, 0x0, 100, 0xFFFFFFFF);
+       parm[0].in.security_flags             = gen_bits_levels(3, 90, 0x0, 70, 0x3, 100, 0xFF);
+       parm[0].in.oplock_level               = gen_bits_levels(3, 90, 0x0, 70, 0x9, 100, 0xFF);
+       parm[0].in.impersonation_level        = gen_bits_levels(3, 90, 0x0, 70, 0x3, 100, 0xFFFFFFFF);
+       parm[0].in.create_flags               = gen_bits_levels(2, 90, 0x0, 100, 0xFFFFFFFF);
        if (gen_chance(2)) {
                parm[0].in.create_flags       |= gen_bits_mask(0xFFFFFFFF);
        }
-       parm[0].in.reserved                   = gen_bits_levels(2, 80, 0x0, 100, 0xFFFFFFFF);
+       parm[0].in.reserved                   = gen_bits_levels(2, 95, 0x0, 100, 0xFFFFFFFF);
        if (gen_chance(2)) {
                parm[0].in.reserved           |= gen_bits_mask(0xFFFFFFFF);
        }
@@ -1078,32 +1084,31 @@ static bool handler_close(int instance)
        return true;
 }
 
-#if 0
 /*
   generate read operations
 */
 static bool handler_read(int instance)
 {
-       union smb_read parm[NSERVERS];
+       struct smb2_read parm[NSERVERS];
        NTSTATUS status[NSERVERS];
 
-       parm[0].readx.level = RAW_READ_READX;
-       parm[0].readx.in.file.fnum = gen_fnum(instance);
-       parm[0].readx.in.offset = gen_offset();
-       parm[0].readx.in.mincnt = gen_io_count();
-       parm[0].readx.in.maxcnt = gen_io_count();
-       parm[0].readx.in.remaining = gen_io_count();
-       parm[0].readx.in.read_for_execute = gen_bool();
-       parm[0].readx.out.data = talloc_array(current_op.mem_ctx, uint8_t,
-                                            MAX(parm[0].readx.in.mincnt, parm[0].readx.in.maxcnt));
+       parm[0].in.file.handle.data[0] = gen_fnum(instance);
+       parm[0].in.reserved    = gen_bits_mask2(0x0, 0xFF);
+       parm[0].in.length      = gen_io_count();
+       parm[0].in.offset      = gen_offset();
+       parm[0].in.min_count   = gen_io_count();
+       parm[0].in.channel     = gen_bits_mask2(0x0, 0xFFFFFFFF);
+       parm[0].in.remaining   = gen_bits_mask2(0x0, 0xFFFFFFFF);
+       parm[0].in.channel_offset = gen_bits_mask2(0x0, 0xFFFF);
+       parm[0].in.channel_length = gen_bits_mask2(0x0, 0xFFFF);
 
        GEN_COPY_PARM;
-       GEN_SET_FNUM(readx.in.file.fnum);
-       GEN_CALL(smb_raw_read(tree, &parm[i]));
+       GEN_SET_FNUM(in.file.handle);
+       GEN_CALL(smb2_read(tree, current_op.mem_ctx, &parm[i]));
 
-       CHECK_EQUAL(readx.out.remaining);
-       CHECK_EQUAL(readx.out.compaction_mode);
-       CHECK_EQUAL(readx.out.nread);
+       CHECK_EQUAL(out.remaining);
+       CHECK_EQUAL(out.reserved);
+       CHECK_EQUAL(out.data.length);
 
        return true;
 }
@@ -1113,23 +1118,23 @@ static bool handler_read(int instance)
 */
 static bool handler_write(int instance)
 {
-       union smb_write parm[NSERVERS];
+       struct smb2_write parm[NSERVERS];
        NTSTATUS status[NSERVERS];
 
-       parm[0].writex.level = RAW_WRITE_WRITEX;
-       parm[0].writex.in.file.fnum = gen_fnum(instance);
-       parm[0].writex.in.offset = gen_offset();
-       parm[0].writex.in.wmode = gen_bits_mask(0xFFFF);
-       parm[0].writex.in.remaining = gen_io_count();
-       parm[0].writex.in.count = gen_io_count();
-       parm[0].writex.in.data = talloc_zero_array(current_op.mem_ctx, uint8_t, parm[0].writex.in.count);
+       parm[0].in.file.handle.data[0] = gen_fnum(instance);
+       parm[0].in.offset = gen_offset();
+       parm[0].in.unknown1 = gen_bits_mask2(0, 0xFFFFFFFF);
+       parm[0].in.unknown2 = gen_bits_mask2(0, 0xFFFFFFFF);
+       parm[0].in.data = data_blob_talloc(current_op.mem_ctx, NULL,
+                                           gen_io_count());
 
        GEN_COPY_PARM;
-       GEN_SET_FNUM(writex.in.file.fnum);
-       GEN_CALL(smb_raw_write(tree, &parm[i]));
+       GEN_SET_FNUM(in.file.handle);
+       GEN_CALL(smb2_write(tree, &parm[i]));
 
-       CHECK_EQUAL(writex.out.nwritten);
-       CHECK_EQUAL(writex.out.remaining);
+       CHECK_EQUAL(out._pad);
+       CHECK_EQUAL(out.nwritten);
+       CHECK_EQUAL(out.unknown1);
 
        return true;
 }
@@ -1139,40 +1144,58 @@ static bool handler_write(int instance)
 */
 static bool handler_lock(int instance)
 {
-       union smb_lock parm[NSERVERS];
+       struct smb2_lock parm[NSERVERS];
        NTSTATUS status[NSERVERS];
-       int n, nlocks;
+       int n;
 
-       parm[0].lockx.level = RAW_LOCK_LOCKX;
-       parm[0].lockx.in.file.fnum = gen_fnum(instance);
-       parm[0].lockx.in.mode = gen_lock_mode();
-       parm[0].lockx.in.timeout = gen_timeout();
-       do {
-               /* make sure we don't accidentially generate an oplock
-                  break ack - otherwise the server can just block forever */
-               parm[0].lockx.in.ulock_cnt = gen_lock_count();
-               parm[0].lockx.in.lock_cnt = gen_lock_count();
-               nlocks = parm[0].lockx.in.ulock_cnt + parm[0].lockx.in.lock_cnt;
-       } while (nlocks == 0);
-
-       if (nlocks > 0) {
-               parm[0].lockx.in.locks = talloc_array(current_op.mem_ctx,
-                                                       struct smb_lock_entry,
-                                                       nlocks);
-               for (n=0;n<nlocks;n++) {
-                       parm[0].lockx.in.locks[n].pid = gen_pid();
-                       parm[0].lockx.in.locks[n].offset = gen_offset();
-                       parm[0].lockx.in.locks[n].count = gen_io_count();
-               }
+       parm[0].level = RAW_LOCK_LOCKX;
+       parm[0].in.file.handle.data[0] = gen_fnum(instance);
+       parm[0].in.lock_count = gen_lock_count();
+       parm[0].in.reserved = gen_bits_mask2(0, 0xFFFFFFFF);
+       
+       parm[0].in.locks = talloc_array(current_op.mem_ctx,
+                                       struct smb2_lock_element,
+                                       parm[0].in.lock_count);
+       for (n=0;n<parm[0].in.lock_count;n++) {
+               parm[0].in.locks[n].offset = gen_offset();
+               parm[0].in.locks[n].length = gen_io_count();
+               /* don't yet cope with async replies */
+               parm[0].in.locks[n].flags  = gen_lock_flags() | 
+                       SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
+               parm[0].in.locks[n].reserved = gen_bits_mask2(0x0, 0xFFFFFFFF);
        }
 
        GEN_COPY_PARM;
-       GEN_SET_FNUM(lockx.in.file.fnum);
-       GEN_CALL(smb_raw_lock(tree, &parm[i]));
+       GEN_SET_FNUM(in.file.handle);
+       GEN_CALL(smb2_lock(tree, &parm[i]));
+
+       return true;
+}
+
+/*
+  generate flush operations
+*/
+static bool handler_flush(int instance)
+{
+       struct smb2_flush parm[NSERVERS];
+       NTSTATUS status[NSERVERS];
+
+       ZERO_STRUCT(parm[0]);
+       parm[0].in.file.handle.data[0] = gen_fnum(instance);
+       parm[0].in.reserved1  = gen_bits_mask2(0x0, 0xFFFF);
+       parm[0].in.reserved2  = gen_bits_mask2(0x0, 0xFFFFFFFF);
+
+       GEN_COPY_PARM;
+       GEN_SET_FNUM(in.file.handle);
+       GEN_CALL(smb2_flush(tree, &parm[i]));
+
+       CHECK_EQUAL(out.reserved);
 
        return true;
 }
 
+#if 0
+
 /*
   generate a fileinfo query structure
 */
@@ -1379,24 +1402,6 @@ static bool cmp_fileinfo(int instance,
        return true;
 }
 
-/*
-  generate qpathinfo operations
-*/
-static bool handler_qpathinfo(int instance)
-{
-       union smb_fileinfo parm[NSERVERS];
-       NTSTATUS status[NSERVERS];
-
-       parm[0].generic.in.file.path = gen_fname_open(instance);
-
-       gen_fileinfo(instance, &parm[0]);
-
-       GEN_COPY_PARM;
-       GEN_CALL(smb_raw_pathinfo(tree, current_op.mem_ctx, &parm[i]));
-
-       return cmp_fileinfo(instance, parm, status);
-}
-
 /*
   generate qfileinfo operations
 */
@@ -1555,7 +1560,7 @@ static void wipe_files(void)
                }
                status = smb2_util_mkdir(servers[i].tree[0], "gentest");
                if (NT_STATUS_IS_ERR(status)) {
-                       printf("Failed to create gentest - %s\n", nt_errstr(status));
+                       printf("Failed to create gentest on server %d - %s\n", i, nt_errstr(status));
                        exit(1);
                }
                if (n > 0) {
@@ -1595,8 +1600,12 @@ static struct {
        bool (*handler)(int instance);
        int count, success_count;
 } gen_ops[] = {
-       {"NTCREATEX",  handler_ntcreatex},
+       {"CREATE",     handler_create},
        {"CLOSE",      handler_close},
+       {"READ",       handler_read},
+       {"WRITE",      handler_write},
+       {"LOCK",       handler_lock},
+       {"FLUSH",      handler_flush},
 };