2
Unix SMB/CIFS implementation.
4
generic testing tool - version with both SMB and SMB2 support
6
Copyright (C) Andrew Tridgell 2003-2008
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3 of the License, or
11
(at your option) any later version.
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with this program. If not, see <http://www.gnu.org/licenses/>.
23
#include "lib/cmdline/popt_common.h"
24
#include "lib/events/events.h"
25
#include "system/time.h"
26
#include "system/filesys.h"
27
#include "libcli/raw/request.h"
28
#include "libcli/libcli.h"
29
#include "libcli/raw/libcliraw.h"
30
#include "libcli/smb2/smb2.h"
31
#include "libcli/smb2/smb2_calls.h"
32
#include "librpc/gen_ndr/security.h"
33
#include "librpc/gen_ndr/ndr_security.h"
34
#include "auth/credentials/credentials.h"
35
#include "libcli/resolve/resolve.h"
36
#include "auth/gensec/gensec.h"
37
#include "param/param.h"
38
#include "dynconfig/dynconfig.h"
39
#include "libcli/security/security.h"
40
#include "libcli/raw/raw_proto.h"
46
static struct gentest_options {
50
int analyze_continuous;
51
uint_t max_open_handles;
55
char **ignore_patterns;
56
const char *seeds_file;
67
/* mapping between open handles on the server and local handles */
71
struct smb2_handle smb2_handle[NSERVERS]; /* SMB2 */
72
uint16_t smb_handle[NSERVERS]; /* SMB */
75
static uint_t num_open_handles;
77
/* state information for the servers. We open NINSTANCES connections to
80
struct smb2_tree *smb2_tree[NINSTANCES];
81
struct smbcli_tree *smb_tree[NINSTANCES];
84
struct cli_credentials *credentials;
87
/* the seeds and flags for each operation */
94
/* oplock break info */
97
struct smb2_handle smb2_handle;
102
} oplocks[NSERVERS][NINSTANCES];
104
/* change notify reply info */
108
union smb_notify notify;
109
} notifies[NSERVERS][NINSTANCES];
111
/* info relevant to the current operation */
118
const char *mismatch;
121
static struct smb2_handle bad_smb2_handle;
124
#define BAD_HANDLE 0xFFFE
126
static bool oplock_handler_smb2(struct smb2_transport *transport, const struct smb2_handle *handle,
127
uint8_t level, void *private_data);
128
static void idle_func_smb2(struct smb2_transport *transport, void *private_data);
129
static bool oplock_handler_smb(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private_data);
130
static void idle_func_smb(struct smbcli_transport *transport, void *private_data);
133
check if a string should be ignored. This is used as the basis
134
for all error ignore settings
136
static bool ignore_pattern(const char *str)
139
if (!options.ignore_patterns) return false;
141
for (i=0;options.ignore_patterns[i];i++) {
142
if (strcmp(options.ignore_patterns[i], str) == 0 ||
143
gen_fnmatch(options.ignore_patterns[i], str) == 0) {
144
DEBUG(2,("Ignoring '%s'\n", str));
151
/*****************************************************
152
connect to the servers
153
*******************************************************/
154
static bool connect_servers_fast(void)
158
/* close all open files */
159
for (h=0;h<options.max_open_handles;h++) {
160
if (!open_handles[h].active) continue;
161
for (i=0;i<NSERVERS;i++) {
164
status = smb2_util_close(servers[i].smb2_tree[open_handles[h].instance],
165
open_handles[h].smb2_handle[i]);
167
status = smbcli_close(servers[i].smb_tree[open_handles[h].instance],
168
open_handles[h].smb_handle[i]);
170
if (NT_STATUS_IS_ERR(status)) {
173
open_handles[h].active = false;
183
/*****************************************************
184
connect to the servers
185
*******************************************************/
186
static bool connect_servers(struct tevent_context *ev,
187
struct loadparm_context *lp_ctx)
191
if (options.fast_reconnect && servers[0].smb2_tree[0]) {
192
if (connect_servers_fast()) {
197
/* close any existing connections */
198
for (i=0;i<NSERVERS;i++) {
199
for (j=0;j<NINSTANCES;j++) {
200
if (servers[i].smb2_tree[j]) {
201
smb2_tdis(servers[i].smb2_tree[j]);
202
talloc_free(servers[i].smb2_tree[j]);
203
servers[i].smb2_tree[j] = NULL;
205
if (servers[i].smb_tree[j]) {
206
smb_tree_disconnect(servers[i].smb_tree[j]);
207
talloc_free(servers[i].smb_tree[j]);
208
servers[i].smb_tree[j] = NULL;
213
for (i=0;i<NSERVERS;i++) {
214
for (j=0;j<NINSTANCES;j++) {
216
struct smbcli_options smb_options;
217
struct smbcli_session_options smb_session_options;
218
lp_smbcli_options(lp_ctx, &smb_options);
219
lp_smbcli_session_options(lp_ctx, &smb_session_options);
221
printf("Connecting to \\\\%s\\%s as %s - instance %d\n",
222
servers[i].server_name, servers[i].share_name,
223
servers[i].credentials->username, j);
225
cli_credentials_set_workstation(servers[i].credentials,
226
"gentest", CRED_SPECIFIED);
229
status = smb2_connect(NULL, servers[i].server_name,
230
lp_smb_ports(lp_ctx),
231
servers[i].share_name,
232
lp_resolve_context(lp_ctx),
233
servers[i].credentials,
234
&servers[i].smb2_tree[j],
236
lp_socket_options(lp_ctx),
237
lp_gensec_settings(lp_ctx, lp_ctx)
240
status = smbcli_tree_full_connection(NULL,
241
&servers[i].smb_tree[j],
242
servers[i].server_name,
243
lp_smb_ports(lp_ctx),
244
servers[i].share_name, "A:",
245
lp_socket_options(lp_ctx),
246
servers[i].credentials,
247
lp_resolve_context(lp_ctx), ev,
249
&smb_session_options,
250
lp_iconv_convenience(lp_ctx),
251
lp_gensec_settings(lp_ctx, lp_ctx));
253
if (!NT_STATUS_IS_OK(status)) {
254
printf("Failed to connect to \\\\%s\\%s - %s\n",
255
servers[i].server_name, servers[i].share_name,
261
servers[i].smb2_tree[j]->session->transport->oplock.handler = oplock_handler_smb2;
262
servers[i].smb2_tree[j]->session->transport->oplock.private_data = (void *)(uintptr_t)((i<<8)|j);
263
smb2_transport_idle_handler(servers[i].smb2_tree[j]->session->transport,
264
idle_func_smb2, 50000, NULL);
266
smbcli_oplock_handler(servers[i].smb_tree[j]->session->transport, oplock_handler_smb,
267
(void *)(uintptr_t)((i<<8)|j));
268
smbcli_transport_idle_handler(servers[i].smb_tree[j]->session->transport, idle_func_smb,
269
50000, (void *)(uintptr_t)((i<<8)|j));
278
work out the time skew between the servers - be conservative
280
static uint_t time_skew(void)
284
ret = labs(servers[0].smb2_tree[0]->session->transport->negotiate.system_time -
285
servers[1].smb2_tree[0]->session->transport->negotiate.system_time);
287
ret = labs(servers[0].smb_tree[0]->session->transport->negotiate.server_time -
288
servers[1].smb_tree[0]->session->transport->negotiate.server_time);
294
static bool smb2_handle_equal(const struct smb2_handle *h1, const struct smb2_handle *h2)
296
return memcmp(h1, h2, sizeof(struct smb2_handle)) == 0;
300
turn a server handle into a local handle
302
static uint_t fnum_to_handle_smb2(int server, int instance, struct smb2_handle server_handle)
305
for (i=0;i<options.max_open_handles;i++) {
306
if (!open_handles[i].active ||
307
instance != open_handles[i].instance) continue;
308
if (smb2_handle_equal(&open_handles[i].smb2_handle[server], &server_handle)) {
312
printf("Invalid server handle in fnum_to_handle on server %d instance %d\n",
318
turn a server handle into a local handle
320
static uint_t fnum_to_handle_smb(int server, int instance, uint16_t server_handle)
323
for (i=0;i<options.max_open_handles;i++) {
324
if (!open_handles[i].active ||
325
instance != open_handles[i].instance) continue;
326
if (open_handles[i].smb_handle[server] == server_handle) {
330
printf("Invalid server handle in fnum_to_handle on server %d instance %d\n",
336
add some newly opened handles
338
static void gen_add_handle_smb2(int instance, const char *name, struct smb2_handle handles[NSERVERS])
341
for (h=0;h<options.max_open_handles;h++) {
342
if (!open_handles[h].active) break;
344
if (h == options.max_open_handles) {
345
/* we have to force close a random handle */
346
h = random() % options.max_open_handles;
347
for (i=0;i<NSERVERS;i++) {
349
status = smb2_util_close(servers[i].smb2_tree[open_handles[h].instance],
350
open_handles[h].smb2_handle[i]);
351
if (NT_STATUS_IS_ERR(status)) {
352
printf("INTERNAL ERROR: Close failed when recovering handle! - %s\n",
356
printf("Recovered handle %d\n", h);
359
for (i=0;i<NSERVERS;i++) {
360
open_handles[h].smb2_handle[i] = handles[i];
361
open_handles[h].instance = instance;
362
open_handles[h].active = true;
363
open_handles[h].name = name;
367
printf("OPEN num_open_handles=%d h=%d (%s)\n",
368
num_open_handles, h, name);
372
add some newly opened handles
374
static void gen_add_handle_smb(int instance, const char *name, uint16_t handles[NSERVERS])
377
for (h=0;h<options.max_open_handles;h++) {
378
if (!open_handles[h].active) break;
380
if (h == options.max_open_handles) {
381
/* we have to force close a random handle */
382
h = random() % options.max_open_handles;
383
for (i=0;i<NSERVERS;i++) {
385
status = smbcli_close(servers[i].smb_tree[open_handles[h].instance],
386
open_handles[h].smb_handle[i]);
387
if (NT_STATUS_IS_ERR(status)) {
388
printf("INTERNAL ERROR: Close failed when recovering handle! - %s\n",
392
printf("Recovered handle %d\n", h);
395
for (i=0;i<NSERVERS;i++) {
396
open_handles[h].smb_handle[i] = handles[i];
397
open_handles[h].instance = instance;
398
open_handles[h].active = true;
399
open_handles[h].name = name;
403
printf("OPEN num_open_handles=%d h=%d (%s)\n",
404
num_open_handles, h, name);
409
remove a closed handle
411
static void gen_remove_handle_smb2(int instance, struct smb2_handle handles[NSERVERS])
414
for (h=0;h<options.max_open_handles;h++) {
415
if (instance == open_handles[h].instance &&
416
smb2_handle_equal(&open_handles[h].smb2_handle[0], &handles[0])) {
417
open_handles[h].active = false;
419
printf("CLOSE num_open_handles=%d h=%d (%s)\n",
421
open_handles[h].name);
425
printf("Removing invalid handle!?\n");
430
remove a closed handle
432
static void gen_remove_handle_smb(int instance, uint16_t handles[NSERVERS])
435
for (h=0;h<options.max_open_handles;h++) {
436
if (instance == open_handles[h].instance &&
437
open_handles[h].smb_handle[0] == handles[0]) {
438
open_handles[h].active = false;
440
printf("CLOSE num_open_handles=%d h=%d (%s)\n",
442
open_handles[h].name);
446
printf("Removing invalid handle!?\n");
451
return true with 'chance' probability as a percentage
453
static bool gen_chance(uint_t chance)
455
return ((random() % 100) <= chance);
459
map an internal handle number to a server handle
461
static struct smb2_handle gen_lookup_handle_smb2(int server, uint16_t handle)
463
if (handle == BAD_HANDLE) return bad_smb2_handle;
464
return open_handles[handle].smb2_handle[server];
468
map an internal handle number to a server handle
470
static uint16_t gen_lookup_handle_smb(int server, uint16_t handle)
472
if (handle == BAD_HANDLE) return BAD_HANDLE;
473
return open_handles[handle].smb_handle[server];
479
static uint16_t gen_fnum(int instance)
484
if (gen_chance(20)) return BAD_HANDLE;
486
while (num_open_handles > 0 && count++ < 10*options.max_open_handles) {
487
h = random() % options.max_open_handles;
488
if (open_handles[h].active &&
489
open_handles[h].instance == instance) {
497
return a file handle, but skewed so we don't close the last
498
couple of handles too readily
500
static uint16_t gen_fnum_close(int instance)
502
if (num_open_handles < 5) {
503
if (gen_chance(90)) return BAD_HANDLE;
506
return gen_fnum(instance);
510
generate an integer in a specified range
512
static int gen_int_range(uint64_t min, uint64_t max)
515
return min + (r % (1+max-min));
519
return a fnum for use as a root fid
520
be careful to call GEN_SET_FNUM() when you use this!
522
static uint16_t gen_root_fid(int instance)
524
if (gen_chance(5)) return gen_fnum(instance);
529
generate a file offset
531
static int gen_offset(void)
533
if (gen_chance(20)) return 0;
534
// if (gen_chance(5)) return gen_int_range(0, 0xFFFFFFFF);
535
return gen_int_range(0, 1024*1024);
541
static int gen_io_count(void)
543
if (gen_chance(20)) return 0;
544
// if (gen_chance(5)) return gen_int_range(0, 0xFFFFFFFF);
545
return gen_int_range(0, 4096);
551
static const char *gen_fname(void)
553
const char *names[] = {"gentest\\gentest.dat",
558
"gentest\\foo4:teststream1",
559
"gentest\\foo4:teststream2",
561
"gentest\\foo5.exe:teststream3",
562
"gentest\\foo5.exe:teststream4",
565
"gentest\\blah\\blergh.txt",
566
"gentest\\blah\\blergh2",
567
"gentest\\blah\\blergh3.txt",
568
"gentest\\blah\\blergh4",
569
"gentest\\blah\\blergh5.txt",
570
"gentest\\blah\\blergh5",
573
"gentest\\a_very_long_name.bin",
579
i = gen_int_range(0, ARRAY_SIZE(names)-1);
580
} while (ignore_pattern(names[i]));
586
generate a filename with a higher chance of choosing an already
589
static const char *gen_fname_open(int instance)
592
h = gen_fnum(instance);
593
if (h == BAD_HANDLE) {
596
return open_handles[h].name;
600
generate a wildcard pattern
602
static const char *gen_pattern(void)
605
const char *names[] = {"gentest\\*.dat",
608
"gentest\\blah\\*.*",
612
if (gen_chance(50)) return gen_fname();
615
i = gen_int_range(0, ARRAY_SIZE(names)-1);
616
} while (ignore_pattern(names[i]));
621
static uint32_t gen_bits_levels(int nlevels, ...)
627
va_start(ap, nlevels);
628
for (i=0;i<nlevels;i++) {
629
pct = va_arg(ap, uint32_t);
630
mask = va_arg(ap, uint32_t);
631
if (pct == 100 || gen_chance(pct)) {
633
return mask & random();
643
static uint32_t gen_bits_mask(uint_t mask)
645
uint_t ret = random();
650
generate a bitmask with high probability of the first mask
651
and low of the second
653
static uint32_t gen_bits_mask2(uint32_t mask1, uint32_t mask2)
655
if (!options.valid && gen_chance(10)) return gen_bits_mask(mask2);
656
return gen_bits_mask(mask1);
660
generate reserved values
662
static uint64_t gen_reserved8(void)
664
if (options.valid) return 0;
665
return gen_bits_mask(0xFF);
668
static uint64_t gen_reserved16(void)
670
if (options.valid) return 0;
671
return gen_bits_mask(0xFFFF);
674
static uint64_t gen_reserved32(void)
676
if (options.valid) return 0;
677
return gen_bits_mask(0xFFFFFFFF);
680
static uint64_t gen_reserved64(void)
682
if (options.valid) return 0;
683
return gen_bits_mask(0xFFFFFFFF) | (((uint64_t)gen_bits_mask(0xFFFFFFFF))<<32);
691
static bool gen_bool(void)
693
return gen_bits_mask2(0x1, 0xFF);
697
generate ntrename flags
699
static uint16_t gen_rename_flags(void)
701
if (gen_chance(30)) return RENAME_FLAG_RENAME;
702
if (gen_chance(30)) return RENAME_FLAG_HARD_LINK;
703
if (gen_chance(30)) return RENAME_FLAG_COPY;
704
return gen_bits_mask(0xFFFF);
710
static uint16_t gen_pid(void)
712
if (gen_chance(10)) return gen_bits_mask(0xFFFF);
717
return a set of lock flags
719
static uint16_t gen_lock_flags_smb2(void)
721
if (!options.valid && gen_chance(5)) return gen_bits_mask(0xFFFF);
722
if (gen_chance(20)) return gen_bits_mask(0x1F);
723
if (gen_chance(50)) return SMB2_LOCK_FLAG_UNLOCK;
724
return gen_bits_mask(SMB2_LOCK_FLAG_SHARED |
725
SMB2_LOCK_FLAG_EXCLUSIVE |
726
SMB2_LOCK_FLAG_FAIL_IMMEDIATELY);
730
generate a lock count
732
static off_t gen_lock_count(void)
734
return gen_int_range(0, 3);
738
generate a NT access mask
740
static uint32_t gen_access_mask(void)
743
if (gen_chance(70)) return SEC_FLAG_MAXIMUM_ALLOWED;
744
if (gen_chance(70)) return SEC_FILE_ALL;
745
ret = gen_bits_mask(0xFFFFFFFF);
746
if (options.valid) ret &= ~SEC_MASK_INVALID;
751
return a lockingx lock mode
753
static uint16_t gen_lock_mode(void)
755
if (!options.valid && gen_chance(5)) return gen_bits_mask(0xFFFF);
756
if (gen_chance(20)) return gen_bits_mask(0x1F);
757
return gen_bits_mask(LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES);
761
generate a ntcreatex flags field
763
static uint32_t gen_ntcreatex_flags(void)
765
if (gen_chance(70)) return NTCREATEX_FLAGS_EXTENDED;
766
return gen_bits_mask2(0x1F, 0xFFFFFFFF);
770
generate a ntcreatex create options bitfield
772
static uint32_t gen_create_options(void)
774
if (!options.valid && gen_chance(20)) return gen_bits_mask(0xFFFFFFFF);
775
if (gen_chance(50)) return 0;
776
return gen_bits_mask(NTCREATEX_OPTIONS_DELETE_ON_CLOSE | NTCREATEX_OPTIONS_DIRECTORY);
780
generate a ntcreatex open disposition
782
static uint32_t gen_open_disp(void)
784
if (gen_chance(50)) return NTCREATEX_DISP_OPEN_IF;
785
if (!options.valid && gen_chance(10)) return gen_bits_mask(0xFFFFFFFF);
786
return gen_int_range(0, 5);
790
generate an openx open mode
792
static uint16_t gen_openx_mode(void)
794
if (!options.valid && gen_chance(20)) return gen_bits_mask(0xFFFF);
795
if (gen_chance(20)) return gen_bits_mask(0xFF);
796
return OPENX_MODE_DENY_NONE | gen_bits_mask(0x3);
800
generate an openx flags field
802
static uint16_t gen_openx_flags(void)
804
if (!options.valid && gen_chance(20)) return gen_bits_mask(0xFFFF);
805
return gen_bits_mask(0x7);
809
generate an openx open function
811
static uint16_t gen_openx_func(void)
813
if (!options.valid && gen_chance(20)) return gen_bits_mask(0xFFFF);
814
return gen_bits_mask(0x13);
818
generate a file attrib combination
820
static uint32_t gen_attrib(void)
823
if (gen_chance(20)) {
824
ret = gen_bits_mask(0xFFFFFFFF);
825
if (options.valid) ret &= FILE_ATTRIBUTE_ALL_MASK;
828
return gen_bits_mask(FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY);
832
generate a unix timestamp
834
static time_t gen_timet(void)
836
if (gen_chance(30)) return 0;
837
return (time_t)random();
841
generate a milliseconds protocol timeout
843
static uint32_t gen_timeout(void)
845
if (gen_chance(98)) return 0;
846
return random() % 50;
852
static NTTIME gen_nttime(void)
855
unix_to_nt_time(&ret, gen_timet());
860
generate a timewarp value
862
static NTTIME gen_timewarp(void)
864
NTTIME ret = gen_nttime();
865
if (gen_chance(98)) ret = 0;
870
generate a file allocation size
872
static uint_t gen_alloc_size(void)
876
if (gen_chance(30)) return 0;
878
ret = random() % 4*1024*1024;
879
/* give a high chance of a round number */
880
if (gen_chance(60)) {
881
ret &= ~(1024*1024 - 1);
887
generate an ea_struct
889
static struct ea_struct gen_ea_struct(void)
892
const char *names[] = {"EAONE",
897
"AVERYLONGATTRIBUTENAME"};
898
const char *values[] = {"VALUE1",
903
"ASOMEWHATLONGERATTRIBUTEVALUE"};
909
i = gen_int_range(0, ARRAY_SIZE(names)-1);
910
} while (ignore_pattern(names[i]));
912
ea.name.s = names[i];
915
i = gen_int_range(0, ARRAY_SIZE(values)-1);
916
} while (ignore_pattern(values[i]));
918
ea.value = data_blob(values[i], strlen(values[i]));
920
if (gen_chance(10)) ea.flags = gen_bits_mask(0xFF);
927
generate an ea_struct
929
static struct smb_ea_list gen_ea_list(void)
931
struct smb_ea_list eas;
933
if (options.no_eas) {
937
eas.num_eas = gen_int_range(0, 3);
938
eas.eas = talloc_array(current_op.mem_ctx, struct ea_struct, eas.num_eas);
939
for (i=0;i<eas.num_eas;i++) {
940
eas.eas[i] = gen_ea_struct();
945
/* generate a security descriptor */
946
static struct security_descriptor *gen_sec_desc(void)
948
struct security_descriptor *sd;
949
if (options.no_acls || gen_chance(90)) return NULL;
951
sd = security_descriptor_dacl_create(current_op.mem_ctx,
954
SEC_ACE_TYPE_ACCESS_ALLOWED,
955
SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
956
SEC_ACE_FLAG_OBJECT_INHERIT,
958
SEC_ACE_TYPE_ACCESS_ALLOWED,
959
SEC_FILE_ALL | SEC_STD_ALL,
966
static void oplock_handler_close_recv_smb(struct smbcli_request *req)
969
status = smbcli_request_simple_recv(req);
970
if (!NT_STATUS_IS_OK(status)) {
971
printf("close failed in oplock_handler\n");
972
smb_panic("close failed in oplock_handler");
977
the oplock handler will either ack the break or close the file
979
static bool oplock_handler_smb(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private_data)
984
struct smbcli_tree *tree = NULL;
985
struct smbcli_request *req;
987
srandom(current_op.seed);
988
do_close = gen_chance(50);
990
for (i=0;i<NSERVERS;i++) {
991
for (j=0;j<NINSTANCES;j++) {
992
if (transport == servers[i].smb_tree[j]->session->transport &&
993
tid == servers[i].smb_tree[j]->tid) {
994
oplocks[i][j].got_break = true;
995
oplocks[i][j].smb_handle = fnum;
996
oplocks[i][j].handle = fnum_to_handle_smb(i, j, fnum);
997
oplocks[i][j].level = level;
998
oplocks[i][j].do_close = do_close;
999
tree = servers[i].smb_tree[j];
1005
printf("Oplock break not for one of our trees!?\n");
1010
printf("oplock ack fnum=%d\n", fnum);
1011
return smbcli_oplock_ack(tree, fnum, level);
1014
printf("oplock close fnum=%d\n", fnum);
1016
io.close.level = RAW_CLOSE_CLOSE;
1017
io.close.in.file.fnum = fnum;
1018
io.close.in.write_time = 0;
1019
req = smb_raw_close_send(tree, &io);
1022
printf("WARNING: close failed in oplock_handler_close\n");
1026
req->async.fn = oplock_handler_close_recv_smb;
1027
req->async.private_data = NULL;
1034
the idle function tries to cope with getting an oplock break on a connection, and
1035
an operation on another connection blocking until that break is acked
1036
we check for operations on all transports in the idle function
1038
static void idle_func_smb(struct smbcli_transport *transport, void *private_data)
1041
for (i=0;i<NSERVERS;i++) {
1042
for (j=0;j<NINSTANCES;j++) {
1043
if (servers[i].smb_tree[j] &&
1044
transport != servers[i].smb_tree[j]->session->transport) {
1045
smbcli_transport_process(servers[i].smb_tree[j]->session->transport);
1052
static void oplock_handler_close_recv_smb2(struct smb2_request *req)
1055
struct smb2_close io;
1056
status = smb2_close_recv(req, &io);
1057
if (!NT_STATUS_IS_OK(status)) {
1058
printf("close failed in oplock_handler\n");
1059
smb_panic("close failed in oplock_handler");
1063
static void oplock_handler_ack_callback_smb2(struct smb2_request *req)
1066
struct smb2_break br;
1068
status = smb2_break_recv(req, &br);
1069
if (!NT_STATUS_IS_OK(status)) {
1070
printf("oplock break ack failed in oplock_handler\n");
1071
smb_panic("oplock break ack failed in oplock_handler");
1075
static bool send_oplock_ack_smb2(struct smb2_tree *tree, struct smb2_handle handle,
1078
struct smb2_break br;
1079
struct smb2_request *req;
1082
br.in.file.handle = handle;
1083
br.in.oplock_level = level;
1084
br.in.reserved = gen_reserved8();
1085
br.in.reserved2 = gen_reserved32();
1087
req = smb2_break_send(tree, &br);
1088
if (req == NULL) return false;
1089
req->async.fn = oplock_handler_ack_callback_smb2;
1090
req->async.private_data = NULL;
1095
the oplock handler will either ack the break or close the file
1097
static bool oplock_handler_smb2(struct smb2_transport *transport, const struct smb2_handle *handle,
1098
uint8_t level, void *private_data)
1100
struct smb2_close io;
1103
struct smb2_tree *tree = NULL;
1104
struct smb2_request *req;
1106
srandom(current_op.seed);
1107
do_close = gen_chance(50);
1109
i = ((uintptr_t)private_data) >> 8;
1110
j = ((uintptr_t)private_data) & 0xFF;
1112
if (i >= NSERVERS || j >= NINSTANCES) {
1113
printf("Bad private_data in oplock_handler\n");
1117
oplocks[i][j].got_break = true;
1118
oplocks[i][j].smb2_handle = *handle;
1119
oplocks[i][j].handle = fnum_to_handle_smb2(i, j, *handle);
1120
oplocks[i][j].level = level;
1121
oplocks[i][j].do_close = do_close;
1122
tree = talloc_get_type(servers[i].smb2_tree[j], struct smb2_tree);
1125
printf("Oplock break not for one of our trees!?\n");
1130
printf("oplock ack handle=%d\n", oplocks[i][j].handle);
1131
return send_oplock_ack_smb2(tree, *handle, level);
1134
printf("oplock close fnum=%d\n", oplocks[i][j].handle);
1137
io.in.file.handle = *handle;
1139
req = smb2_close_send(tree, &io);
1142
printf("WARNING: close failed in oplock_handler_close\n");
1146
req->async.fn = oplock_handler_close_recv_smb2;
1147
req->async.private_data = NULL;
1154
the idle function tries to cope with getting an oplock break on a connection, and
1155
an operation on another connection blocking until that break is acked
1156
we check for operations on all transports in the idle function
1158
static void idle_func_smb2(struct smb2_transport *transport, void *private_data)
1161
for (i=0;i<NSERVERS;i++) {
1162
for (j=0;j<NINSTANCES;j++) {
1163
if (servers[i].smb2_tree[j] &&
1164
transport != servers[i].smb2_tree[j]->session->transport) {
1165
// smb2_transport_process(servers[i].smb2_tree[j]->session->transport);
1174
compare NTSTATUS, using checking ignored patterns
1176
static bool compare_status(NTSTATUS status1, NTSTATUS status2)
1180
if (NT_STATUS_EQUAL(status1, status2)) return true;
1182
/* one code being an error and the other OK is always an error */
1183
if (NT_STATUS_IS_OK(status1) || NT_STATUS_IS_OK(status2)) {
1184
current_op.mismatch = nt_errstr(status1);
1188
/* if we are ignoring one of the status codes then consider this a match */
1189
if (ignore_pattern(nt_errstr(status1)) ||
1190
ignore_pattern(nt_errstr(status2))) {
1194
/* also support ignore patterns of the form NT_STATUS_XX:NT_STATUS_YY
1195
meaning that the first server returns NT_STATUS_XX and the 2nd
1196
returns NT_STATUS_YY */
1197
s = talloc_asprintf(current_op.mem_ctx, "%s:%s",
1199
nt_errstr(status2));
1200
if (ignore_pattern(s)) {
1204
current_op.mismatch = nt_errstr(status1);
1209
check for pending packets on all connections
1211
static void check_pending(void)
1217
for (j=0;j<NINSTANCES;j++) {
1218
for (i=0;i<NSERVERS;i++) {
1219
// smb2_transport_process(servers[i].smb2_tree[j]->session->transport);
1225
check that the same oplock breaks have been received by all instances
1227
static bool check_oplocks(const char *call)
1232
if (!options.use_oplocks || options.smb2) {
1233
/* no smb2 oplocks in gentest yet */
1240
for (j=0;j<NINSTANCES;j++) {
1241
for (i=1;i<NSERVERS;i++) {
1242
if (oplocks[0][j].got_break != oplocks[i][j].got_break ||
1243
oplocks[0][j].handle != oplocks[i][j].handle ||
1244
oplocks[0][j].level != oplocks[i][j].level) {
1245
if (tries++ < 10) goto again;
1246
printf("oplock break inconsistent - %d/%d/%d vs %d/%d/%d\n",
1247
oplocks[0][j].got_break,
1248
oplocks[0][j].handle,
1249
oplocks[0][j].level,
1250
oplocks[i][j].got_break,
1251
oplocks[i][j].handle,
1252
oplocks[i][j].level);
1253
current_op.mismatch = "oplock break";
1259
/* if we got a break and closed then remove the handle */
1260
for (j=0;j<NINSTANCES;j++) {
1261
if (oplocks[0][j].got_break &&
1262
oplocks[0][j].do_close) {
1263
uint16_t fnums[NSERVERS];
1264
for (i=0;i<NSERVERS;i++) {
1265
fnums[i] = oplocks[i][j].smb_handle;
1267
gen_remove_handle_smb(j, fnums);
1276
check that the same change notify info has been received by all instances
1278
static bool check_notifies(const char *call)
1284
/* no smb2 notifies in gentest yet */
1291
for (j=0;j<NINSTANCES;j++) {
1292
for (i=1;i<NSERVERS;i++) {
1294
union smb_notify not1, not2;
1296
if (notifies[0][j].notify_count != notifies[i][j].notify_count) {
1297
if (tries++ < 10) goto again;
1298
printf("Notify count inconsistent %d %d\n",
1299
notifies[0][j].notify_count,
1300
notifies[i][j].notify_count);
1301
current_op.mismatch = "notify count";
1305
if (notifies[0][j].notify_count == 0) continue;
1307
if (!NT_STATUS_EQUAL(notifies[0][j].status,
1308
notifies[i][j].status)) {
1309
printf("Notify status mismatch - %s - %s\n",
1310
nt_errstr(notifies[0][j].status),
1311
nt_errstr(notifies[i][j].status));
1312
current_op.mismatch = "Notify status";
1316
if (!NT_STATUS_IS_OK(notifies[0][j].status)) {
1320
not1 = notifies[0][j].notify;
1321
not2 = notifies[i][j].notify;
1323
for (n=0;n<not1.nttrans.out.num_changes;n++) {
1324
if (not1.nttrans.out.changes[n].action !=
1325
not2.nttrans.out.changes[n].action) {
1326
printf("Notify action %d inconsistent %d %d\n", n,
1327
not1.nttrans.out.changes[n].action,
1328
not2.nttrans.out.changes[n].action);
1329
current_op.mismatch = "notify action";
1332
if (strcmp(not1.nttrans.out.changes[n].name.s,
1333
not2.nttrans.out.changes[n].name.s)) {
1334
printf("Notify name %d inconsistent %s %s\n", n,
1335
not1.nttrans.out.changes[n].name.s,
1336
not2.nttrans.out.changes[n].name.s);
1337
current_op.mismatch = "notify name";
1340
if (not1.nttrans.out.changes[n].name.private_length !=
1341
not2.nttrans.out.changes[n].name.private_length) {
1342
printf("Notify name length %d inconsistent %d %d\n", n,
1343
not1.nttrans.out.changes[n].name.private_length,
1344
not2.nttrans.out.changes[n].name.private_length);
1345
current_op.mismatch = "notify name length";
1352
ZERO_STRUCT(notifies);
1357
#define GEN_COPY_PARM do { \
1359
for (i=1;i<NSERVERS;i++) { \
1360
parm[i] = parm[0]; \
1364
#define GEN_CALL(call, treetype, treefield) do { \
1366
ZERO_STRUCT(oplocks); \
1367
ZERO_STRUCT(notifies); \
1368
for (i=0;i<NSERVERS;i++) { \
1369
struct treetype *tree = servers[i].treefield[instance]; \
1372
current_op.status = status[0]; \
1373
for (i=1;i<NSERVERS;i++) { \
1374
if (!compare_status(status[0], status[1])) { \
1375
printf("status different in %s - %s %s\n", #call, \
1376
nt_errstr(status[0]), nt_errstr(status[i])); \
1377
current_op.mismatch = nt_errstr(status[0]); \
1381
if (!check_oplocks(#call)) return false; \
1382
if (!check_notifies(#call)) return false; \
1383
if (!NT_STATUS_IS_OK(status[0])) { \
1388
#define GEN_CALL_SMB(call) GEN_CALL(call, smbcli_tree, smb_tree)
1389
#define GEN_CALL_SMB2(call) GEN_CALL(call, smb2_tree, smb2_tree)
1391
#define ADD_HANDLE_SMB2(name, field) do { \
1392
struct smb2_handle handles[NSERVERS]; \
1394
for (i=0;i<NSERVERS;i++) { \
1395
handles[i] = parm[i].field; \
1397
gen_add_handle_smb2(instance, name, handles); \
1400
#define REMOVE_HANDLE_SMB2(field) do { \
1401
struct smb2_handle handles[NSERVERS]; \
1403
for (i=0;i<NSERVERS;i++) { \
1404
handles[i] = parm[i].field; \
1406
gen_remove_handle_smb2(instance, handles); \
1409
#define ADD_HANDLE_SMB(name, field) do { \
1410
uint16_t handles[NSERVERS]; \
1412
for (i=0;i<NSERVERS;i++) { \
1413
handles[i] = parm[i].field; \
1415
gen_add_handle_smb(instance, name, handles); \
1418
#define REMOVE_HANDLE_SMB(field) do { \
1419
uint16_t handles[NSERVERS]; \
1421
for (i=0;i<NSERVERS;i++) { \
1422
handles[i] = parm[i].field; \
1424
gen_remove_handle_smb(instance, handles); \
1427
#define GEN_SET_FNUM_SMB2(field) do { \
1429
for (i=0;i<NSERVERS;i++) { \
1430
parm[i].field = gen_lookup_handle_smb2(i, parm[i].field.data[0]); \
1434
#define GEN_SET_FNUM_SMB(field) do { \
1436
for (i=0;i<NSERVERS;i++) { \
1437
parm[i].field = gen_lookup_handle_smb(i, parm[i].field); \
1441
#define CHECK_EQUAL(field) do { \
1442
if (parm[0].field != parm[1].field && !ignore_pattern(#field)) { \
1443
current_op.mismatch = #field; \
1444
printf("Mismatch in %s - 0x%llx 0x%llx\n", #field, \
1445
(unsigned long long)parm[0].field, (unsigned long long)parm[1].field); \
1450
#define CHECK_SECDESC(field) do { \
1451
if (!security_acl_equal(parm[0].field->dacl, parm[1].field->dacl) && !ignore_pattern(#field)) { \
1452
current_op.mismatch = #field; \
1453
printf("Mismatch in %s\n", #field); \
1458
#define CHECK_ATTRIB(field) do { \
1459
if (!options.mask_indexing) { \
1460
CHECK_EQUAL(field); \
1461
} else if ((~FILE_ATTRIBUTE_NONINDEXED & parm[0].field) != (~FILE_ATTRIBUTE_NONINDEXED & parm[1].field) && !ignore_pattern(#field)) { \
1462
current_op.mismatch = #field; \
1463
printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
1464
(int)parm[0].field, (int)parm[1].field); \
1469
#define CHECK_WSTR_EQUAL(field) do { \
1470
if ((!parm[0].field.s && parm[1].field.s) || (parm[0].field.s && !parm[1].field.s)) { \
1471
current_op.mismatch = #field; \
1472
printf("%s is NULL!\n", #field); \
1475
if (parm[0].field.s && strcmp(parm[0].field.s, parm[1].field.s) != 0 && !ignore_pattern(#field)) { \
1476
current_op.mismatch = #field; \
1477
printf("Mismatch in %s - %s %s\n", #field, \
1478
parm[0].field.s, parm[1].field.s); \
1481
CHECK_EQUAL(field.private_length); \
1484
#define CHECK_BLOB_EQUAL(field) do { \
1485
if (((parm[0].field.data == NULL && parm[1].field.data != NULL) || \
1486
(parm[1].field.data == NULL && parm[0].field.data != NULL) || \
1487
(memcmp(parm[0].field.data, parm[1].field.data, parm[0].field.length) != 0)) && !ignore_pattern(#field)) { \
1488
current_op.mismatch = #field; \
1489
printf("Mismatch in %s\n", #field); \
1492
CHECK_EQUAL(field.length); \
1495
#define CHECK_TIMES_EQUAL(field) do { \
1496
if (labs(parm[0].field - parm[1].field) > time_skew() && \
1497
!ignore_pattern(#field)) { \
1498
current_op.mismatch = #field; \
1499
printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
1500
(int)parm[0].field, (int)parm[1].field); \
1505
#define CHECK_NTTIMES_EQUAL(field) do { \
1506
if (labs(nt_time_to_unix(parm[0].field) - \
1507
nt_time_to_unix(parm[1].field)) > time_skew() && \
1508
!ignore_pattern(#field)) { \
1509
current_op.mismatch = #field; \
1510
printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
1511
(int)nt_time_to_unix(parm[0].field), \
1512
(int)nt_time_to_unix(parm[1].field)); \
1519
compare returned fileinfo structures
1521
static bool cmp_fileinfo(int instance,
1522
union smb_fileinfo parm[NSERVERS],
1523
NTSTATUS status[NSERVERS])
1526
enum smb_fileinfo_level level = parm[0].generic.level;
1528
if (level == RAW_FILEINFO_ALL_INFORMATION &&
1530
level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
1534
case RAW_FILEINFO_GENERIC:
1537
case RAW_FILEINFO_GETATTR:
1538
CHECK_ATTRIB(getattr.out.attrib);
1539
CHECK_EQUAL(getattr.out.size);
1540
CHECK_TIMES_EQUAL(getattr.out.write_time);
1543
case RAW_FILEINFO_GETATTRE:
1544
CHECK_TIMES_EQUAL(getattre.out.create_time);
1545
CHECK_TIMES_EQUAL(getattre.out.access_time);
1546
CHECK_TIMES_EQUAL(getattre.out.write_time);
1547
CHECK_EQUAL(getattre.out.size);
1548
CHECK_EQUAL(getattre.out.alloc_size);
1549
CHECK_ATTRIB(getattre.out.attrib);
1552
case RAW_FILEINFO_STANDARD:
1553
CHECK_TIMES_EQUAL(standard.out.create_time);
1554
CHECK_TIMES_EQUAL(standard.out.access_time);
1555
CHECK_TIMES_EQUAL(standard.out.write_time);
1556
CHECK_EQUAL(standard.out.size);
1557
CHECK_EQUAL(standard.out.alloc_size);
1558
CHECK_ATTRIB(standard.out.attrib);
1561
case RAW_FILEINFO_EA_SIZE:
1562
CHECK_TIMES_EQUAL(ea_size.out.create_time);
1563
CHECK_TIMES_EQUAL(ea_size.out.access_time);
1564
CHECK_TIMES_EQUAL(ea_size.out.write_time);
1565
CHECK_EQUAL(ea_size.out.size);
1566
CHECK_EQUAL(ea_size.out.alloc_size);
1567
CHECK_ATTRIB(ea_size.out.attrib);
1568
CHECK_EQUAL(ea_size.out.ea_size);
1571
case RAW_FILEINFO_ALL_EAS:
1572
CHECK_EQUAL(all_eas.out.num_eas);
1573
for (i=0;i<parm[0].all_eas.out.num_eas;i++) {
1574
CHECK_EQUAL(all_eas.out.eas[i].flags);
1575
CHECK_WSTR_EQUAL(all_eas.out.eas[i].name);
1576
CHECK_BLOB_EQUAL(all_eas.out.eas[i].value);
1580
case RAW_FILEINFO_IS_NAME_VALID:
1583
case RAW_FILEINFO_BASIC_INFO:
1584
case RAW_FILEINFO_BASIC_INFORMATION:
1585
CHECK_NTTIMES_EQUAL(basic_info.out.create_time);
1586
CHECK_NTTIMES_EQUAL(basic_info.out.access_time);
1587
CHECK_NTTIMES_EQUAL(basic_info.out.write_time);
1588
CHECK_NTTIMES_EQUAL(basic_info.out.change_time);
1589
CHECK_ATTRIB(basic_info.out.attrib);
1592
case RAW_FILEINFO_STANDARD_INFO:
1593
case RAW_FILEINFO_STANDARD_INFORMATION:
1594
CHECK_EQUAL(standard_info.out.alloc_size);
1595
CHECK_EQUAL(standard_info.out.size);
1596
CHECK_EQUAL(standard_info.out.nlink);
1597
CHECK_EQUAL(standard_info.out.delete_pending);
1598
CHECK_EQUAL(standard_info.out.directory);
1601
case RAW_FILEINFO_EA_INFO:
1602
case RAW_FILEINFO_EA_INFORMATION:
1603
CHECK_EQUAL(ea_info.out.ea_size);
1606
case RAW_FILEINFO_NAME_INFO:
1607
case RAW_FILEINFO_NAME_INFORMATION:
1608
CHECK_WSTR_EQUAL(name_info.out.fname);
1611
case RAW_FILEINFO_ALL_INFO:
1612
case RAW_FILEINFO_ALL_INFORMATION:
1613
CHECK_NTTIMES_EQUAL(all_info.out.create_time);
1614
CHECK_NTTIMES_EQUAL(all_info.out.access_time);
1615
CHECK_NTTIMES_EQUAL(all_info.out.write_time);
1616
CHECK_NTTIMES_EQUAL(all_info.out.change_time);
1617
CHECK_ATTRIB(all_info.out.attrib);
1618
CHECK_EQUAL(all_info.out.alloc_size);
1619
CHECK_EQUAL(all_info.out.size);
1620
CHECK_EQUAL(all_info.out.nlink);
1621
CHECK_EQUAL(all_info.out.delete_pending);
1622
CHECK_EQUAL(all_info.out.directory);
1623
CHECK_EQUAL(all_info.out.ea_size);
1624
CHECK_WSTR_EQUAL(all_info.out.fname);
1627
case RAW_FILEINFO_ALT_NAME_INFO:
1628
case RAW_FILEINFO_ALT_NAME_INFORMATION:
1629
CHECK_WSTR_EQUAL(alt_name_info.out.fname);
1632
case RAW_FILEINFO_STREAM_INFO:
1633
case RAW_FILEINFO_STREAM_INFORMATION:
1634
CHECK_EQUAL(stream_info.out.num_streams);
1635
for (i=0;i<parm[0].stream_info.out.num_streams;i++) {
1636
CHECK_EQUAL(stream_info.out.streams[i].size);
1637
CHECK_EQUAL(stream_info.out.streams[i].alloc_size);
1638
CHECK_WSTR_EQUAL(stream_info.out.streams[i].stream_name);
1642
case RAW_FILEINFO_COMPRESSION_INFO:
1643
case RAW_FILEINFO_COMPRESSION_INFORMATION:
1644
CHECK_EQUAL(compression_info.out.compressed_size);
1645
CHECK_EQUAL(compression_info.out.format);
1646
CHECK_EQUAL(compression_info.out.unit_shift);
1647
CHECK_EQUAL(compression_info.out.chunk_shift);
1648
CHECK_EQUAL(compression_info.out.cluster_shift);
1651
case RAW_FILEINFO_INTERNAL_INFORMATION:
1652
CHECK_EQUAL(internal_information.out.file_id);
1655
case RAW_FILEINFO_ACCESS_INFORMATION:
1656
CHECK_EQUAL(access_information.out.access_flags);
1659
case RAW_FILEINFO_POSITION_INFORMATION:
1660
CHECK_EQUAL(position_information.out.position);
1663
case RAW_FILEINFO_MODE_INFORMATION:
1664
CHECK_EQUAL(mode_information.out.mode);
1667
case RAW_FILEINFO_ALIGNMENT_INFORMATION:
1668
CHECK_EQUAL(alignment_information.out.alignment_requirement);
1671
case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
1672
CHECK_NTTIMES_EQUAL(network_open_information.out.create_time);
1673
CHECK_NTTIMES_EQUAL(network_open_information.out.access_time);
1674
CHECK_NTTIMES_EQUAL(network_open_information.out.write_time);
1675
CHECK_NTTIMES_EQUAL(network_open_information.out.change_time);
1676
CHECK_EQUAL(network_open_information.out.alloc_size);
1677
CHECK_EQUAL(network_open_information.out.size);
1678
CHECK_ATTRIB(network_open_information.out.attrib);
1681
case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
1682
CHECK_ATTRIB(attribute_tag_information.out.attrib);
1683
CHECK_EQUAL(attribute_tag_information.out.reparse_tag);
1686
case RAW_FILEINFO_SMB2_ALL_INFORMATION:
1687
CHECK_NTTIMES_EQUAL(all_info2.out.create_time);
1688
CHECK_NTTIMES_EQUAL(all_info2.out.access_time);
1689
CHECK_NTTIMES_EQUAL(all_info2.out.write_time);
1690
CHECK_NTTIMES_EQUAL(all_info2.out.change_time);
1691
CHECK_ATTRIB(all_info2.out.attrib);
1692
CHECK_EQUAL(all_info2.out.unknown1);
1693
CHECK_EQUAL(all_info2.out.alloc_size);
1694
CHECK_EQUAL(all_info2.out.size);
1695
CHECK_EQUAL(all_info2.out.nlink);
1696
CHECK_EQUAL(all_info2.out.delete_pending);
1697
CHECK_EQUAL(all_info2.out.directory);
1698
CHECK_EQUAL(all_info2.out.file_id);
1699
CHECK_EQUAL(all_info2.out.ea_size);
1700
CHECK_EQUAL(all_info2.out.access_mask);
1701
CHECK_EQUAL(all_info2.out.position);
1702
CHECK_EQUAL(all_info2.out.mode);
1703
CHECK_EQUAL(all_info2.out.alignment_requirement);
1704
CHECK_WSTR_EQUAL(all_info2.out.fname);
1707
case RAW_FILEINFO_SMB2_ALL_EAS:
1708
CHECK_EQUAL(all_eas.out.num_eas);
1709
for (i=0;i<parm[0].all_eas.out.num_eas;i++) {
1710
CHECK_EQUAL(all_eas.out.eas[i].flags);
1711
CHECK_WSTR_EQUAL(all_eas.out.eas[i].name);
1712
CHECK_BLOB_EQUAL(all_eas.out.eas[i].value);
1716
case RAW_FILEINFO_SEC_DESC:
1717
CHECK_SECDESC(query_secdesc.out.sd);
1720
/* Unhandled levels */
1721
case RAW_FILEINFO_EA_LIST:
1722
case RAW_FILEINFO_UNIX_BASIC:
1723
case RAW_FILEINFO_UNIX_LINK:
1724
case RAW_FILEINFO_UNIX_INFO2:
1734
generate openx operations
1736
static bool handler_smb_openx(int instance)
1738
union smb_open parm[NSERVERS];
1739
NTSTATUS status[NSERVERS];
1741
parm[0].openx.level = RAW_OPEN_OPENX;
1742
parm[0].openx.in.flags = gen_openx_flags();
1743
parm[0].openx.in.open_mode = gen_openx_mode();
1744
parm[0].openx.in.search_attrs = gen_attrib();
1745
parm[0].openx.in.file_attrs = gen_attrib();
1746
parm[0].openx.in.write_time = gen_timet();
1747
parm[0].openx.in.open_func = gen_openx_func();
1748
parm[0].openx.in.size = gen_io_count();
1749
parm[0].openx.in.timeout = gen_timeout();
1750
parm[0].openx.in.fname = gen_fname_open(instance);
1752
if (!options.use_oplocks) {
1753
/* mask out oplocks */
1754
parm[0].openx.in.flags &= ~(OPENX_FLAGS_REQUEST_OPLOCK|
1755
OPENX_FLAGS_REQUEST_BATCH_OPLOCK);
1759
GEN_CALL_SMB(smb_raw_open(tree, current_op.mem_ctx, &parm[i]));
1761
CHECK_ATTRIB(openx.out.attrib);
1762
CHECK_EQUAL(openx.out.size);
1763
CHECK_EQUAL(openx.out.access);
1764
CHECK_EQUAL(openx.out.ftype);
1765
CHECK_EQUAL(openx.out.devstate);
1766
CHECK_EQUAL(openx.out.action);
1767
CHECK_EQUAL(openx.out.access_mask);
1768
CHECK_EQUAL(openx.out.unknown);
1769
CHECK_TIMES_EQUAL(openx.out.write_time);
1771
/* open creates a new file handle */
1772
ADD_HANDLE_SMB(parm[0].openx.in.fname, openx.out.file.fnum);
1779
generate open operations
1781
static bool handler_smb_open(int instance)
1783
union smb_open parm[NSERVERS];
1784
NTSTATUS status[NSERVERS];
1786
parm[0].openold.level = RAW_OPEN_OPEN;
1787
parm[0].openold.in.open_mode = gen_bits_mask2(0xF, 0xFFFF);
1788
parm[0].openold.in.search_attrs = gen_attrib();
1789
parm[0].openold.in.fname = gen_fname_open(instance);
1791
if (!options.use_oplocks) {
1792
/* mask out oplocks */
1793
parm[0].openold.in.open_mode &= ~(OPENX_FLAGS_REQUEST_OPLOCK|
1794
OPENX_FLAGS_REQUEST_BATCH_OPLOCK);
1798
GEN_CALL_SMB(smb_raw_open(tree, current_op.mem_ctx, &parm[i]));
1800
CHECK_ATTRIB(openold.out.attrib);
1801
CHECK_TIMES_EQUAL(openold.out.write_time);
1802
CHECK_EQUAL(openold.out.size);
1803
CHECK_EQUAL(openold.out.rmode);
1805
/* open creates a new file handle */
1806
ADD_HANDLE_SMB(parm[0].openold.in.fname, openold.out.file.fnum);
1813
generate ntcreatex operations
1815
static bool handler_smb_ntcreatex(int instance)
1817
union smb_open parm[NSERVERS];
1818
NTSTATUS status[NSERVERS];
1820
parm[0].ntcreatex.level = RAW_OPEN_NTCREATEX;
1821
parm[0].ntcreatex.in.flags = gen_ntcreatex_flags();
1822
parm[0].ntcreatex.in.root_fid = gen_root_fid(instance);
1823
parm[0].ntcreatex.in.access_mask = gen_access_mask();
1824
parm[0].ntcreatex.in.alloc_size = gen_alloc_size();
1825
parm[0].ntcreatex.in.file_attr = gen_attrib();
1826
parm[0].ntcreatex.in.share_access = gen_bits_mask2(0x7, 0xFFFFFFFF);
1827
parm[0].ntcreatex.in.open_disposition = gen_open_disp();
1828
parm[0].ntcreatex.in.create_options = gen_create_options();
1829
parm[0].ntcreatex.in.impersonation = gen_bits_mask2(0, 0xFFFFFFFF);
1830
parm[0].ntcreatex.in.security_flags = gen_bits_mask2(0, 0xFF);
1831
parm[0].ntcreatex.in.fname = gen_fname_open(instance);
1833
if (!options.use_oplocks) {
1834
/* mask out oplocks */
1835
parm[0].ntcreatex.in.flags &= ~(NTCREATEX_FLAGS_REQUEST_OPLOCK|
1836
NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK);
1840
if (parm[0].ntcreatex.in.root_fid != 0) {
1841
GEN_SET_FNUM_SMB(ntcreatex.in.root_fid);
1843
GEN_CALL_SMB(smb_raw_open(tree, current_op.mem_ctx, &parm[i]));
1845
CHECK_EQUAL(ntcreatex.out.oplock_level);
1846
CHECK_EQUAL(ntcreatex.out.create_action);
1847
CHECK_NTTIMES_EQUAL(ntcreatex.out.create_time);
1848
CHECK_NTTIMES_EQUAL(ntcreatex.out.access_time);
1849
CHECK_NTTIMES_EQUAL(ntcreatex.out.write_time);
1850
CHECK_NTTIMES_EQUAL(ntcreatex.out.change_time);
1851
CHECK_ATTRIB(ntcreatex.out.attrib);
1852
CHECK_EQUAL(ntcreatex.out.alloc_size);
1853
CHECK_EQUAL(ntcreatex.out.size);
1854
CHECK_EQUAL(ntcreatex.out.file_type);
1855
CHECK_EQUAL(ntcreatex.out.ipc_state);
1856
CHECK_EQUAL(ntcreatex.out.is_directory);
1858
/* ntcreatex creates a new file handle */
1859
ADD_HANDLE_SMB(parm[0].ntcreatex.in.fname, ntcreatex.out.file.fnum);
1865
generate close operations
1867
static bool handler_smb_close(int instance)
1869
union smb_close parm[NSERVERS];
1870
NTSTATUS status[NSERVERS];
1872
parm[0].close.level = RAW_CLOSE_CLOSE;
1873
parm[0].close.in.file.fnum = gen_fnum_close(instance);
1874
parm[0].close.in.write_time = gen_timet();
1877
GEN_SET_FNUM_SMB(close.in.file.fnum);
1878
GEN_CALL_SMB(smb_raw_close(tree, &parm[i]));
1880
REMOVE_HANDLE_SMB(close.in.file.fnum);
1886
generate unlink operations
1888
static bool handler_smb_unlink(int instance)
1890
union smb_unlink parm[NSERVERS];
1891
NTSTATUS status[NSERVERS];
1893
parm[0].unlink.in.pattern = gen_pattern();
1894
parm[0].unlink.in.attrib = gen_attrib();
1897
GEN_CALL_SMB(smb_raw_unlink(tree, &parm[i]));
1903
generate chkpath operations
1905
static bool handler_smb_chkpath(int instance)
1907
union smb_chkpath parm[NSERVERS];
1908
NTSTATUS status[NSERVERS];
1910
parm[0].chkpath.in.path = gen_fname_open(instance);
1913
GEN_CALL_SMB(smb_raw_chkpath(tree, &parm[i]));
1919
generate mkdir operations
1921
static bool handler_smb_mkdir(int instance)
1923
union smb_mkdir parm[NSERVERS];
1924
NTSTATUS status[NSERVERS];
1926
parm[0].mkdir.level = RAW_MKDIR_MKDIR;
1927
parm[0].mkdir.in.path = gen_fname_open(instance);
1930
GEN_CALL_SMB(smb_raw_mkdir(tree, &parm[i]));
1936
generate rmdir operations
1938
static bool handler_smb_rmdir(int instance)
1940
struct smb_rmdir parm[NSERVERS];
1941
NTSTATUS status[NSERVERS];
1943
parm[0].in.path = gen_fname_open(instance);
1946
GEN_CALL_SMB(smb_raw_rmdir(tree, &parm[i]));
1952
generate rename operations
1954
static bool handler_smb_rename(int instance)
1956
union smb_rename parm[NSERVERS];
1957
NTSTATUS status[NSERVERS];
1959
parm[0].generic.level = RAW_RENAME_RENAME;
1960
parm[0].rename.in.pattern1 = gen_pattern();
1961
parm[0].rename.in.pattern2 = gen_pattern();
1962
parm[0].rename.in.attrib = gen_attrib();
1965
GEN_CALL_SMB(smb_raw_rename(tree, &parm[i]));
1971
generate ntrename operations
1973
static bool handler_smb_ntrename(int instance)
1975
union smb_rename parm[NSERVERS];
1976
NTSTATUS status[NSERVERS];
1978
parm[0].generic.level = RAW_RENAME_NTRENAME;
1979
parm[0].ntrename.in.old_name = gen_fname();
1980
parm[0].ntrename.in.new_name = gen_fname();
1981
parm[0].ntrename.in.attrib = gen_attrib();
1982
parm[0].ntrename.in.cluster_size = gen_bits_mask2(0, 0xFFFFFFF);
1983
parm[0].ntrename.in.flags = gen_rename_flags();
1986
GEN_CALL_SMB(smb_raw_rename(tree, &parm[i]));
1993
generate seek operations
1995
static bool handler_smb_seek(int instance)
1997
union smb_seek parm[NSERVERS];
1998
NTSTATUS status[NSERVERS];
2000
parm[0].lseek.in.file.fnum = gen_fnum(instance);
2001
parm[0].lseek.in.mode = gen_bits_mask2(0x3, 0xFFFF);
2002
parm[0].lseek.in.offset = gen_offset();
2005
GEN_SET_FNUM_SMB(lseek.in.file.fnum);
2006
GEN_CALL_SMB(smb_raw_seek(tree, &parm[i]));
2008
CHECK_EQUAL(lseek.out.offset);
2015
generate readx operations
2017
static bool handler_smb_readx(int instance)
2019
union smb_read parm[NSERVERS];
2020
NTSTATUS status[NSERVERS];
2022
parm[0].readx.level = RAW_READ_READX;
2023
parm[0].readx.in.file.fnum = gen_fnum(instance);
2024
parm[0].readx.in.offset = gen_offset();
2025
parm[0].readx.in.mincnt = gen_io_count();
2026
parm[0].readx.in.maxcnt = gen_io_count();
2027
parm[0].readx.in.remaining = gen_io_count();
2028
parm[0].readx.in.read_for_execute = gen_bool();
2029
parm[0].readx.out.data = talloc_array(current_op.mem_ctx, uint8_t,
2030
MAX(parm[0].readx.in.mincnt, parm[0].readx.in.maxcnt));
2033
GEN_SET_FNUM_SMB(readx.in.file.fnum);
2034
GEN_CALL_SMB(smb_raw_read(tree, &parm[i]));
2036
CHECK_EQUAL(readx.out.remaining);
2037
CHECK_EQUAL(readx.out.compaction_mode);
2038
CHECK_EQUAL(readx.out.nread);
2044
generate writex operations
2046
static bool handler_smb_writex(int instance)
2048
union smb_write parm[NSERVERS];
2049
NTSTATUS status[NSERVERS];
2051
parm[0].writex.level = RAW_WRITE_WRITEX;
2052
parm[0].writex.in.file.fnum = gen_fnum(instance);
2053
parm[0].writex.in.offset = gen_offset();
2054
parm[0].writex.in.wmode = gen_bits_mask(0xFFFF);
2055
parm[0].writex.in.remaining = gen_io_count();
2056
parm[0].writex.in.count = gen_io_count();
2057
parm[0].writex.in.data = talloc_zero_array(current_op.mem_ctx, uint8_t, parm[0].writex.in.count);
2060
GEN_SET_FNUM_SMB(writex.in.file.fnum);
2061
GEN_CALL_SMB(smb_raw_write(tree, &parm[i]));
2063
CHECK_EQUAL(writex.out.nwritten);
2064
CHECK_EQUAL(writex.out.remaining);
2070
generate lockingx operations
2072
static bool handler_smb_lockingx(int instance)
2074
union smb_lock parm[NSERVERS];
2075
NTSTATUS status[NSERVERS];
2078
parm[0].lockx.level = RAW_LOCK_LOCKX;
2079
parm[0].lockx.in.file.fnum = gen_fnum(instance);
2080
parm[0].lockx.in.mode = gen_lock_mode();
2081
parm[0].lockx.in.timeout = gen_timeout();
2083
/* make sure we don't accidentially generate an oplock
2084
break ack - otherwise the server can just block forever */
2085
parm[0].lockx.in.ulock_cnt = gen_lock_count();
2086
parm[0].lockx.in.lock_cnt = gen_lock_count();
2087
nlocks = parm[0].lockx.in.ulock_cnt + parm[0].lockx.in.lock_cnt;
2088
} while (nlocks == 0);
2091
parm[0].lockx.in.locks = talloc_array(current_op.mem_ctx,
2092
struct smb_lock_entry,
2094
for (n=0;n<nlocks;n++) {
2095
parm[0].lockx.in.locks[n].pid = gen_pid();
2096
parm[0].lockx.in.locks[n].offset = gen_offset();
2097
parm[0].lockx.in.locks[n].count = gen_io_count();
2102
GEN_SET_FNUM_SMB(lockx.in.file.fnum);
2103
GEN_CALL_SMB(smb_raw_lock(tree, &parm[i]));
2110
generate a fileinfo query structure
2112
static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
2116
#define LVL(v) {RAW_SFILEINFO_ ## v, "RAW_SFILEINFO_" #v}
2118
enum smb_setfileinfo_level level;
2122
/* disabled until win2003 can handle them ... */
2123
LVL(EA_SET), LVL(BASIC_INFO), LVL(DISPOSITION_INFO),
2124
LVL(STANDARD), LVL(ALLOCATION_INFO), LVL(END_OF_FILE_INFO),
2126
LVL(SETATTR), LVL(SETATTRE), LVL(BASIC_INFORMATION),
2127
LVL(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION),
2128
LVL(POSITION_INFORMATION), LVL(MODE_INFORMATION),
2129
LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION),
2130
LVL(1023), LVL(1025), LVL(1029), LVL(1032), LVL(1039), LVL(1040)
2133
i = gen_int_range(0, ARRAY_SIZE(levels)-1);
2134
} while (ignore_pattern(levels[i].name));
2136
info->generic.level = levels[i].level;
2138
switch (info->generic.level) {
2139
case RAW_SFILEINFO_SETATTR:
2140
info->setattr.in.attrib = gen_attrib();
2141
info->setattr.in.write_time = gen_timet();
2143
case RAW_SFILEINFO_SETATTRE:
2144
info->setattre.in.create_time = gen_timet();
2145
info->setattre.in.access_time = gen_timet();
2146
info->setattre.in.write_time = gen_timet();
2148
case RAW_SFILEINFO_STANDARD:
2149
info->standard.in.create_time = gen_timet();
2150
info->standard.in.access_time = gen_timet();
2151
info->standard.in.write_time = gen_timet();
2153
case RAW_SFILEINFO_EA_SET: {
2154
static struct ea_struct ea;
2155
info->ea_set.in.num_eas = 1;
2156
info->ea_set.in.eas = &ea;
2157
info->ea_set.in.eas[0] = gen_ea_struct();
2160
case RAW_SFILEINFO_BASIC_INFO:
2161
case RAW_SFILEINFO_BASIC_INFORMATION:
2162
info->basic_info.in.create_time = gen_nttime();
2163
info->basic_info.in.access_time = gen_nttime();
2164
info->basic_info.in.write_time = gen_nttime();
2165
info->basic_info.in.change_time = gen_nttime();
2166
info->basic_info.in.attrib = gen_attrib();
2168
case RAW_SFILEINFO_DISPOSITION_INFO:
2169
case RAW_SFILEINFO_DISPOSITION_INFORMATION:
2170
info->disposition_info.in.delete_on_close = gen_bool();
2172
case RAW_SFILEINFO_ALLOCATION_INFO:
2173
case RAW_SFILEINFO_ALLOCATION_INFORMATION:
2174
info->allocation_info.in.alloc_size = gen_alloc_size();
2176
case RAW_SFILEINFO_END_OF_FILE_INFO:
2177
case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
2178
info->end_of_file_info.in.size = gen_offset();
2180
case RAW_SFILEINFO_RENAME_INFORMATION:
2181
case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
2182
info->rename_information.in.overwrite = gen_bool();
2183
info->rename_information.in.root_fid = gen_root_fid(instance);
2184
info->rename_information.in.new_name = gen_fname_open(instance);
2186
case RAW_SFILEINFO_POSITION_INFORMATION:
2187
info->position_information.in.position = gen_offset();
2189
case RAW_SFILEINFO_MODE_INFORMATION:
2190
info->mode_information.in.mode = gen_bits_mask(0xFFFFFFFF);
2192
case RAW_SFILEINFO_FULL_EA_INFORMATION:
2193
info->full_ea_information.in.eas = gen_ea_list();
2195
case RAW_SFILEINFO_GENERIC:
2196
case RAW_SFILEINFO_SEC_DESC:
2197
case RAW_SFILEINFO_UNIX_BASIC:
2198
case RAW_SFILEINFO_UNIX_LINK:
2199
case RAW_SFILEINFO_UNIX_HLINK:
2200
case RAW_SFILEINFO_1023:
2201
case RAW_SFILEINFO_1025:
2202
case RAW_SFILEINFO_1029:
2203
case RAW_SFILEINFO_1032:
2204
case RAW_SFILEINFO_1039:
2205
case RAW_SFILEINFO_1040:
2206
case RAW_SFILEINFO_UNIX_INFO2:
2214
generate a fileinfo query structure
2216
static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
2220
#define LVL(v) {RAW_SFILEINFO_ ## v, "RAW_SFILEINFO_" #v}
2222
enum smb_setfileinfo_level level;
2225
struct levels smb_levels[] = {
2226
LVL(EA_SET), LVL(BASIC_INFO), LVL(DISPOSITION_INFO),
2227
LVL(STANDARD), LVL(ALLOCATION_INFO), LVL(END_OF_FILE_INFO),
2228
LVL(SETATTR), LVL(SETATTRE), LVL(BASIC_INFORMATION),
2229
LVL(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION),
2230
LVL(POSITION_INFORMATION), LVL(FULL_EA_INFORMATION), LVL(MODE_INFORMATION),
2231
LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION),
2232
LVL(PIPE_INFORMATION), LVL(VALID_DATA_INFORMATION), LVL(SHORT_NAME_INFORMATION),
2233
LVL(1025), LVL(1027), LVL(1029), LVL(1030), LVL(1031), LVL(1032), LVL(1036),
2234
LVL(1041), LVL(1042), LVL(1043), LVL(1044),
2236
struct levels smb2_levels[] = {
2237
LVL(BASIC_INFORMATION),
2238
LVL(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION),
2239
LVL(POSITION_INFORMATION), LVL(FULL_EA_INFORMATION), LVL(MODE_INFORMATION),
2240
LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION),
2241
LVL(PIPE_INFORMATION), LVL(VALID_DATA_INFORMATION), LVL(SHORT_NAME_INFORMATION),
2242
LVL(1025), LVL(1027), LVL(1029), LVL(1030), LVL(1031), LVL(1032), LVL(1036),
2243
LVL(1041), LVL(1042), LVL(1043), LVL(1044),
2245
struct levels *levels = options.smb2?smb2_levels:smb_levels;
2246
uint32_t num_levels = options.smb2?ARRAY_SIZE(smb2_levels):ARRAY_SIZE(smb_levels);
2249
i = gen_int_range(0, num_levels-1);
2250
} while (ignore_pattern(levels[i].name));
2253
info->generic.level = levels[i].level;
2255
switch (info->generic.level) {
2256
case RAW_SFILEINFO_SETATTR:
2257
info->setattr.in.attrib = gen_attrib();
2258
info->setattr.in.write_time = gen_timet();
2260
case RAW_SFILEINFO_SETATTRE:
2261
info->setattre.in.create_time = gen_timet();
2262
info->setattre.in.access_time = gen_timet();
2263
info->setattre.in.write_time = gen_timet();
2265
case RAW_SFILEINFO_STANDARD:
2266
info->standard.in.create_time = gen_timet();
2267
info->standard.in.access_time = gen_timet();
2268
info->standard.in.write_time = gen_timet();
2270
case RAW_SFILEINFO_EA_SET: {
2271
static struct ea_struct ea;
2272
info->ea_set.in.num_eas = 1;
2273
info->ea_set.in.eas = &ea;
2274
info->ea_set.in.eas[0] = gen_ea_struct();
2277
case RAW_SFILEINFO_BASIC_INFO:
2278
case RAW_SFILEINFO_BASIC_INFORMATION:
2279
info->basic_info.in.create_time = gen_nttime();
2280
info->basic_info.in.access_time = gen_nttime();
2281
info->basic_info.in.write_time = gen_nttime();
2282
info->basic_info.in.change_time = gen_nttime();
2283
info->basic_info.in.attrib = gen_attrib();
2285
case RAW_SFILEINFO_DISPOSITION_INFO:
2286
case RAW_SFILEINFO_DISPOSITION_INFORMATION:
2287
info->disposition_info.in.delete_on_close = gen_bool();
2289
case RAW_SFILEINFO_ALLOCATION_INFO:
2290
case RAW_SFILEINFO_ALLOCATION_INFORMATION:
2291
info->allocation_info.in.alloc_size = gen_alloc_size();
2293
case RAW_SFILEINFO_END_OF_FILE_INFO:
2294
case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
2295
info->end_of_file_info.in.size = gen_offset();
2297
case RAW_SFILEINFO_RENAME_INFORMATION:
2298
case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
2299
info->rename_information.in.overwrite = gen_bool();
2300
info->rename_information.in.root_fid = gen_root_fid(instance);
2301
info->rename_information.in.new_name = gen_fname_open(instance);
2303
case RAW_SFILEINFO_POSITION_INFORMATION:
2304
info->position_information.in.position = gen_offset();
2306
case RAW_SFILEINFO_MODE_INFORMATION:
2307
info->mode_information.in.mode = gen_bits_mask(0xFFFFFFFF);
2309
case RAW_SFILEINFO_FULL_EA_INFORMATION:
2310
info->full_ea_information.in.eas = gen_ea_list();
2313
case RAW_SFILEINFO_GENERIC:
2314
case RAW_SFILEINFO_SEC_DESC:
2315
case RAW_SFILEINFO_1025:
2316
case RAW_SFILEINFO_1029:
2317
case RAW_SFILEINFO_1032:
2318
case RAW_SFILEINFO_UNIX_BASIC:
2319
case RAW_SFILEINFO_UNIX_INFO2:
2320
case RAW_SFILEINFO_UNIX_LINK:
2321
case RAW_SFILEINFO_UNIX_HLINK:
2330
generate a fileinfo query structure
2332
static void gen_fileinfo_smb(int instance, union smb_fileinfo *info)
2336
#define LVL(v) {RAW_FILEINFO_ ## v, "RAW_FILEINFO_" #v}
2338
enum smb_fileinfo_level level;
2341
LVL(GETATTR), LVL(GETATTRE), LVL(STANDARD),
2342
LVL(EA_SIZE), LVL(ALL_EAS), LVL(IS_NAME_VALID),
2343
LVL(BASIC_INFO), LVL(STANDARD_INFO), LVL(EA_INFO),
2344
LVL(NAME_INFO), LVL(ALL_INFO), LVL(ALT_NAME_INFO),
2345
LVL(STREAM_INFO), LVL(COMPRESSION_INFO), LVL(BASIC_INFORMATION),
2346
LVL(STANDARD_INFORMATION), LVL(INTERNAL_INFORMATION), LVL(EA_INFORMATION),
2347
LVL(ACCESS_INFORMATION), LVL(NAME_INFORMATION), LVL(POSITION_INFORMATION),
2348
LVL(MODE_INFORMATION), LVL(ALIGNMENT_INFORMATION), LVL(ALL_INFORMATION),
2349
LVL(ALT_NAME_INFORMATION), LVL(STREAM_INFORMATION), LVL(COMPRESSION_INFORMATION),
2350
LVL(NETWORK_OPEN_INFORMATION), LVL(ATTRIBUTE_TAG_INFORMATION)
2353
i = gen_int_range(0, ARRAY_SIZE(levels)-1);
2354
} while (ignore_pattern(levels[i].name));
2356
info->generic.level = levels[i].level;
2360
generate qpathinfo operations
2362
static bool handler_smb_qpathinfo(int instance)
2364
union smb_fileinfo parm[NSERVERS];
2365
NTSTATUS status[NSERVERS];
2367
parm[0].generic.in.file.path = gen_fname_open(instance);
2369
gen_fileinfo_smb(instance, &parm[0]);
2372
GEN_CALL_SMB(smb_raw_pathinfo(tree, current_op.mem_ctx, &parm[i]));
2374
return cmp_fileinfo(instance, parm, status);
2378
generate qfileinfo operations
2380
static bool handler_smb_qfileinfo(int instance)
2382
union smb_fileinfo parm[NSERVERS];
2383
NTSTATUS status[NSERVERS];
2385
parm[0].generic.in.file.fnum = gen_fnum(instance);
2387
gen_fileinfo_smb(instance, &parm[0]);
2390
GEN_SET_FNUM_SMB(generic.in.file.fnum);
2391
GEN_CALL_SMB(smb_raw_fileinfo(tree, current_op.mem_ctx, &parm[i]));
2393
return cmp_fileinfo(instance, parm, status);
2398
generate setpathinfo operations
2400
static bool handler_smb_spathinfo(int instance)
2402
union smb_setfileinfo parm[NSERVERS];
2403
NTSTATUS status[NSERVERS];
2405
gen_setfileinfo(instance, &parm[0]);
2406
parm[0].generic.in.file.path = gen_fname_open(instance);
2410
/* a special case for the fid in a RENAME */
2411
if (parm[0].generic.level == RAW_SFILEINFO_RENAME_INFORMATION &&
2412
parm[0].rename_information.in.root_fid != 0) {
2413
GEN_SET_FNUM_SMB(rename_information.in.root_fid);
2416
GEN_CALL_SMB(smb_raw_setpathinfo(tree, &parm[i]));
2423
generate setfileinfo operations
2425
static bool handler_smb_sfileinfo(int instance)
2427
union smb_setfileinfo parm[NSERVERS];
2428
NTSTATUS status[NSERVERS];
2430
parm[0].generic.in.file.fnum = gen_fnum(instance);
2432
gen_setfileinfo(instance, &parm[0]);
2435
GEN_SET_FNUM_SMB(generic.in.file.fnum);
2436
GEN_CALL_SMB(smb_raw_setfileinfo(tree, &parm[i]));
2443
this is called when a change notify reply comes in
2445
static void async_notify_smb(struct smbcli_request *req)
2447
union smb_notify notify;
2451
struct smbcli_transport *transport = req->transport;
2453
tid = SVAL(req->in.hdr, HDR_TID);
2455
notify.nttrans.level = RAW_NOTIFY_NTTRANS;
2456
status = smb_raw_changenotify_recv(req, current_op.mem_ctx, ¬ify);
2457
if (NT_STATUS_IS_OK(status) && notify.nttrans.out.num_changes > 0) {
2458
printf("notify tid=%d num_changes=%d action=%d name=%s\n",
2460
notify.nttrans.out.num_changes,
2461
notify.nttrans.out.changes[0].action,
2462
notify.nttrans.out.changes[0].name.s);
2465
for (i=0;i<NSERVERS;i++) {
2466
for (j=0;j<NINSTANCES;j++) {
2467
if (transport == servers[i].smb_tree[j]->session->transport &&
2468
tid == servers[i].smb_tree[j]->tid) {
2469
notifies[i][j].notify_count++;
2470
notifies[i][j].status = status;
2471
notifies[i][j].notify = notify;
2478
generate change notify operations
2480
static bool handler_smb_notify(int instance)
2482
union smb_notify parm[NSERVERS];
2485
ZERO_STRUCT(parm[0]);
2486
parm[0].nttrans.level = RAW_NOTIFY_NTTRANS;
2487
parm[0].nttrans.in.buffer_size = gen_io_count();
2488
parm[0].nttrans.in.completion_filter = gen_bits_mask(0xFF);
2489
parm[0].nttrans.in.file.fnum = gen_fnum(instance);
2490
parm[0].nttrans.in.recursive = gen_bool();
2493
GEN_SET_FNUM_SMB(nttrans.in.file.fnum);
2495
for (n=0;n<NSERVERS;n++) {
2496
struct smbcli_request *req;
2497
req = smb_raw_changenotify_send(servers[n].smb_tree[instance], &parm[n]);
2498
req->async.fn = async_notify_smb;
2506
generate ntcreatex operations
2508
static bool handler_smb2_create(int instance)
2510
struct smb2_create parm[NSERVERS];
2511
NTSTATUS status[NSERVERS];
2513
ZERO_STRUCT(parm[0]);
2514
parm[0].in.security_flags = gen_bits_levels(3, 90, 0x0, 70, 0x3, 100, 0xFF);
2515
parm[0].in.oplock_level = gen_bits_levels(3, 90, 0x0, 70, 0x9, 100, 0xFF);
2516
parm[0].in.impersonation_level = gen_bits_levels(3, 90, 0x0, 70, 0x3, 100, 0xFFFFFFFF);
2517
parm[0].in.create_flags = gen_reserved64();
2518
parm[0].in.reserved = gen_reserved64();
2519
parm[0].in.desired_access = gen_access_mask();
2520
parm[0].in.file_attributes = gen_attrib();
2521
parm[0].in.share_access = gen_bits_mask2(0x7, 0xFFFFFFFF);
2522
parm[0].in.create_disposition = gen_open_disp();
2523
parm[0].in.create_options = gen_create_options();
2524
parm[0].in.fname = gen_fname_open(instance);
2525
parm[0].in.eas = gen_ea_list();
2526
parm[0].in.alloc_size = gen_alloc_size();
2527
parm[0].in.durable_open = gen_bool();
2528
parm[0].in.query_maximal_access = gen_bool();
2529
parm[0].in.timewarp = gen_timewarp();
2530
parm[0].in.query_on_disk_id = gen_bool();
2531
parm[0].in.sec_desc = gen_sec_desc();
2533
if (!options.use_oplocks) {
2534
/* mask out oplocks */
2535
parm[0].in.oplock_level = 0;
2538
if (options.valid) {
2539
parm[0].in.security_flags &= 3;
2540
parm[0].in.oplock_level &= 9;
2541
parm[0].in.impersonation_level &= 3;
2545
GEN_CALL_SMB2(smb2_create(tree, current_op.mem_ctx, &parm[i]));
2547
CHECK_EQUAL(out.oplock_level);
2548
CHECK_EQUAL(out.reserved);
2549
CHECK_EQUAL(out.create_action);
2550
CHECK_NTTIMES_EQUAL(out.create_time);
2551
CHECK_NTTIMES_EQUAL(out.access_time);
2552
CHECK_NTTIMES_EQUAL(out.write_time);
2553
CHECK_NTTIMES_EQUAL(out.change_time);
2554
CHECK_EQUAL(out.alloc_size);
2555
CHECK_EQUAL(out.size);
2556
CHECK_ATTRIB(out.file_attr);
2557
CHECK_EQUAL(out.reserved2);
2558
CHECK_EQUAL(out.maximal_access);
2560
/* ntcreatex creates a new file handle */
2561
ADD_HANDLE_SMB2(parm[0].in.fname, out.file.handle);
2567
generate close operations
2569
static bool handler_smb2_close(int instance)
2571
struct smb2_close parm[NSERVERS];
2572
NTSTATUS status[NSERVERS];
2574
ZERO_STRUCT(parm[0]);
2575
parm[0].in.file.handle.data[0] = gen_fnum_close(instance);
2576
parm[0].in.flags = gen_bits_mask2(0x1, 0xFFFF);
2579
GEN_SET_FNUM_SMB2(in.file.handle);
2580
GEN_CALL_SMB2(smb2_close(tree, &parm[i]));
2582
CHECK_EQUAL(out.flags);
2583
CHECK_EQUAL(out._pad);
2584
CHECK_NTTIMES_EQUAL(out.create_time);
2585
CHECK_NTTIMES_EQUAL(out.access_time);
2586
CHECK_NTTIMES_EQUAL(out.write_time);
2587
CHECK_NTTIMES_EQUAL(out.change_time);
2588
CHECK_EQUAL(out.alloc_size);
2589
CHECK_EQUAL(out.size);
2590
CHECK_ATTRIB(out.file_attr);
2592
REMOVE_HANDLE_SMB2(in.file.handle);
2598
generate read operations
2600
static bool handler_smb2_read(int instance)
2602
struct smb2_read parm[NSERVERS];
2603
NTSTATUS status[NSERVERS];
2605
parm[0].in.file.handle.data[0] = gen_fnum(instance);
2606
parm[0].in.reserved = gen_reserved8();
2607
parm[0].in.length = gen_io_count();
2608
parm[0].in.offset = gen_offset();
2609
parm[0].in.min_count = gen_io_count();
2610
parm[0].in.channel = gen_bits_mask2(0x0, 0xFFFFFFFF);
2611
parm[0].in.remaining = gen_bits_mask2(0x0, 0xFFFFFFFF);
2612
parm[0].in.channel_offset = gen_bits_mask2(0x0, 0xFFFF);
2613
parm[0].in.channel_length = gen_bits_mask2(0x0, 0xFFFF);
2616
GEN_SET_FNUM_SMB2(in.file.handle);
2617
GEN_CALL_SMB2(smb2_read(tree, current_op.mem_ctx, &parm[i]));
2619
CHECK_EQUAL(out.remaining);
2620
CHECK_EQUAL(out.reserved);
2621
CHECK_EQUAL(out.data.length);
2627
generate write operations
2629
static bool handler_smb2_write(int instance)
2631
struct smb2_write parm[NSERVERS];
2632
NTSTATUS status[NSERVERS];
2634
parm[0].in.file.handle.data[0] = gen_fnum(instance);
2635
parm[0].in.offset = gen_offset();
2636
parm[0].in.unknown1 = gen_bits_mask2(0, 0xFFFFFFFF);
2637
parm[0].in.unknown2 = gen_bits_mask2(0, 0xFFFFFFFF);
2638
parm[0].in.data = data_blob_talloc(current_op.mem_ctx, NULL,
2642
GEN_SET_FNUM_SMB2(in.file.handle);
2643
GEN_CALL_SMB2(smb2_write(tree, &parm[i]));
2645
CHECK_EQUAL(out._pad);
2646
CHECK_EQUAL(out.nwritten);
2647
CHECK_EQUAL(out.unknown1);
2653
generate lockingx operations
2655
static bool handler_smb2_lock(int instance)
2657
struct smb2_lock parm[NSERVERS];
2658
NTSTATUS status[NSERVERS];
2661
parm[0].level = RAW_LOCK_LOCKX;
2662
parm[0].in.file.handle.data[0] = gen_fnum(instance);
2663
parm[0].in.lock_count = gen_lock_count();
2664
parm[0].in.reserved = gen_reserved32();
2666
parm[0].in.locks = talloc_array(current_op.mem_ctx,
2667
struct smb2_lock_element,
2668
parm[0].in.lock_count);
2669
for (n=0;n<parm[0].in.lock_count;n++) {
2670
parm[0].in.locks[n].offset = gen_offset();
2671
parm[0].in.locks[n].length = gen_io_count();
2672
/* don't yet cope with async replies */
2673
parm[0].in.locks[n].flags = gen_lock_flags_smb2() |
2674
SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2675
parm[0].in.locks[n].reserved = gen_bits_mask2(0x0, 0xFFFFFFFF);
2679
GEN_SET_FNUM_SMB2(in.file.handle);
2680
GEN_CALL_SMB2(smb2_lock(tree, &parm[i]));
2686
generate flush operations
2688
static bool handler_smb2_flush(int instance)
2690
struct smb2_flush parm[NSERVERS];
2691
NTSTATUS status[NSERVERS];
2693
ZERO_STRUCT(parm[0]);
2694
parm[0].in.file.handle.data[0] = gen_fnum(instance);
2695
parm[0].in.reserved1 = gen_reserved16();
2696
parm[0].in.reserved2 = gen_reserved32();
2699
GEN_SET_FNUM_SMB2(in.file.handle);
2700
GEN_CALL_SMB2(smb2_flush(tree, &parm[i]));
2702
CHECK_EQUAL(out.reserved);
2708
generate echo operations
2710
static bool handler_smb2_echo(int instance)
2712
NTSTATUS status[NSERVERS];
2714
GEN_CALL_SMB2(smb2_keepalive(tree->session->transport));
2722
generate a fileinfo query structure
2724
static void gen_fileinfo_smb2(int instance, union smb_fileinfo *info)
2727
#define LVL(v) {RAW_FILEINFO_ ## v, "RAW_FILEINFO_" #v}
2729
enum smb_fileinfo_level level;
2732
LVL(BASIC_INFORMATION),
2733
LVL(STANDARD_INFORMATION), LVL(INTERNAL_INFORMATION), LVL(EA_INFORMATION),
2734
LVL(ACCESS_INFORMATION), LVL(NAME_INFORMATION), LVL(POSITION_INFORMATION),
2735
LVL(MODE_INFORMATION), LVL(ALIGNMENT_INFORMATION), LVL(SMB2_ALL_INFORMATION),
2736
LVL(ALT_NAME_INFORMATION), LVL(STREAM_INFORMATION), LVL(COMPRESSION_INFORMATION),
2737
LVL(NETWORK_OPEN_INFORMATION), LVL(ATTRIBUTE_TAG_INFORMATION),
2738
LVL(SMB2_ALL_EAS), LVL(SMB2_ALL_INFORMATION), LVL(SEC_DESC),
2741
i = gen_int_range(0, ARRAY_SIZE(levels)-1);
2742
} while (ignore_pattern(levels[i].name));
2744
info->generic.level = levels[i].level;
2748
generate qfileinfo operations
2750
static bool handler_smb2_qfileinfo(int instance)
2752
union smb_fileinfo parm[NSERVERS];
2753
NTSTATUS status[NSERVERS];
2755
parm[0].generic.in.file.handle.data[0] = gen_fnum(instance);
2757
gen_fileinfo_smb2(instance, &parm[0]);
2760
GEN_SET_FNUM_SMB2(generic.in.file.handle);
2761
GEN_CALL_SMB2(smb2_getinfo_file(tree, current_op.mem_ctx, &parm[i]));
2763
return cmp_fileinfo(instance, parm, status);
2768
generate setfileinfo operations
2770
static bool handler_smb2_sfileinfo(int instance)
2772
union smb_setfileinfo parm[NSERVERS];
2773
NTSTATUS status[NSERVERS];
2775
gen_setfileinfo(instance, &parm[0]);
2776
parm[0].generic.in.file.fnum = gen_fnum(instance);
2779
GEN_SET_FNUM_SMB2(generic.in.file.handle);
2780
GEN_CALL_SMB2(smb2_setinfo_file(tree, &parm[i]));
2786
wipe any relevant files
2788
static void wipe_files(void)
2793
if (options.skip_cleanup) {
2797
for (i=0;i<NSERVERS;i++) {
2800
n = smb2_deltree(servers[i].smb2_tree[0], "gentest");
2802
n = smbcli_deltree(servers[i].smb_tree[0], "gentest");
2805
printf("Failed to wipe tree on server %d\n", i);
2809
status = smb2_util_mkdir(servers[i].smb2_tree[0], "gentest");
2811
status = smbcli_mkdir(servers[i].smb_tree[0], "gentest");
2813
if (NT_STATUS_IS_ERR(status)) {
2814
printf("Failed to create gentest on server %d - %s\n", i, nt_errstr(status));
2818
printf("Deleted %d files on server %d\n", n, i);
2824
dump the current seeds - useful for continuing a backtrack
2826
static void dump_seeds(void)
2831
if (!options.seeds_file) {
2834
f = fopen("seeds.tmp", "w");
2837
for (i=0;i<options.numops;i++) {
2838
fprintf(f, "%u\n", op_parms[i].seed);
2841
rename("seeds.tmp", options.seeds_file);
2847
the list of top-level operations that we will generate
2851
bool (*handler)(int instance);
2853
int count, success_count;
2855
{"CREATE", handler_smb2_create, true},
2856
{"CLOSE", handler_smb2_close, true},
2857
{"READ", handler_smb2_read, true},
2858
{"WRITE", handler_smb2_write, true},
2859
{"LOCK", handler_smb2_lock, true},
2860
{"FLUSH", handler_smb2_flush, true},
2861
{"ECHO", handler_smb2_echo, true},
2862
{"QFILEINFO", handler_smb2_qfileinfo, true},
2863
{"SFILEINFO", handler_smb2_sfileinfo, true},
2865
{"OPEN", handler_smb_open, false},
2866
{"OPENX", handler_smb_openx, false},
2867
{"NTCREATEX", handler_smb_ntcreatex, false},
2868
{"CLOSE", handler_smb_close, false},
2869
{"UNLINK", handler_smb_unlink, false},
2870
{"MKDIR", handler_smb_mkdir, false},
2871
{"RMDIR", handler_smb_rmdir, false},
2872
{"RENAME", handler_smb_rename, false},
2873
{"NTRENAME", handler_smb_ntrename, false},
2874
{"READX", handler_smb_readx, false},
2875
{"WRITEX", handler_smb_writex, false},
2876
{"CHKPATH", handler_smb_chkpath, false},
2877
{"SEEK", handler_smb_seek, false},
2878
{"LOCKINGX", handler_smb_lockingx, false},
2879
{"QPATHINFO", handler_smb_qpathinfo, false},
2880
{"QFILEINFO", handler_smb_qfileinfo, false},
2881
{"SPATHINFO", handler_smb_spathinfo, false},
2882
{"SFILEINFO", handler_smb_sfileinfo, false},
2883
{"NOTIFY", handler_smb_notify, false},
2884
{"SEEK", handler_smb_seek, false},
2889
run the test with the current set of op_parms parameters
2890
return the number of operations that completed successfully
2892
static int run_test(struct tevent_context *ev, struct loadparm_context *lp_ctx)
2896
if (!connect_servers(ev, lp_ctx)) {
2897
printf("Failed to connect to servers\n");
2903
/* wipe any leftover files from old runs */
2906
/* reset the open handles array */
2907
memset(open_handles, 0, options.max_open_handles * sizeof(open_handles[0]));
2908
num_open_handles = 0;
2910
for (i=0;i<ARRAY_SIZE(gen_ops);i++) {
2911
gen_ops[i].count = 0;
2912
gen_ops[i].success_count = 0;
2915
for (op=0; op<options.numops; op++) {
2916
int instance, which_op;
2919
if (op_parms[op].disabled) continue;
2921
srandom(op_parms[op].seed);
2923
instance = gen_int_range(0, NINSTANCES-1);
2925
/* generate a non-ignored operation */
2927
which_op = gen_int_range(0, ARRAY_SIZE(gen_ops)-1);
2928
} while (ignore_pattern(gen_ops[which_op].name) ||
2929
gen_ops[which_op].smb2 != options.smb2);
2931
DEBUG(3,("Generating op %s on instance %d\n",
2932
gen_ops[which_op].name, instance));
2934
current_op.seed = op_parms[op].seed;
2935
current_op.opnum = op;
2936
current_op.name = gen_ops[which_op].name;
2937
current_op.status = NT_STATUS_OK;
2938
talloc_free(current_op.mem_ctx);
2939
current_op.mem_ctx = talloc_named(NULL, 0, "%s", current_op.name);
2941
ret = gen_ops[which_op].handler(instance);
2943
gen_ops[which_op].count++;
2944
if (NT_STATUS_IS_OK(current_op.status)) {
2945
gen_ops[which_op].success_count++;
2949
printf("Failed at operation %d - %s\n",
2950
op, gen_ops[which_op].name);
2954
if (op % 100 == 0) {
2959
for (i=0;i<ARRAY_SIZE(gen_ops);i++) {
2960
printf("Op %-10s got %d/%d success\n",
2962
gen_ops[i].success_count,
2970
perform a backtracking analysis of the minimal set of operations
2971
to generate an error
2973
static void backtrack_analyze(struct tevent_context *ev,
2974
struct loadparm_context *lp_ctx)
2977
const char *mismatch = current_op.mismatch;
2979
chunk = options.numops / 2;
2984
chunk > 0 && base+chunk < options.numops && options.numops > 1; ) {
2987
chunk = MIN(chunk, options.numops / 2);
2989
/* mark this range as disabled */
2990
max = MIN(options.numops, base+chunk);
2991
for (i=base;i<max; i++) {
2992
op_parms[i].disabled = true;
2994
printf("Testing %d ops with %d-%d disabled\n",
2995
options.numops, base, max-1);
2996
ret = run_test(ev, lp_ctx);
2997
printf("Completed %d of %d ops\n", ret, options.numops);
2998
for (i=base;i<max; i++) {
2999
op_parms[i].disabled = false;
3001
if (ret == options.numops) {
3002
/* this chunk is needed */
3004
} else if (mismatch != current_op.mismatch &&
3005
strcmp(mismatch, current_op.mismatch)) {
3007
printf("Different error in backtracking\n");
3008
} else if (ret < base) {
3009
printf("damn - inconsistent errors! found early error\n");
3010
options.numops = ret+1;
3013
/* it failed - this chunk isn't needed for a failure */
3014
memmove(&op_parms[base], &op_parms[max],
3015
sizeof(op_parms[0]) * (options.numops - max));
3016
options.numops = (ret+1) - (max - base);
3026
if (options.analyze_continuous && chunk == 0 && options.numops != 1) {
3029
} while (chunk > 0);
3031
printf("Reduced to %d ops\n", options.numops);
3032
ret = run_test(ev, lp_ctx);
3033
if (ret != options.numops - 1) {
3034
printf("Inconsistent result? ret=%d numops=%d\n", ret, options.numops);
3039
start the main gentest process
3041
static bool start_gentest(struct tevent_context *ev,
3042
struct loadparm_context *lp_ctx)
3047
/* allocate the open_handles array */
3048
open_handles = calloc(options.max_open_handles, sizeof(open_handles[0]));
3050
srandom(options.seed);
3051
op_parms = calloc(options.numops, sizeof(op_parms[0]));
3053
/* generate the seeds - after this everything is deterministic */
3054
if (options.use_preset_seeds) {
3056
char **preset = file_lines_load(options.seeds_file, &numops, 0, NULL);
3058
printf("Failed to load %s - %s\n", options.seeds_file, strerror(errno));
3061
if (numops < options.numops) {
3062
options.numops = numops;
3064
for (op=0;op<options.numops;op++) {
3066
printf("Not enough seeds in %s\n", options.seeds_file);
3069
op_parms[op].seed = atoi(preset[op]);
3071
printf("Loaded %d seeds from %s\n", options.numops, options.seeds_file);
3073
for (op=0; op<options.numops; op++) {
3074
op_parms[op].seed = random();
3078
ret = run_test(ev, lp_ctx);
3080
if (ret != options.numops && options.analyze) {
3081
options.numops = ret+1;
3082
backtrack_analyze(ev, lp_ctx);
3083
} else if (options.analyze_always) {
3084
backtrack_analyze(ev, lp_ctx);
3085
} else if (options.analyze_continuous) {
3086
while (run_test(ev, lp_ctx) == options.numops) ;
3089
return ret == options.numops;
3093
static void usage(poptContext pc)
3097
gentest //server1/share1 //server2/share2 [options..]\n\
3099
poptPrintUsage(pc, stdout, 0);
3103
split a UNC name into server and share names
3105
static bool split_unc_name(const char *unc, char **server, char **share)
3107
char *p = strdup(unc);
3108
if (!p) return false;
3109
all_string_sub(p, "\\", "/", 0);
3110
if (strncmp(p, "//", 2) != 0) return false;
3113
p = strchr(*server, '/');
3114
if (!p) return false;
3124
/****************************************************************************
3126
****************************************************************************/
3127
int main(int argc, char *argv[])
3130
int i, username_count=0;
3132
char *ignore_file=NULL;
3133
struct tevent_context *ev;
3134
struct loadparm_context *lp_ctx;
3138
enum {OPT_UNCLIST=1000};
3139
struct poptOption long_options[] = {
3141
{"smb2", 0, POPT_ARG_NONE, &options.smb2, 0, "use SMB2 protocol", NULL},
3142
{"seed", 0, POPT_ARG_INT, &options.seed, 0, "Seed to use for randomizer", NULL},
3143
{"num-ops", 0, POPT_ARG_INT, &options.numops, 0, "num ops", NULL},
3144
{"oplocks", 0, POPT_ARG_NONE, &options.use_oplocks,0, "use oplocks", NULL},
3145
{"showall", 0, POPT_ARG_NONE, &options.showall, 0, "display all operations", NULL},
3146
{"analyse", 0, POPT_ARG_NONE, &options.analyze, 0, "do backtrack analysis", NULL},
3147
{"analysealways", 0, POPT_ARG_NONE, &options.analyze_always, 0, "analysis always", NULL},
3148
{"analysecontinuous", 0, POPT_ARG_NONE, &options.analyze_continuous, 0, "analysis continuous", NULL},
3149
{"ignore", 0, POPT_ARG_STRING, &ignore_file, 0, "ignore from file", NULL},
3150
{"preset", 0, POPT_ARG_NONE, &options.use_preset_seeds, 0, "use preset seeds", NULL},
3151
{"fast", 0, POPT_ARG_NONE, &options.fast_reconnect, 0, "use fast reconnect", NULL},
3152
{"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
3153
{"seedsfile", 0, POPT_ARG_STRING, &options.seeds_file, 0, "seed file", NULL},
3154
{ "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "[DOMAIN/]USERNAME[%PASSWORD]" },
3155
{"maskindexing", 0, POPT_ARG_NONE, &options.mask_indexing, 0, "mask out the indexed file attrib", NULL},
3156
{"noeas", 0, POPT_ARG_NONE, &options.no_eas, 0, "don't use extended attributes", NULL},
3157
{"noacls", 0, POPT_ARG_NONE, &options.no_acls, 0, "don't use ACLs", NULL},
3158
{"skip-cleanup", 0, POPT_ARG_NONE, &options.skip_cleanup, 0, "don't delete files at start", NULL},
3159
{"valid", 0, POPT_ARG_NONE, &options.valid, 0, "generate only valid fields", NULL},
3161
POPT_COMMON_CONNECTION
3162
POPT_COMMON_CREDENTIALS
3167
memset(&bad_smb2_handle, 0xFF, sizeof(bad_smb2_handle));
3170
options.seed = time(NULL);
3171
options.numops = 1000;
3172
options.max_open_handles = 20;
3173
options.seeds_file = "gentest_seeds.dat";
3175
pc = poptGetContext("gentest", argc, (const char **) argv, long_options,
3176
POPT_CONTEXT_KEEP_FIRST);
3178
poptSetOtherOptionHelp(pc, "<unc1> <unc2>");
3180
lp_ctx = cmdline_lp_ctx;
3181
servers[0].credentials = cli_credentials_init(talloc_autofree_context());
3182
servers[1].credentials = cli_credentials_init(talloc_autofree_context());
3183
cli_credentials_guess(servers[0].credentials, lp_ctx);
3184
cli_credentials_guess(servers[1].credentials, lp_ctx);
3186
while((opt = poptGetNextOpt(pc)) != -1) {
3189
lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
3192
if (username_count == 2) {
3196
cli_credentials_parse_string(servers[username_count].credentials, poptGetOptArg(pc), CRED_SPECIFIED);
3203
options.ignore_patterns = file_lines_load(ignore_file, NULL, 0, NULL);
3206
argv_new = discard_const_p(char *, poptGetArgs(pc));
3208
for (i=0; i<argc; i++) {
3209
if (argv_new[i] == NULL) {
3215
if (!(argc_new >= 3)) {
3222
setup_logging("gentest", DEBUG_STDOUT);
3224
if (argc < 3 || argv[1][0] == '-') {
3229
setup_logging(argv[0], DEBUG_STDOUT);
3231
for (i=0;i<NSERVERS;i++) {
3232
const char *share = argv[1+i];
3233
if (!split_unc_name(share, &servers[i].server_name, &servers[i].share_name)) {
3234
printf("Invalid share name '%s'\n", share);
3239
if (username_count == 0) {
3243
if (username_count == 1) {
3244
servers[1].credentials = servers[0].credentials;
3247
printf("seed=%u\n", options.seed);
3249
ev = s4_event_context_init(talloc_autofree_context());
3251
gensec_init(lp_ctx);
3253
ret = start_gentest(ev, lp_ctx);
3256
printf("gentest completed - no errors\n");
3258
printf("gentest failed\n");