summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/torture/gentest_smb2.c222
1 files changed, 173 insertions, 49 deletions
diff --git a/source4/torture/gentest_smb2.c b/source4/torture/gentest_smb2.c
index 46545699d0..428f325a76 100644
--- a/source4/torture/gentest_smb2.c
+++ b/source4/torture/gentest_smb2.c
@@ -55,6 +55,7 @@ static struct gentest_options {
int fast_reconnect;
int mask_indexing;
int no_eas;
+ int skip_cleanup;
} options;
/* mapping between open handles on the server and local handles */
@@ -112,7 +113,8 @@ static struct smb2_handle bad_smb2_handle;
#define BAD_HANDLE 0xFFFE
-static bool oplock_handler(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private);
+static bool oplock_handler(struct smb2_transport *transport, const struct smb2_handle *handle,
+ uint8_t level, void *private_data);
static void idle_func(struct smb2_transport *transport, void *private);
/*
@@ -208,7 +210,8 @@ static bool connect_servers(struct event_context *ev,
return false;
}
-// smb2_oplock_handler(servers[i].cli[j]->transport, oplock_handler, NULL);
+ servers[i].tree[j]->session->transport->oplock.handler = oplock_handler;
+ servers[i].tree[j]->session->transport->oplock.private_data = (void *)(uintptr_t)((i<<8)|j);
smb2_transport_idle_handler(servers[i].tree[j]->session->transport, idle_func, 50000, NULL);
}
}
@@ -512,24 +515,37 @@ static uint32_t gen_bits_mask2(uint32_t mask1, uint32_t mask2)
}
/*
- generate a boolean
-*/
-static bool gen_bool(void)
+ generate reserved values
+ */
+static uint64_t gen_reserved8(void)
{
- return gen_bits_mask2(0x1, 0xFF);
+ return gen_bits_mask(0xFF);
}
-/*
- generate ntrename flags
-*/
-static uint16_t gen_rename_flags(void)
+static uint64_t gen_reserved16(void)
{
- if (gen_chance(30)) return RENAME_FLAG_RENAME;
- if (gen_chance(30)) return RENAME_FLAG_HARD_LINK;
- if (gen_chance(30)) return RENAME_FLAG_COPY;
return gen_bits_mask(0xFFFF);
}
+static uint64_t gen_reserved32(void)
+{
+ return gen_bits_mask(0xFFFFFFFF);
+}
+
+static uint64_t gen_reserved64(void)
+{
+ return gen_bits_mask(0xFFFFFFFF) | (((uint64_t)gen_bits_mask(0xFFFFFFFF))<<32);
+}
+
+
+
+/*
+ generate a boolean
+*/
+static bool gen_bool(void)
+{
+ return gen_bits_mask2(0x1, 0xFF);
+}
/*
return a set of lock flags
@@ -553,15 +569,6 @@ static off_t gen_lock_count(void)
}
/*
- generate a ntcreatex flags field
-*/
-static uint32_t gen_ntcreatex_flags(void)
-{
- if (gen_chance(70)) return NTCREATEX_FLAGS_EXTENDED;
- return gen_bits_mask2(0x1F, 0xFFFFFFFF);
-}
-
-/*
generate a NT access mask
*/
static uint32_t gen_access_mask(void)
@@ -620,15 +627,6 @@ static NTTIME gen_nttime(void)
}
/*
- generate a milliseconds protocol timeout
-*/
-static uint32_t gen_timeout(void)
-{
- if (gen_chance(98)) return 0;
- return random() % 50;
-}
-
-/*
generate a file allocation size
*/
static uint_t gen_alloc_size(void)
@@ -704,6 +702,107 @@ static struct smb_ea_list gen_ea_list(void)
return eas;
}
+static void oplock_handler_close_recv(struct smb2_request *req)
+{
+ NTSTATUS status;
+ struct smb2_close io;
+ status = smb2_close_recv(req, &io);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("close failed in oplock_handler\n");
+ smb_panic("close failed in oplock_handler");
+ }
+}
+
+static void oplock_handler_ack_callback(struct smb2_request *req)
+{
+ NTSTATUS status;
+ struct smb2_break br;
+
+ status = smb2_break_recv(req, &br);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("oplock break ack failed in oplock_handler\n");
+ smb_panic("oplock break ack failed in oplock_handler");
+ }
+}
+
+static bool send_oplock_ack(struct smb2_tree *tree, struct smb2_handle handle,
+ uint8_t level)
+{
+ struct smb2_break br;
+ struct smb2_request *req;
+
+ ZERO_STRUCT(br);
+ br.in.file.handle = handle;
+ br.in.oplock_level = level;
+ br.in.reserved = gen_reserved8();
+ br.in.reserved2 = gen_reserved32();
+
+ req = smb2_break_send(tree, &br);
+ if (req == NULL) return false;
+ req->async.fn = oplock_handler_ack_callback;
+ req->async.private_data = NULL;
+ return true;
+}
+
+/*
+ the oplock handler will either ack the break or close the file
+*/
+static bool oplock_handler(struct smb2_transport *transport, const struct smb2_handle *handle,
+ uint8_t level, void *private_data)
+{
+ struct smb2_close io;
+ unsigned i, j;
+ bool do_close;
+ struct smb2_tree *tree = NULL;
+ struct smb2_request *req;
+
+ srandom(current_op.seed);
+ do_close = gen_chance(50);
+
+ i = ((uintptr_t)private_data) >> 8;
+ j = ((uintptr_t)private_data) & 0xFF;
+
+ if (i >= NSERVERS || j >= NINSTANCES) {
+ printf("Bad private_data in oplock_handler\n");
+ return false;
+ }
+
+ oplocks[i][j].got_break = true;
+ oplocks[i][j].server_handle = *handle;
+ oplocks[i][j].handle = fnum_to_handle(i, j, *handle);
+ oplocks[i][j].level = level;
+ oplocks[i][j].do_close = do_close;
+ tree = talloc_get_type(servers[i].tree[j], struct smb2_tree);
+
+ if (!tree) {
+ printf("Oplock break not for one of our trees!?\n");
+ return false;
+ }
+
+ if (!do_close) {
+ printf("oplock ack handle=%d\n", oplocks[i][j].handle);
+ return send_oplock_ack(tree, *handle, level);
+ }
+
+ printf("oplock close fnum=%d\n", oplocks[i][j].handle);
+
+ ZERO_STRUCT(io);
+ io.in.file.handle = *handle;
+ io.in.flags = 0;
+ req = smb2_close_send(tree, &io);
+
+ if (req == NULL) {
+ printf("WARNING: close failed in oplock_handler_close\n");
+ return false;
+ }
+
+ req->async.fn = oplock_handler_close_recv;
+ req->async.private_data = NULL;
+
+ return true;
+}
+
+
/*
the idle function tries to cope with getting an oplock break on a connection, and
an operation on another connection blocking until that break is acked
@@ -742,7 +841,7 @@ static bool compare_status(NTSTATUS status1, NTSTATUS status2)
return false;
}
-
+#if 0
/*
check for pending packets on all connections
*/
@@ -758,6 +857,7 @@ static void check_pending(void)
}
}
}
+#endif
/*
check that the same oplock breaks have been received by all instances
@@ -974,15 +1074,6 @@ again:
CHECK_EQUAL(field.length); \
} while(0)
-#define CHECK_TIMES_EQUAL(field) do { \
- if (labs(parm[0].field - parm[1].field) > time_skew() && \
- !ignore_pattern(#field)) { \
- printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
- (int)parm[0].field, (int)parm[1].field); \
- return false; \
- } \
-} while(0)
-
#define CHECK_NTTIMES_EQUAL(field) do { \
if (labs(nt_time_to_unix(parm[0].field) - \
nt_time_to_unix(parm[1].field)) > time_skew() && \
@@ -1010,10 +1101,7 @@ static bool handler_create(int instance)
if (gen_chance(2)) {
parm[0].in.create_flags |= gen_bits_mask(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);
- }
+ parm[0].in.reserved = gen_reserved64();
parm[0].in.desired_access = gen_access_mask();
parm[0].in.file_attributes = gen_attrib();
parm[0].in.share_access = gen_bits_mask2(0x7, 0xFFFFFFFF);
@@ -1088,7 +1176,7 @@ static bool handler_read(int instance)
NTSTATUS status[NSERVERS];
parm[0].in.file.handle.data[0] = gen_fnum(instance);
- parm[0].in.reserved = gen_bits_mask2(0x0, 0xFF);
+ parm[0].in.reserved = gen_reserved8();
parm[0].in.length = gen_io_count();
parm[0].in.offset = gen_offset();
parm[0].in.min_count = gen_io_count();
@@ -1146,7 +1234,7 @@ static bool handler_lock(int instance)
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.reserved = gen_reserved32();
parm[0].in.locks = talloc_array(current_op.mem_ctx,
struct smb2_lock_element,
@@ -1177,8 +1265,8 @@ static bool handler_flush(int instance)
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);
+ parm[0].in.reserved1 = gen_reserved16();
+ parm[0].in.reserved2 = gen_reserved32();
GEN_COPY_PARM;
GEN_SET_FNUM(in.file.handle);
@@ -1242,6 +1330,23 @@ static bool cmp_fileinfo(int instance,
case RAW_FILEINFO_GENERIC:
return false;
+ /* SMB1 specific values */
+ case RAW_FILEINFO_GETATTR:
+ case RAW_FILEINFO_GETATTRE:
+ case RAW_FILEINFO_STANDARD:
+ case RAW_FILEINFO_EA_SIZE:
+ case RAW_FILEINFO_ALL_EAS:
+ case RAW_FILEINFO_IS_NAME_VALID:
+ case RAW_FILEINFO_BASIC_INFO:
+ case RAW_FILEINFO_STANDARD_INFO:
+ case RAW_FILEINFO_EA_INFO:
+ case RAW_FILEINFO_NAME_INFO:
+ case RAW_FILEINFO_ALL_INFO:
+ case RAW_FILEINFO_ALT_NAME_INFO:
+ case RAW_FILEINFO_STREAM_INFO:
+ case RAW_FILEINFO_COMPRESSION_INFO:
+ return false;
+
case RAW_FILEINFO_BASIC_INFORMATION:
CHECK_NTTIMES_EQUAL(basic_info.out.create_time);
CHECK_NTTIMES_EQUAL(basic_info.out.access_time);
@@ -1411,6 +1516,16 @@ static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
info->generic.level = levels[i].level;
switch (info->generic.level) {
+ case RAW_SFILEINFO_SETATTR:
+ case RAW_SFILEINFO_SETATTRE:
+ case RAW_SFILEINFO_STANDARD:
+ case RAW_SFILEINFO_EA_SET:
+ case RAW_SFILEINFO_BASIC_INFO:
+ case RAW_SFILEINFO_DISPOSITION_INFO:
+ case RAW_SFILEINFO_END_OF_FILE_INFO:
+ case RAW_SFILEINFO_ALLOCATION_INFO:
+ break;
+
case RAW_SFILEINFO_BASIC_INFORMATION:
info->basic_info.in.create_time = gen_nttime();
info->basic_info.in.access_time = gen_nttime();
@@ -1447,6 +1562,10 @@ static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
case RAW_SFILEINFO_1032:
case RAW_SFILEINFO_1039:
case RAW_SFILEINFO_1040:
+ case RAW_SFILEINFO_UNIX_BASIC:
+ case RAW_SFILEINFO_UNIX_INFO2:
+ case RAW_SFILEINFO_UNIX_LINK:
+ case RAW_SFILEINFO_UNIX_HLINK:
/* Untested */
break;
}
@@ -1479,6 +1598,10 @@ static void wipe_files(void)
int i;
NTSTATUS status;
+ if (options.skip_cleanup) {
+ return;
+ }
+
for (i=0;i<NSERVERS;i++) {
int n = smb2_deltree(servers[i].tree[0], "gentest");
if (n == -1) {
@@ -1802,6 +1925,7 @@ static bool split_unc_name(const char *unc, char **server, char **share)
{ "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "[DOMAIN/]USERNAME[%PASSWORD]" },
{"maskindexing", 0, POPT_ARG_NONE, &options.mask_indexing, 0, "mask out the indexed file attrib", NULL},
{"noeas", 0, POPT_ARG_NONE, &options.no_eas, 0, "don't use extended attributes", NULL},
+ {"skip-cleanup", 0, POPT_ARG_NONE, &options.skip_cleanup, 0, "don't delete files at start", NULL},
POPT_COMMON_SAMBA
POPT_COMMON_CONNECTION
POPT_COMMON_CREDENTIALS