~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/torture/gentest.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   generic testing tool - version with both SMB and SMB2 support
 
5
 
 
6
   Copyright (C) Andrew Tridgell 2003-2008
 
7
   
 
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.
 
12
   
 
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.
 
17
   
 
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/>.
 
20
*/
 
21
 
 
22
#include "includes.h"
 
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"
 
41
 
 
42
#define NSERVERS 2
 
43
#define NINSTANCES 2
 
44
 
 
45
/* global options */
 
46
static struct gentest_options {
 
47
        int showall;
 
48
        int analyze;
 
49
        int analyze_always;
 
50
        int analyze_continuous;
 
51
        uint_t max_open_handles;
 
52
        uint_t seed;
 
53
        uint_t numops;
 
54
        int use_oplocks;
 
55
        char **ignore_patterns;
 
56
        const char *seeds_file;
 
57
        int use_preset_seeds;
 
58
        int fast_reconnect;
 
59
        int mask_indexing;
 
60
        int no_eas;
 
61
        int no_acls;
 
62
        int skip_cleanup;
 
63
        int valid;
 
64
        int smb2;
 
65
} options;
 
66
 
 
67
/* mapping between open handles on the server and local handles */
 
68
static struct {
 
69
        bool active;
 
70
        uint_t instance;
 
71
        struct smb2_handle smb2_handle[NSERVERS]; /* SMB2 */
 
72
        uint16_t smb_handle[NSERVERS];            /* SMB */
 
73
        const char *name;
 
74
} *open_handles;
 
75
static uint_t num_open_handles;
 
76
 
 
77
/* state information for the servers. We open NINSTANCES connections to
 
78
   each server */
 
79
static struct {
 
80
        struct smb2_tree *smb2_tree[NINSTANCES];
 
81
        struct smbcli_tree *smb_tree[NINSTANCES];
 
82
        char *server_name;
 
83
        char *share_name;
 
84
        struct cli_credentials *credentials;
 
85
} servers[NSERVERS];
 
86
 
 
87
/* the seeds and flags for each operation */
 
88
static struct {
 
89
        uint_t seed;
 
90
        bool disabled;
 
91
} *op_parms;
 
92
 
 
93
 
 
94
/* oplock break info */
 
95
static struct {
 
96
        bool got_break;
 
97
        struct smb2_handle smb2_handle;
 
98
        uint16_t smb_handle;
 
99
        uint16_t handle;
 
100
        uint8_t level;
 
101
        bool do_close;
 
102
} oplocks[NSERVERS][NINSTANCES];
 
103
 
 
104
/* change notify reply info */
 
105
static struct {
 
106
        int notify_count;
 
107
        NTSTATUS status;
 
108
        union smb_notify notify;
 
109
} notifies[NSERVERS][NINSTANCES];
 
110
 
 
111
/* info relevant to the current operation */
 
112
static struct {
 
113
        const char *name;
 
114
        uint_t seed;
 
115
        NTSTATUS status;
 
116
        uint_t opnum;
 
117
        TALLOC_CTX *mem_ctx;
 
118
        const char *mismatch;
 
119
} current_op;
 
120
 
 
121
static struct smb2_handle bad_smb2_handle;
 
122
 
 
123
 
 
124
#define BAD_HANDLE 0xFFFE
 
125
 
 
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);
 
131
 
 
132
/*
 
133
  check if a string should be ignored. This is used as the basis
 
134
  for all error ignore settings
 
135
*/
 
136
static bool ignore_pattern(const char *str)
 
137
{
 
138
        int i;
 
139
        if (!options.ignore_patterns) return false;
 
140
 
 
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));
 
145
                        return true;
 
146
                }
 
147
        }
 
148
        return false;
 
149
}
 
150
 
 
151
/***************************************************** 
 
152
connect to the servers
 
153
*******************************************************/
 
154
static bool connect_servers_fast(void)
 
155
{
 
156
        int h, i;
 
157
 
 
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++) {
 
162
                        NTSTATUS status;
 
163
                        if (options.smb2) {
 
164
                                status = smb2_util_close(servers[i].smb2_tree[open_handles[h].instance],
 
165
                                                         open_handles[h].smb2_handle[i]);
 
166
                        } else {
 
167
                                status = smbcli_close(servers[i].smb_tree[open_handles[h].instance],
 
168
                                                      open_handles[h].smb_handle[i]);
 
169
                        }
 
170
                        if (NT_STATUS_IS_ERR(status)) {
 
171
                                return false;
 
172
                        }
 
173
                        open_handles[h].active = false;
 
174
                }
 
175
        }
 
176
 
 
177
        return true;
 
178
}
 
179
 
 
180
 
 
181
 
 
182
 
 
183
/***************************************************** 
 
184
connect to the servers
 
185
*******************************************************/
 
186
static bool connect_servers(struct tevent_context *ev,
 
187
                            struct loadparm_context *lp_ctx)
 
188
{
 
189
        int i, j;
 
190
 
 
191
        if (options.fast_reconnect && servers[0].smb2_tree[0]) {
 
192
                if (connect_servers_fast()) {
 
193
                        return true;
 
194
                }
 
195
        }
 
196
 
 
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;
 
204
                        }
 
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;
 
209
                        }
 
210
                }
 
211
        }
 
212
 
 
213
        for (i=0;i<NSERVERS;i++) {
 
214
                for (j=0;j<NINSTANCES;j++) {
 
215
                        NTSTATUS status;
 
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);
 
220
 
 
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);
 
224
 
 
225
                        cli_credentials_set_workstation(servers[i].credentials, 
 
226
                                                        "gentest", CRED_SPECIFIED);
 
227
 
 
228
                        if (options.smb2) {
 
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],
 
235
                                                      ev, &smb_options,
 
236
                                                          lp_socket_options(lp_ctx),
 
237
                                                          lp_gensec_settings(lp_ctx, lp_ctx)
 
238
                                                          );
 
239
                        } else {
 
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,
 
248
                                                                     &smb_options,
 
249
                                                                     &smb_session_options,
 
250
                                                                         lp_iconv_convenience(lp_ctx),
 
251
                                                                         lp_gensec_settings(lp_ctx, lp_ctx));
 
252
                        }
 
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,
 
256
                                       nt_errstr(status));
 
257
                                return false;
 
258
                        }
 
259
 
 
260
                        if (options.smb2) {
 
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);
 
265
                        } else {
 
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));
 
270
                        }
 
271
                }
 
272
        }
 
273
 
 
274
        return true;
 
275
}
 
276
 
 
277
/*
 
278
  work out the time skew between the servers - be conservative
 
279
*/
 
280
static uint_t time_skew(void)
 
281
{
 
282
        uint_t ret;
 
283
        if (options.smb2) {
 
284
                ret = labs(servers[0].smb2_tree[0]->session->transport->negotiate.system_time -
 
285
                           servers[1].smb2_tree[0]->session->transport->negotiate.system_time);
 
286
        } else {
 
287
                ret = labs(servers[0].smb_tree[0]->session->transport->negotiate.server_time -
 
288
                           servers[1].smb_tree[0]->session->transport->negotiate.server_time);
 
289
        }
 
290
        return ret + 300;
 
291
}
 
292
 
 
293
 
 
294
static bool smb2_handle_equal(const struct smb2_handle *h1, const struct smb2_handle *h2)
 
295
{
 
296
        return memcmp(h1, h2, sizeof(struct smb2_handle)) == 0;
 
297
}
 
298
 
 
299
/*
 
300
  turn a server handle into a local handle
 
301
*/
 
302
static uint_t fnum_to_handle_smb2(int server, int instance, struct smb2_handle server_handle)
 
303
{
 
304
        uint_t i;
 
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)) {
 
309
                        return i;
 
310
                }
 
311
        }
 
312
        printf("Invalid server handle in fnum_to_handle on server %d instance %d\n", 
 
313
               server, instance);
 
314
        return BAD_HANDLE;
 
315
}
 
316
 
 
317
/*
 
318
  turn a server handle into a local handle
 
319
*/
 
320
static uint_t fnum_to_handle_smb(int server, int instance, uint16_t server_handle)
 
321
{
 
322
        uint_t i;
 
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) {
 
327
                        return i;
 
328
                }
 
329
        }
 
330
        printf("Invalid server handle in fnum_to_handle on server %d instance %d\n", 
 
331
               server, instance);
 
332
        return BAD_HANDLE;
 
333
}
 
334
 
 
335
/*
 
336
  add some newly opened handles
 
337
*/
 
338
static void gen_add_handle_smb2(int instance, const char *name, struct smb2_handle handles[NSERVERS])
 
339
{
 
340
        int i, h;
 
341
        for (h=0;h<options.max_open_handles;h++) {
 
342
                if (!open_handles[h].active) break;
 
343
        }
 
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++) {
 
348
                        NTSTATUS status;
 
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",
 
353
                                       nt_errstr(status));
 
354
                        }
 
355
                }
 
356
                printf("Recovered handle %d\n", h);
 
357
                num_open_handles--;
 
358
        }
 
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;
 
364
        }
 
365
        num_open_handles++;
 
366
 
 
367
        printf("OPEN num_open_handles=%d h=%d (%s)\n", 
 
368
               num_open_handles, h, name);
 
369
}
 
370
 
 
371
/*
 
372
  add some newly opened handles
 
373
*/
 
374
static void gen_add_handle_smb(int instance, const char *name, uint16_t handles[NSERVERS])
 
375
{
 
376
        int i, h;
 
377
        for (h=0;h<options.max_open_handles;h++) {
 
378
                if (!open_handles[h].active) break;
 
379
        }
 
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++) {
 
384
                        NTSTATUS status;
 
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",
 
389
                                       nt_errstr(status));
 
390
                        }
 
391
                }
 
392
                printf("Recovered handle %d\n", h);
 
393
                num_open_handles--;
 
394
        }
 
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;
 
400
        }
 
401
        num_open_handles++;
 
402
 
 
403
        printf("OPEN num_open_handles=%d h=%d (%s)\n", 
 
404
               num_open_handles, h, name);
 
405
}
 
406
 
 
407
 
 
408
/*
 
409
  remove a closed handle
 
410
*/
 
411
static void gen_remove_handle_smb2(int instance, struct smb2_handle handles[NSERVERS])
 
412
{
 
413
        int h;
 
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;                 
 
418
                        num_open_handles--;
 
419
                        printf("CLOSE num_open_handles=%d h=%d (%s)\n", 
 
420
                               num_open_handles, h, 
 
421
                               open_handles[h].name);
 
422
                        return;
 
423
                }
 
424
        }
 
425
        printf("Removing invalid handle!?\n");
 
426
        exit(1);
 
427
}
 
428
 
 
429
/*
 
430
  remove a closed handle
 
431
*/
 
432
static void gen_remove_handle_smb(int instance, uint16_t handles[NSERVERS])
 
433
{
 
434
        int h;
 
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;                 
 
439
                        num_open_handles--;
 
440
                        printf("CLOSE num_open_handles=%d h=%d (%s)\n", 
 
441
                               num_open_handles, h, 
 
442
                               open_handles[h].name);
 
443
                        return;
 
444
                }
 
445
        }
 
446
        printf("Removing invalid handle!?\n");
 
447
        exit(1);
 
448
}
 
449
 
 
450
/*
 
451
  return true with 'chance' probability as a percentage
 
452
*/
 
453
static bool gen_chance(uint_t chance)
 
454
{
 
455
        return ((random() % 100) <= chance);
 
456
}
 
457
 
 
458
/*
 
459
  map an internal handle number to a server handle
 
460
*/
 
461
static struct smb2_handle gen_lookup_handle_smb2(int server, uint16_t handle)
 
462
{
 
463
        if (handle == BAD_HANDLE) return bad_smb2_handle;
 
464
        return open_handles[handle].smb2_handle[server];
 
465
}
 
466
 
 
467
/*
 
468
  map an internal handle number to a server handle
 
469
*/
 
470
static uint16_t gen_lookup_handle_smb(int server, uint16_t handle)
 
471
{
 
472
        if (handle == BAD_HANDLE) return BAD_HANDLE;
 
473
        return open_handles[handle].smb_handle[server];
 
474
}
 
475
 
 
476
/*
 
477
  return a file handle
 
478
*/
 
479
static uint16_t gen_fnum(int instance)
 
480
{
 
481
        uint16_t h;
 
482
        int count = 0;
 
483
 
 
484
        if (gen_chance(20)) return BAD_HANDLE;
 
485
 
 
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) {
 
490
                        return h;
 
491
                }
 
492
        }
 
493
        return BAD_HANDLE;
 
494
}
 
495
 
 
496
/*
 
497
  return a file handle, but skewed so we don't close the last
 
498
  couple of handles too readily
 
499
*/
 
500
static uint16_t gen_fnum_close(int instance)
 
501
{
 
502
        if (num_open_handles < 5) {
 
503
                if (gen_chance(90)) return BAD_HANDLE;
 
504
        }
 
505
 
 
506
        return gen_fnum(instance);
 
507
}
 
508
 
 
509
/*
 
510
  generate an integer in a specified range
 
511
*/
 
512
static int gen_int_range(uint64_t min, uint64_t max)
 
513
{
 
514
        uint_t r = random();
 
515
        return min + (r % (1+max-min));
 
516
}
 
517
 
 
518
/*
 
519
  return a fnum for use as a root fid
 
520
  be careful to call GEN_SET_FNUM() when you use this!
 
521
*/
 
522
static uint16_t gen_root_fid(int instance)
 
523
{
 
524
        if (gen_chance(5)) return gen_fnum(instance);
 
525
        return 0;
 
526
}
 
527
 
 
528
/*
 
529
  generate a file offset
 
530
*/
 
531
static int gen_offset(void)
 
532
{
 
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);
 
536
}
 
537
 
 
538
/*
 
539
  generate a io count
 
540
*/
 
541
static int gen_io_count(void)
 
542
{
 
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);
 
546
}
 
547
 
 
548
/*
 
549
  generate a filename
 
550
*/
 
551
static const char *gen_fname(void)
 
552
{
 
553
        const char *names[] = {"gentest\\gentest.dat", 
 
554
                               "gentest\\foo", 
 
555
                               "gentest\\foo2.sym", 
 
556
                               "gentest\\foo3.dll", 
 
557
                               "gentest\\foo4", 
 
558
                               "gentest\\foo4:teststream1", 
 
559
                               "gentest\\foo4:teststream2", 
 
560
                               "gentest\\foo5.exe", 
 
561
                               "gentest\\foo5.exe:teststream3", 
 
562
                               "gentest\\foo5.exe:teststream4", 
 
563
                               "gentest\\foo6.com", 
 
564
                               "gentest\\blah", 
 
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", 
 
571
                               "gentest\\blah\\.", 
 
572
                               "gentest\\blah\\..", 
 
573
                               "gentest\\a_very_long_name.bin", 
 
574
                               "gentest\\x.y", 
 
575
                               "gentest\\blah"};
 
576
        int i;
 
577
 
 
578
        do {
 
579
                i = gen_int_range(0, ARRAY_SIZE(names)-1);
 
580
        } while (ignore_pattern(names[i]));
 
581
 
 
582
        return names[i];
 
583
}
 
584
 
 
585
/*
 
586
  generate a filename with a higher chance of choosing an already 
 
587
  open file
 
588
*/
 
589
static const char *gen_fname_open(int instance)
 
590
{
 
591
        uint16_t h;
 
592
        h = gen_fnum(instance);
 
593
        if (h == BAD_HANDLE) {
 
594
                return gen_fname();
 
595
        }
 
596
        return open_handles[h].name;
 
597
}
 
598
 
 
599
/*
 
600
  generate a wildcard pattern
 
601
*/
 
602
static const char *gen_pattern(void)
 
603
{
 
604
        int i;
 
605
        const char *names[] = {"gentest\\*.dat", 
 
606
                               "gentest\\*", 
 
607
                               "gentest\\*.*", 
 
608
                               "gentest\\blah\\*.*", 
 
609
                               "gentest\\blah\\*", 
 
610
                               "gentest\\?"};
 
611
 
 
612
        if (gen_chance(50)) return gen_fname();
 
613
 
 
614
        do {
 
615
                i = gen_int_range(0, ARRAY_SIZE(names)-1);
 
616
        } while (ignore_pattern(names[i]));
 
617
 
 
618
        return names[i];
 
619
}
 
620
 
 
621
static uint32_t gen_bits_levels(int nlevels, ...)
 
622
{
 
623
        va_list ap;
 
624
        uint32_t pct;
 
625
        uint32_t mask;
 
626
        int i;
 
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)) {
 
632
                        va_end(ap);
 
633
                        return mask & random();
 
634
                }
 
635
        }
 
636
        va_end(ap);
 
637
        return 0;
 
638
}
 
639
 
 
640
/*
 
641
  generate a bitmask
 
642
*/
 
643
static uint32_t gen_bits_mask(uint_t mask)
 
644
{
 
645
        uint_t ret = random();
 
646
        return ret & mask;
 
647
}
 
648
 
 
649
/*
 
650
  generate a bitmask with high probability of the first mask
 
651
  and low of the second
 
652
*/
 
653
static uint32_t gen_bits_mask2(uint32_t mask1, uint32_t mask2)
 
654
{
 
655
        if (!options.valid && gen_chance(10)) return gen_bits_mask(mask2);
 
656
        return gen_bits_mask(mask1);
 
657
}
 
658
 
 
659
/*
 
660
  generate reserved values
 
661
 */
 
662
static uint64_t gen_reserved8(void)
 
663
{
 
664
        if (options.valid) return 0;
 
665
        return gen_bits_mask(0xFF);
 
666
}
 
667
 
 
668
static uint64_t gen_reserved16(void)
 
669
{
 
670
        if (options.valid) return 0;
 
671
        return gen_bits_mask(0xFFFF);
 
672
}
 
673
 
 
674
static uint64_t gen_reserved32(void)
 
675
{
 
676
        if (options.valid) return 0;
 
677
        return gen_bits_mask(0xFFFFFFFF);
 
678
}
 
679
 
 
680
static uint64_t gen_reserved64(void)
 
681
{
 
682
        if (options.valid) return 0;
 
683
        return gen_bits_mask(0xFFFFFFFF) | (((uint64_t)gen_bits_mask(0xFFFFFFFF))<<32);
 
684
}
 
685
 
 
686
 
 
687
 
 
688
/*
 
689
  generate a boolean
 
690
*/
 
691
static bool gen_bool(void)
 
692
{
 
693
        return gen_bits_mask2(0x1, 0xFF);
 
694
}
 
695
 
 
696
/*
 
697
  generate ntrename flags
 
698
*/
 
699
static uint16_t gen_rename_flags(void)
 
700
{
 
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);
 
705
}
 
706
 
 
707
/*
 
708
  generate a pid 
 
709
*/
 
710
static uint16_t gen_pid(void)
 
711
{
 
712
        if (gen_chance(10)) return gen_bits_mask(0xFFFF);
 
713
        return getpid();
 
714
}
 
715
 
 
716
/*
 
717
  return a set of lock flags
 
718
*/
 
719
static uint16_t gen_lock_flags_smb2(void)
 
720
{
 
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);
 
727
}
 
728
 
 
729
/*
 
730
  generate a lock count
 
731
*/
 
732
static off_t gen_lock_count(void)
 
733
{
 
734
        return gen_int_range(0, 3);
 
735
}
 
736
 
 
737
/*
 
738
  generate a NT access mask
 
739
*/
 
740
static uint32_t gen_access_mask(void)
 
741
{
 
742
        uint32_t ret;
 
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;
 
747
        return ret;
 
748
}
 
749
 
 
750
/*
 
751
  return a lockingx lock mode
 
752
*/
 
753
static uint16_t gen_lock_mode(void)
 
754
{
 
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);
 
758
}
 
759
 
 
760
/*
 
761
  generate a ntcreatex flags field
 
762
*/
 
763
static uint32_t gen_ntcreatex_flags(void)
 
764
{
 
765
        if (gen_chance(70)) return NTCREATEX_FLAGS_EXTENDED;
 
766
        return gen_bits_mask2(0x1F, 0xFFFFFFFF);
 
767
}
 
768
 
 
769
/*
 
770
  generate a ntcreatex create options bitfield
 
771
*/
 
772
static uint32_t gen_create_options(void)
 
773
{
 
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);
 
777
}
 
778
 
 
779
/*
 
780
  generate a ntcreatex open disposition
 
781
*/
 
782
static uint32_t gen_open_disp(void)
 
783
{
 
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);
 
787
}
 
788
 
 
789
/*
 
790
  generate an openx open mode
 
791
*/
 
792
static uint16_t gen_openx_mode(void)
 
793
{
 
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);
 
797
}
 
798
 
 
799
/*
 
800
  generate an openx flags field
 
801
*/
 
802
static uint16_t gen_openx_flags(void)
 
803
{
 
804
        if (!options.valid && gen_chance(20)) return gen_bits_mask(0xFFFF);
 
805
        return gen_bits_mask(0x7);
 
806
}
 
807
 
 
808
/*
 
809
  generate an openx open function
 
810
*/
 
811
static uint16_t gen_openx_func(void)
 
812
{
 
813
        if (!options.valid && gen_chance(20)) return gen_bits_mask(0xFFFF);
 
814
        return gen_bits_mask(0x13);
 
815
}
 
816
 
 
817
/*
 
818
  generate a file attrib combination
 
819
*/
 
820
static uint32_t gen_attrib(void)
 
821
{
 
822
        uint32_t ret;
 
823
        if (gen_chance(20)) {
 
824
                ret = gen_bits_mask(0xFFFFFFFF);
 
825
                if (options.valid) ret &= FILE_ATTRIBUTE_ALL_MASK;
 
826
                return ret;
 
827
        }
 
828
        return gen_bits_mask(FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY);
 
829
}
 
830
 
 
831
/*
 
832
  generate a unix timestamp
 
833
*/
 
834
static time_t gen_timet(void)
 
835
{
 
836
        if (gen_chance(30)) return 0;
 
837
        return (time_t)random();
 
838
}
 
839
 
 
840
/*
 
841
  generate a milliseconds protocol timeout
 
842
*/
 
843
static uint32_t gen_timeout(void)
 
844
{
 
845
        if (gen_chance(98)) return 0;
 
846
        return random() % 50;
 
847
}
 
848
 
 
849
/*
 
850
  generate a timestamp
 
851
*/
 
852
static NTTIME gen_nttime(void)
 
853
{
 
854
        NTTIME ret;
 
855
        unix_to_nt_time(&ret, gen_timet());
 
856
        return ret;
 
857
}
 
858
 
 
859
/*
 
860
  generate a timewarp value
 
861
*/
 
862
static NTTIME gen_timewarp(void)
 
863
{
 
864
        NTTIME ret = gen_nttime();
 
865
        if (gen_chance(98)) ret = 0;
 
866
        return ret;
 
867
}
 
868
 
 
869
/*
 
870
  generate a file allocation size
 
871
*/
 
872
static uint_t gen_alloc_size(void)
 
873
{
 
874
        uint_t ret;
 
875
 
 
876
        if (gen_chance(30)) return 0;
 
877
 
 
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);
 
882
        }
 
883
        return ret;
 
884
}
 
885
 
 
886
/*
 
887
  generate an ea_struct
 
888
*/
 
889
static struct ea_struct gen_ea_struct(void)
 
890
{
 
891
        struct ea_struct ea;
 
892
        const char *names[] = {"EAONE", 
 
893
                               "", 
 
894
                               "FOO!", 
 
895
                               " WITH SPACES ", 
 
896
                               ".", 
 
897
                               "AVERYLONGATTRIBUTENAME"};
 
898
        const char *values[] = {"VALUE1", 
 
899
                               "", 
 
900
                               "NOT MUCH FOO", 
 
901
                               " LEADING SPACES ", 
 
902
                               ":", 
 
903
                               "ASOMEWHATLONGERATTRIBUTEVALUE"};
 
904
        int i;
 
905
 
 
906
        ZERO_STRUCT(ea);
 
907
 
 
908
        do {
 
909
                i = gen_int_range(0, ARRAY_SIZE(names)-1);
 
910
        } while (ignore_pattern(names[i]));
 
911
 
 
912
        ea.name.s = names[i];
 
913
 
 
914
        do {
 
915
                i = gen_int_range(0, ARRAY_SIZE(values)-1);
 
916
        } while (ignore_pattern(values[i]));
 
917
 
 
918
        ea.value = data_blob(values[i], strlen(values[i]));
 
919
 
 
920
        if (gen_chance(10)) ea.flags = gen_bits_mask(0xFF);
 
921
        ea.flags = 0;
 
922
 
 
923
        return ea;
 
924
}
 
925
 
 
926
/*
 
927
  generate an ea_struct
 
928
*/
 
929
static struct smb_ea_list gen_ea_list(void)
 
930
{
 
931
        struct smb_ea_list eas;
 
932
        int i;
 
933
        if (options.no_eas) {
 
934
                ZERO_STRUCT(eas);
 
935
                return eas;
 
936
        }
 
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();
 
941
        }
 
942
        return eas;
 
943
}
 
944
 
 
945
/* generate a security descriptor */
 
946
static struct security_descriptor *gen_sec_desc(void)
 
947
{
 
948
        struct security_descriptor *sd;
 
949
        if (options.no_acls || gen_chance(90)) return NULL;
 
950
 
 
951
        sd = security_descriptor_dacl_create(current_op.mem_ctx,
 
952
                                             0, NULL, NULL,
 
953
                                             NULL,
 
954
                                             SEC_ACE_TYPE_ACCESS_ALLOWED,
 
955
                                             SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
 
956
                                             SEC_ACE_FLAG_OBJECT_INHERIT,
 
957
                                             SID_WORLD,
 
958
                                             SEC_ACE_TYPE_ACCESS_ALLOWED,
 
959
                                             SEC_FILE_ALL | SEC_STD_ALL,
 
960
                                             0,
 
961
                                             NULL);
 
962
        return sd;
 
963
}
 
964
 
 
965
 
 
966
static void oplock_handler_close_recv_smb(struct smbcli_request *req)
 
967
{
 
968
        NTSTATUS status;
 
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");
 
973
        }
 
974
}
 
975
 
 
976
/*
 
977
  the oplock handler will either ack the break or close the file
 
978
*/
 
979
static bool oplock_handler_smb(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private_data)
 
980
{
 
981
        union smb_close io;
 
982
        int i, j;
 
983
        bool do_close;
 
984
        struct smbcli_tree *tree = NULL;
 
985
        struct smbcli_request *req;
 
986
 
 
987
        srandom(current_op.seed);
 
988
        do_close = gen_chance(50);
 
989
 
 
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];
 
1000
                        }
 
1001
                }
 
1002
        }
 
1003
 
 
1004
        if (!tree) {
 
1005
                printf("Oplock break not for one of our trees!?\n");
 
1006
                return false;
 
1007
        }
 
1008
 
 
1009
        if (!do_close) {
 
1010
                printf("oplock ack fnum=%d\n", fnum);
 
1011
                return smbcli_oplock_ack(tree, fnum, level);
 
1012
        }
 
1013
 
 
1014
        printf("oplock close fnum=%d\n", fnum);
 
1015
 
 
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);
 
1020
 
 
1021
        if (req == NULL) {
 
1022
                printf("WARNING: close failed in oplock_handler_close\n");
 
1023
                return false;
 
1024
        }
 
1025
 
 
1026
        req->async.fn = oplock_handler_close_recv_smb;
 
1027
        req->async.private_data = NULL;
 
1028
 
 
1029
        return true;
 
1030
}
 
1031
 
 
1032
 
 
1033
/*
 
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
 
1037
*/
 
1038
static void idle_func_smb(struct smbcli_transport *transport, void *private_data)
 
1039
{
 
1040
        int i, j;
 
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);
 
1046
                        }
 
1047
                }
 
1048
        }
 
1049
 
 
1050
}
 
1051
 
 
1052
static void oplock_handler_close_recv_smb2(struct smb2_request *req)
 
1053
{
 
1054
        NTSTATUS status;
 
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");
 
1060
        }
 
1061
}
 
1062
 
 
1063
static void oplock_handler_ack_callback_smb2(struct smb2_request *req)
 
1064
{
 
1065
        NTSTATUS status;
 
1066
        struct smb2_break br;
 
1067
 
 
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");
 
1072
        }
 
1073
}
 
1074
 
 
1075
static bool send_oplock_ack_smb2(struct smb2_tree *tree, struct smb2_handle handle, 
 
1076
                                 uint8_t level)
 
1077
{
 
1078
        struct smb2_break br;
 
1079
        struct smb2_request *req;
 
1080
 
 
1081
        ZERO_STRUCT(br);
 
1082
        br.in.file.handle       = handle;
 
1083
        br.in.oplock_level      = level;
 
1084
        br.in.reserved          = gen_reserved8();
 
1085
        br.in.reserved2         = gen_reserved32();
 
1086
 
 
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;
 
1091
        return true;
 
1092
}
 
1093
 
 
1094
/*
 
1095
  the oplock handler will either ack the break or close the file
 
1096
*/
 
1097
static bool oplock_handler_smb2(struct smb2_transport *transport, const struct smb2_handle *handle, 
 
1098
                                uint8_t level, void *private_data)
 
1099
{
 
1100
        struct smb2_close io;
 
1101
        unsigned i, j;
 
1102
        bool do_close;
 
1103
        struct smb2_tree *tree = NULL;
 
1104
        struct smb2_request *req;
 
1105
 
 
1106
        srandom(current_op.seed);
 
1107
        do_close = gen_chance(50);
 
1108
 
 
1109
        i = ((uintptr_t)private_data) >> 8;
 
1110
        j = ((uintptr_t)private_data) & 0xFF;
 
1111
 
 
1112
        if (i >= NSERVERS || j >= NINSTANCES) {
 
1113
                printf("Bad private_data in oplock_handler\n");
 
1114
                return false;
 
1115
        }
 
1116
 
 
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);
 
1123
 
 
1124
        if (!tree) {
 
1125
                printf("Oplock break not for one of our trees!?\n");
 
1126
                return false;
 
1127
        }
 
1128
 
 
1129
        if (!do_close) {
 
1130
                printf("oplock ack handle=%d\n", oplocks[i][j].handle);
 
1131
                return send_oplock_ack_smb2(tree, *handle, level);
 
1132
        }
 
1133
 
 
1134
        printf("oplock close fnum=%d\n", oplocks[i][j].handle);
 
1135
 
 
1136
        ZERO_STRUCT(io);
 
1137
        io.in.file.handle = *handle;
 
1138
        io.in.flags = 0;
 
1139
        req = smb2_close_send(tree, &io);
 
1140
 
 
1141
        if (req == NULL) {
 
1142
                printf("WARNING: close failed in oplock_handler_close\n");
 
1143
                return false;
 
1144
        }
 
1145
 
 
1146
        req->async.fn = oplock_handler_close_recv_smb2;
 
1147
        req->async.private_data = NULL;
 
1148
 
 
1149
        return true;
 
1150
}
 
1151
 
 
1152
 
 
1153
/*
 
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
 
1157
*/
 
1158
static void idle_func_smb2(struct smb2_transport *transport, void *private_data)
 
1159
{
 
1160
        int i, j;
 
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);
 
1166
                        }
 
1167
                }
 
1168
        }
 
1169
 
 
1170
}
 
1171
 
 
1172
 
 
1173
/*
 
1174
  compare NTSTATUS, using checking ignored patterns
 
1175
*/
 
1176
static bool compare_status(NTSTATUS status1, NTSTATUS status2)
 
1177
{
 
1178
        char *s;
 
1179
 
 
1180
        if (NT_STATUS_EQUAL(status1, status2)) return true;
 
1181
 
 
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);
 
1185
                return false;
 
1186
        }
 
1187
 
 
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))) {
 
1191
                return true;
 
1192
        }
 
1193
 
 
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", 
 
1198
                            nt_errstr(status1), 
 
1199
                            nt_errstr(status2));
 
1200
        if (ignore_pattern(s)) {
 
1201
                return true;
 
1202
        }
 
1203
 
 
1204
        current_op.mismatch = nt_errstr(status1);
 
1205
        return false;
 
1206
}
 
1207
 
 
1208
/*
 
1209
  check for pending packets on all connections
 
1210
*/
 
1211
static void check_pending(void)
 
1212
{
 
1213
        int i, j;
 
1214
 
 
1215
        msleep(20);
 
1216
 
 
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);
 
1220
                }
 
1221
        }       
 
1222
}
 
1223
 
 
1224
/*
 
1225
  check that the same oplock breaks have been received by all instances
 
1226
*/
 
1227
static bool check_oplocks(const char *call)
 
1228
{
 
1229
        int i, j;
 
1230
        int tries = 0;
 
1231
 
 
1232
        if (!options.use_oplocks || options.smb2) {
 
1233
                /* no smb2 oplocks in gentest yet */
 
1234
                return true;
 
1235
        }
 
1236
 
 
1237
again:
 
1238
        check_pending();
 
1239
 
 
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";
 
1254
                                return false;
 
1255
                        }
 
1256
                }
 
1257
        }
 
1258
 
 
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;
 
1266
                        }
 
1267
                        gen_remove_handle_smb(j, fnums);
 
1268
                        break;
 
1269
                }
 
1270
        }       
 
1271
        return true;
 
1272
}
 
1273
 
 
1274
 
 
1275
/*
 
1276
  check that the same change notify info has been received by all instances
 
1277
*/
 
1278
static bool check_notifies(const char *call)
 
1279
{
 
1280
        int i, j;
 
1281
        int tries = 0;
 
1282
 
 
1283
        if (options.smb2) {
 
1284
                /* no smb2 notifies in gentest yet */
 
1285
                return true;
 
1286
        }
 
1287
 
 
1288
again:
 
1289
        check_pending();
 
1290
 
 
1291
        for (j=0;j<NINSTANCES;j++) {
 
1292
                for (i=1;i<NSERVERS;i++) {
 
1293
                        int n;
 
1294
                        union smb_notify not1, not2;
 
1295
 
 
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";
 
1302
                                return false;
 
1303
                        }
 
1304
 
 
1305
                        if (notifies[0][j].notify_count == 0) continue;
 
1306
 
 
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";
 
1313
                                return false;
 
1314
                        }
 
1315
 
 
1316
                        if (!NT_STATUS_IS_OK(notifies[0][j].status)) {
 
1317
                                continue;
 
1318
                        }
 
1319
 
 
1320
                        not1 = notifies[0][j].notify;
 
1321
                        not2 = notifies[i][j].notify;
 
1322
 
 
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";
 
1330
                                        return false;
 
1331
                                }
 
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";
 
1338
                                        return false;
 
1339
                                }
 
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";
 
1346
                                        return false;
 
1347
                                }
 
1348
                        }
 
1349
                }
 
1350
        }
 
1351
 
 
1352
        ZERO_STRUCT(notifies);
 
1353
 
 
1354
        return true;
 
1355
}
 
1356
 
 
1357
#define GEN_COPY_PARM do { \
 
1358
        int i; \
 
1359
        for (i=1;i<NSERVERS;i++) { \
 
1360
                parm[i] = parm[0]; \
 
1361
        } \
 
1362
} while (0)
 
1363
 
 
1364
#define GEN_CALL(call, treetype, treefield) do {                \
 
1365
        int i; \
 
1366
        ZERO_STRUCT(oplocks); \
 
1367
        ZERO_STRUCT(notifies); \
 
1368
        for (i=0;i<NSERVERS;i++) { \
 
1369
                struct treetype *tree = servers[i].treefield[instance]; \
 
1370
                status[i] = call; \
 
1371
        } \
 
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]); \
 
1378
                        return false; \
 
1379
                } \
 
1380
        } \
 
1381
        if (!check_oplocks(#call)) return false;        \
 
1382
        if (!check_notifies(#call)) return false;       \
 
1383
        if (!NT_STATUS_IS_OK(status[0])) { \
 
1384
                return true; \
 
1385
        } \
 
1386
} while(0)
 
1387
 
 
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)
 
1390
 
 
1391
#define ADD_HANDLE_SMB2(name, field) do { \
 
1392
        struct smb2_handle handles[NSERVERS]; \
 
1393
        int i; \
 
1394
        for (i=0;i<NSERVERS;i++) { \
 
1395
                handles[i] = parm[i].field; \
 
1396
        } \
 
1397
        gen_add_handle_smb2(instance, name, handles); \
 
1398
} while(0)
 
1399
 
 
1400
#define REMOVE_HANDLE_SMB2(field) do { \
 
1401
        struct smb2_handle handles[NSERVERS]; \
 
1402
        int i; \
 
1403
        for (i=0;i<NSERVERS;i++) { \
 
1404
                handles[i] = parm[i].field; \
 
1405
        } \
 
1406
        gen_remove_handle_smb2(instance, handles); \
 
1407
} while(0)
 
1408
 
 
1409
#define ADD_HANDLE_SMB(name, field) do { \
 
1410
        uint16_t handles[NSERVERS]; \
 
1411
        int i; \
 
1412
        for (i=0;i<NSERVERS;i++) { \
 
1413
                handles[i] = parm[i].field; \
 
1414
        } \
 
1415
        gen_add_handle_smb(instance, name, handles); \
 
1416
} while(0)
 
1417
 
 
1418
#define REMOVE_HANDLE_SMB(field) do { \
 
1419
        uint16_t handles[NSERVERS]; \
 
1420
        int i; \
 
1421
        for (i=0;i<NSERVERS;i++) { \
 
1422
                handles[i] = parm[i].field; \
 
1423
        } \
 
1424
        gen_remove_handle_smb(instance, handles); \
 
1425
} while(0)
 
1426
 
 
1427
#define GEN_SET_FNUM_SMB2(field) do { \
 
1428
        int i; \
 
1429
        for (i=0;i<NSERVERS;i++) { \
 
1430
                parm[i].field = gen_lookup_handle_smb2(i, parm[i].field.data[0]); \
 
1431
        } \
 
1432
} while(0)
 
1433
 
 
1434
#define GEN_SET_FNUM_SMB(field) do { \
 
1435
        int i; \
 
1436
        for (i=0;i<NSERVERS;i++) { \
 
1437
                parm[i].field = gen_lookup_handle_smb(i, parm[i].field); \
 
1438
        } \
 
1439
} while(0)
 
1440
 
 
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); \
 
1446
                return false; \
 
1447
        } \
 
1448
} while(0)
 
1449
 
 
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); \
 
1454
                return false;                       \
 
1455
        } \
 
1456
} while(0)
 
1457
 
 
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); \
 
1465
                return false; \
 
1466
        } \
 
1467
} while(0)
 
1468
 
 
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); \
 
1473
                return false; \
 
1474
        } \
 
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); \
 
1479
                return false; \
 
1480
        } \
 
1481
        CHECK_EQUAL(field.private_length); \
 
1482
} while(0)
 
1483
 
 
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); \
 
1490
                return false; \
 
1491
        } \
 
1492
        CHECK_EQUAL(field.length); \
 
1493
} while(0)
 
1494
 
 
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); \
 
1501
                return false; \
 
1502
        } \
 
1503
} while(0)
 
1504
 
 
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)); \
 
1513
                return false; \
 
1514
        } \
 
1515
} while(0)
 
1516
 
 
1517
 
 
1518
/*
 
1519
  compare returned fileinfo structures
 
1520
*/
 
1521
static bool cmp_fileinfo(int instance, 
 
1522
                         union smb_fileinfo parm[NSERVERS],
 
1523
                         NTSTATUS status[NSERVERS])
 
1524
{
 
1525
        int i;
 
1526
        enum smb_fileinfo_level level = parm[0].generic.level;
 
1527
 
 
1528
        if (level == RAW_FILEINFO_ALL_INFORMATION &&
 
1529
            options.smb2) {
 
1530
                level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
 
1531
        }
 
1532
 
 
1533
        switch (level) {
 
1534
        case RAW_FILEINFO_GENERIC:
 
1535
                return false;
 
1536
 
 
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);
 
1541
                break;
 
1542
 
 
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);
 
1550
                break;
 
1551
 
 
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);
 
1559
                break;
 
1560
 
 
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);
 
1569
                break;
 
1570
 
 
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);
 
1577
                }
 
1578
                break;
 
1579
 
 
1580
        case RAW_FILEINFO_IS_NAME_VALID:
 
1581
                break;
 
1582
                
 
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);
 
1590
                break;
 
1591
 
 
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);
 
1599
                break;
 
1600
 
 
1601
        case RAW_FILEINFO_EA_INFO:
 
1602
        case RAW_FILEINFO_EA_INFORMATION:
 
1603
                CHECK_EQUAL(ea_info.out.ea_size);
 
1604
                break;
 
1605
 
 
1606
        case RAW_FILEINFO_NAME_INFO:
 
1607
        case RAW_FILEINFO_NAME_INFORMATION:
 
1608
                CHECK_WSTR_EQUAL(name_info.out.fname);
 
1609
                break;
 
1610
 
 
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);
 
1625
                break;
 
1626
 
 
1627
        case RAW_FILEINFO_ALT_NAME_INFO:
 
1628
        case RAW_FILEINFO_ALT_NAME_INFORMATION:
 
1629
                CHECK_WSTR_EQUAL(alt_name_info.out.fname);
 
1630
                break;
 
1631
 
 
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);
 
1639
                }
 
1640
                break;
 
1641
 
 
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);
 
1649
                break;
 
1650
 
 
1651
        case RAW_FILEINFO_INTERNAL_INFORMATION:
 
1652
                CHECK_EQUAL(internal_information.out.file_id);
 
1653
                break;
 
1654
 
 
1655
        case RAW_FILEINFO_ACCESS_INFORMATION:
 
1656
                CHECK_EQUAL(access_information.out.access_flags);
 
1657
                break;
 
1658
 
 
1659
        case RAW_FILEINFO_POSITION_INFORMATION:
 
1660
                CHECK_EQUAL(position_information.out.position);
 
1661
                break;
 
1662
 
 
1663
        case RAW_FILEINFO_MODE_INFORMATION:
 
1664
                CHECK_EQUAL(mode_information.out.mode);
 
1665
                break;
 
1666
 
 
1667
        case RAW_FILEINFO_ALIGNMENT_INFORMATION:
 
1668
                CHECK_EQUAL(alignment_information.out.alignment_requirement);
 
1669
                break;
 
1670
 
 
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);
 
1679
                break;
 
1680
 
 
1681
        case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
 
1682
                CHECK_ATTRIB(attribute_tag_information.out.attrib);
 
1683
                CHECK_EQUAL(attribute_tag_information.out.reparse_tag);
 
1684
                break;
 
1685
 
 
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);
 
1705
                break;
 
1706
 
 
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);
 
1713
                }
 
1714
                break;
 
1715
 
 
1716
        case RAW_FILEINFO_SEC_DESC:
 
1717
                CHECK_SECDESC(query_secdesc.out.sd);
 
1718
                break;
 
1719
 
 
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:
 
1725
                break;
 
1726
        }
 
1727
 
 
1728
        return true;
 
1729
}
 
1730
 
 
1731
 
 
1732
 
 
1733
/*
 
1734
  generate openx operations
 
1735
*/
 
1736
static bool handler_smb_openx(int instance)
 
1737
{
 
1738
        union smb_open parm[NSERVERS];
 
1739
        NTSTATUS status[NSERVERS];
 
1740
 
 
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);
 
1751
 
 
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);
 
1756
        }
 
1757
        
 
1758
        GEN_COPY_PARM;
 
1759
        GEN_CALL_SMB(smb_raw_open(tree, current_op.mem_ctx, &parm[i]));
 
1760
 
 
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);
 
1770
 
 
1771
        /* open creates a new file handle */
 
1772
        ADD_HANDLE_SMB(parm[0].openx.in.fname, openx.out.file.fnum);
 
1773
 
 
1774
        return true;
 
1775
}
 
1776
 
 
1777
 
 
1778
/*
 
1779
  generate open operations
 
1780
*/
 
1781
static bool handler_smb_open(int instance)
 
1782
{
 
1783
        union smb_open parm[NSERVERS];
 
1784
        NTSTATUS status[NSERVERS];
 
1785
 
 
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);
 
1790
 
 
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);
 
1795
        }
 
1796
        
 
1797
        GEN_COPY_PARM;
 
1798
        GEN_CALL_SMB(smb_raw_open(tree, current_op.mem_ctx, &parm[i]));
 
1799
 
 
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);
 
1804
 
 
1805
        /* open creates a new file handle */
 
1806
        ADD_HANDLE_SMB(parm[0].openold.in.fname, openold.out.file.fnum);
 
1807
 
 
1808
        return true;
 
1809
}
 
1810
 
 
1811
 
 
1812
/*
 
1813
  generate ntcreatex operations
 
1814
*/
 
1815
static bool handler_smb_ntcreatex(int instance)
 
1816
{
 
1817
        union smb_open parm[NSERVERS];
 
1818
        NTSTATUS status[NSERVERS];
 
1819
 
 
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);
 
1832
 
 
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);
 
1837
        }
 
1838
        
 
1839
        GEN_COPY_PARM;
 
1840
        if (parm[0].ntcreatex.in.root_fid != 0) {
 
1841
                GEN_SET_FNUM_SMB(ntcreatex.in.root_fid);
 
1842
        }
 
1843
        GEN_CALL_SMB(smb_raw_open(tree, current_op.mem_ctx, &parm[i]));
 
1844
 
 
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);
 
1857
 
 
1858
        /* ntcreatex creates a new file handle */
 
1859
        ADD_HANDLE_SMB(parm[0].ntcreatex.in.fname, ntcreatex.out.file.fnum);
 
1860
 
 
1861
        return true;
 
1862
}
 
1863
 
 
1864
/*
 
1865
  generate close operations
 
1866
*/
 
1867
static bool handler_smb_close(int instance)
 
1868
{
 
1869
        union smb_close parm[NSERVERS];
 
1870
        NTSTATUS status[NSERVERS];
 
1871
 
 
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();
 
1875
 
 
1876
        GEN_COPY_PARM;
 
1877
        GEN_SET_FNUM_SMB(close.in.file.fnum);
 
1878
        GEN_CALL_SMB(smb_raw_close(tree, &parm[i]));
 
1879
 
 
1880
        REMOVE_HANDLE_SMB(close.in.file.fnum);
 
1881
 
 
1882
        return true;
 
1883
}
 
1884
 
 
1885
/*
 
1886
  generate unlink operations
 
1887
*/
 
1888
static bool handler_smb_unlink(int instance)
 
1889
{
 
1890
        union smb_unlink parm[NSERVERS];
 
1891
        NTSTATUS status[NSERVERS];
 
1892
 
 
1893
        parm[0].unlink.in.pattern = gen_pattern();
 
1894
        parm[0].unlink.in.attrib = gen_attrib();
 
1895
 
 
1896
        GEN_COPY_PARM;
 
1897
        GEN_CALL_SMB(smb_raw_unlink(tree, &parm[i]));
 
1898
 
 
1899
        return true;
 
1900
}
 
1901
 
 
1902
/*
 
1903
  generate chkpath operations
 
1904
*/
 
1905
static bool handler_smb_chkpath(int instance)
 
1906
{
 
1907
        union smb_chkpath parm[NSERVERS];
 
1908
        NTSTATUS status[NSERVERS];
 
1909
 
 
1910
        parm[0].chkpath.in.path = gen_fname_open(instance);
 
1911
 
 
1912
        GEN_COPY_PARM;
 
1913
        GEN_CALL_SMB(smb_raw_chkpath(tree, &parm[i]));
 
1914
 
 
1915
        return true;
 
1916
}
 
1917
 
 
1918
/*
 
1919
  generate mkdir operations
 
1920
*/
 
1921
static bool handler_smb_mkdir(int instance)
 
1922
{
 
1923
        union smb_mkdir parm[NSERVERS];
 
1924
        NTSTATUS status[NSERVERS];
 
1925
 
 
1926
        parm[0].mkdir.level = RAW_MKDIR_MKDIR;
 
1927
        parm[0].mkdir.in.path = gen_fname_open(instance);
 
1928
 
 
1929
        GEN_COPY_PARM;
 
1930
        GEN_CALL_SMB(smb_raw_mkdir(tree, &parm[i]));
 
1931
 
 
1932
        return true;
 
1933
}
 
1934
 
 
1935
/*
 
1936
  generate rmdir operations
 
1937
*/
 
1938
static bool handler_smb_rmdir(int instance)
 
1939
{
 
1940
        struct smb_rmdir parm[NSERVERS];
 
1941
        NTSTATUS status[NSERVERS];
 
1942
 
 
1943
        parm[0].in.path = gen_fname_open(instance);
 
1944
 
 
1945
        GEN_COPY_PARM;
 
1946
        GEN_CALL_SMB(smb_raw_rmdir(tree, &parm[i]));
 
1947
 
 
1948
        return true;
 
1949
}
 
1950
 
 
1951
/*
 
1952
  generate rename operations
 
1953
*/
 
1954
static bool handler_smb_rename(int instance)
 
1955
{
 
1956
        union smb_rename parm[NSERVERS];
 
1957
        NTSTATUS status[NSERVERS];
 
1958
 
 
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();
 
1963
 
 
1964
        GEN_COPY_PARM;
 
1965
        GEN_CALL_SMB(smb_raw_rename(tree, &parm[i]));
 
1966
 
 
1967
        return true;
 
1968
}
 
1969
 
 
1970
/*
 
1971
  generate ntrename operations
 
1972
*/
 
1973
static bool handler_smb_ntrename(int instance)
 
1974
{
 
1975
        union smb_rename parm[NSERVERS];
 
1976
        NTSTATUS status[NSERVERS];
 
1977
 
 
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();
 
1984
 
 
1985
        GEN_COPY_PARM;
 
1986
        GEN_CALL_SMB(smb_raw_rename(tree, &parm[i]));
 
1987
 
 
1988
        return true;
 
1989
}
 
1990
 
 
1991
 
 
1992
/*
 
1993
  generate seek operations
 
1994
*/
 
1995
static bool handler_smb_seek(int instance)
 
1996
{
 
1997
        union smb_seek parm[NSERVERS];
 
1998
        NTSTATUS status[NSERVERS];
 
1999
 
 
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();
 
2003
 
 
2004
        GEN_COPY_PARM;
 
2005
        GEN_SET_FNUM_SMB(lseek.in.file.fnum);
 
2006
        GEN_CALL_SMB(smb_raw_seek(tree, &parm[i]));
 
2007
 
 
2008
        CHECK_EQUAL(lseek.out.offset);
 
2009
 
 
2010
        return true;
 
2011
}
 
2012
 
 
2013
 
 
2014
/*
 
2015
  generate readx operations
 
2016
*/
 
2017
static bool handler_smb_readx(int instance)
 
2018
{
 
2019
        union smb_read parm[NSERVERS];
 
2020
        NTSTATUS status[NSERVERS];
 
2021
 
 
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));
 
2031
 
 
2032
        GEN_COPY_PARM;
 
2033
        GEN_SET_FNUM_SMB(readx.in.file.fnum);
 
2034
        GEN_CALL_SMB(smb_raw_read(tree, &parm[i]));
 
2035
 
 
2036
        CHECK_EQUAL(readx.out.remaining);
 
2037
        CHECK_EQUAL(readx.out.compaction_mode);
 
2038
        CHECK_EQUAL(readx.out.nread);
 
2039
 
 
2040
        return true;
 
2041
}
 
2042
 
 
2043
/*
 
2044
  generate writex operations
 
2045
*/
 
2046
static bool handler_smb_writex(int instance)
 
2047
{
 
2048
        union smb_write parm[NSERVERS];
 
2049
        NTSTATUS status[NSERVERS];
 
2050
 
 
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);
 
2058
 
 
2059
        GEN_COPY_PARM;
 
2060
        GEN_SET_FNUM_SMB(writex.in.file.fnum);
 
2061
        GEN_CALL_SMB(smb_raw_write(tree, &parm[i]));
 
2062
 
 
2063
        CHECK_EQUAL(writex.out.nwritten);
 
2064
        CHECK_EQUAL(writex.out.remaining);
 
2065
 
 
2066
        return true;
 
2067
}
 
2068
 
 
2069
/*
 
2070
  generate lockingx operations
 
2071
*/
 
2072
static bool handler_smb_lockingx(int instance)
 
2073
{
 
2074
        union smb_lock parm[NSERVERS];
 
2075
        NTSTATUS status[NSERVERS];
 
2076
        int n, nlocks;
 
2077
 
 
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();
 
2082
        do {
 
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);
 
2089
 
 
2090
        if (nlocks > 0) {
 
2091
                parm[0].lockx.in.locks = talloc_array(current_op.mem_ctx,
 
2092
                                                        struct smb_lock_entry,
 
2093
                                                        nlocks);
 
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();
 
2098
                }
 
2099
        }
 
2100
 
 
2101
        GEN_COPY_PARM;
 
2102
        GEN_SET_FNUM_SMB(lockx.in.file.fnum);
 
2103
        GEN_CALL_SMB(smb_raw_lock(tree, &parm[i]));
 
2104
 
 
2105
        return true;
 
2106
}
 
2107
 
 
2108
#if 0
 
2109
/*
 
2110
  generate a fileinfo query structure
 
2111
*/
 
2112
static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
 
2113
{
 
2114
        int i;
 
2115
        #undef LVL
 
2116
        #define LVL(v) {RAW_SFILEINFO_ ## v, "RAW_SFILEINFO_" #v}
 
2117
        struct {
 
2118
                enum smb_setfileinfo_level level;
 
2119
                const char *name;
 
2120
        }  levels[] = {
 
2121
#if 0
 
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), 
 
2125
#endif
 
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)
 
2131
        };
 
2132
        do {
 
2133
                i = gen_int_range(0, ARRAY_SIZE(levels)-1);
 
2134
        } while (ignore_pattern(levels[i].name));
 
2135
 
 
2136
        info->generic.level = levels[i].level;
 
2137
 
 
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();
 
2142
                break;
 
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();
 
2147
                break;
 
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();
 
2152
                break;
 
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();
 
2158
        }
 
2159
                break;
 
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();
 
2167
                break;
 
2168
        case RAW_SFILEINFO_DISPOSITION_INFO:
 
2169
        case RAW_SFILEINFO_DISPOSITION_INFORMATION:
 
2170
                info->disposition_info.in.delete_on_close = gen_bool();
 
2171
                break;
 
2172
        case RAW_SFILEINFO_ALLOCATION_INFO:
 
2173
        case RAW_SFILEINFO_ALLOCATION_INFORMATION:
 
2174
                info->allocation_info.in.alloc_size = gen_alloc_size();
 
2175
                break;
 
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();
 
2179
                break;
 
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);
 
2185
                break;
 
2186
        case RAW_SFILEINFO_POSITION_INFORMATION:
 
2187
                info->position_information.in.position = gen_offset();
 
2188
                break;
 
2189
        case RAW_SFILEINFO_MODE_INFORMATION:
 
2190
                info->mode_information.in.mode = gen_bits_mask(0xFFFFFFFF);
 
2191
                break;
 
2192
        case RAW_SFILEINFO_FULL_EA_INFORMATION:
 
2193
                info->full_ea_information.in.eas = gen_ea_list();
 
2194
                break;
 
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:
 
2207
                /* Untested */
 
2208
                break;
 
2209
        }
 
2210
}
 
2211
#endif
 
2212
 
 
2213
/*
 
2214
  generate a fileinfo query structure
 
2215
*/
 
2216
static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
 
2217
{
 
2218
        int i;
 
2219
        #undef LVL
 
2220
        #define LVL(v) {RAW_SFILEINFO_ ## v, "RAW_SFILEINFO_" #v}
 
2221
        struct levels {
 
2222
                enum smb_setfileinfo_level level;
 
2223
                const char *name;
 
2224
        };
 
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),
 
2235
        };
 
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),
 
2244
        };
 
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);
 
2247
 
 
2248
        do {
 
2249
                i = gen_int_range(0, num_levels-1);
 
2250
        } while (ignore_pattern(levels[i].name));
 
2251
 
 
2252
        ZERO_STRUCTP(info);
 
2253
        info->generic.level = levels[i].level;
 
2254
 
 
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();
 
2259
                break;
 
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();
 
2264
                break;
 
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();
 
2269
                break;
 
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();
 
2275
                break;
 
2276
        }
 
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();
 
2284
                break;
 
2285
        case RAW_SFILEINFO_DISPOSITION_INFO:
 
2286
        case RAW_SFILEINFO_DISPOSITION_INFORMATION:
 
2287
                info->disposition_info.in.delete_on_close = gen_bool();
 
2288
                break;
 
2289
        case RAW_SFILEINFO_ALLOCATION_INFO:
 
2290
        case RAW_SFILEINFO_ALLOCATION_INFORMATION:
 
2291
                info->allocation_info.in.alloc_size = gen_alloc_size();
 
2292
                break;
 
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();
 
2296
                break;
 
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);
 
2302
                break;
 
2303
        case RAW_SFILEINFO_POSITION_INFORMATION:
 
2304
                info->position_information.in.position = gen_offset();
 
2305
                break;
 
2306
        case RAW_SFILEINFO_MODE_INFORMATION:
 
2307
                info->mode_information.in.mode = gen_bits_mask(0xFFFFFFFF);
 
2308
                break;
 
2309
        case RAW_SFILEINFO_FULL_EA_INFORMATION:
 
2310
                info->full_ea_information.in.eas = gen_ea_list();
 
2311
                break;
 
2312
 
 
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:
 
2322
                /* Untested */
 
2323
                break;
 
2324
        }
 
2325
}
 
2326
 
 
2327
 
 
2328
 
 
2329
/*
 
2330
  generate a fileinfo query structure
 
2331
*/
 
2332
static void gen_fileinfo_smb(int instance, union smb_fileinfo *info)
 
2333
{
 
2334
        int i;
 
2335
        #undef LVL
 
2336
        #define LVL(v) {RAW_FILEINFO_ ## v, "RAW_FILEINFO_" #v}
 
2337
        struct {
 
2338
                enum smb_fileinfo_level level;
 
2339
                const char *name;
 
2340
        }  levels[] = {
 
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)
 
2351
        };
 
2352
        do {
 
2353
                i = gen_int_range(0, ARRAY_SIZE(levels)-1);
 
2354
        } while (ignore_pattern(levels[i].name));
 
2355
 
 
2356
        info->generic.level = levels[i].level;
 
2357
}
 
2358
 
 
2359
/*
 
2360
  generate qpathinfo operations
 
2361
*/
 
2362
static bool handler_smb_qpathinfo(int instance)
 
2363
{
 
2364
        union smb_fileinfo parm[NSERVERS];
 
2365
        NTSTATUS status[NSERVERS];
 
2366
 
 
2367
        parm[0].generic.in.file.path = gen_fname_open(instance);
 
2368
 
 
2369
        gen_fileinfo_smb(instance, &parm[0]);
 
2370
 
 
2371
        GEN_COPY_PARM;
 
2372
        GEN_CALL_SMB(smb_raw_pathinfo(tree, current_op.mem_ctx, &parm[i]));
 
2373
 
 
2374
        return cmp_fileinfo(instance, parm, status);
 
2375
}
 
2376
 
 
2377
/*
 
2378
  generate qfileinfo operations
 
2379
*/
 
2380
static bool handler_smb_qfileinfo(int instance)
 
2381
{
 
2382
        union smb_fileinfo parm[NSERVERS];
 
2383
        NTSTATUS status[NSERVERS];
 
2384
 
 
2385
        parm[0].generic.in.file.fnum = gen_fnum(instance);
 
2386
 
 
2387
        gen_fileinfo_smb(instance, &parm[0]);
 
2388
 
 
2389
        GEN_COPY_PARM;
 
2390
        GEN_SET_FNUM_SMB(generic.in.file.fnum);
 
2391
        GEN_CALL_SMB(smb_raw_fileinfo(tree, current_op.mem_ctx, &parm[i]));
 
2392
 
 
2393
        return cmp_fileinfo(instance, parm, status);
 
2394
}
 
2395
 
 
2396
 
 
2397
/*
 
2398
  generate setpathinfo operations
 
2399
*/
 
2400
static bool handler_smb_spathinfo(int instance)
 
2401
{
 
2402
        union smb_setfileinfo parm[NSERVERS];
 
2403
        NTSTATUS status[NSERVERS];
 
2404
 
 
2405
        gen_setfileinfo(instance, &parm[0]);
 
2406
        parm[0].generic.in.file.path = gen_fname_open(instance);
 
2407
 
 
2408
        GEN_COPY_PARM;
 
2409
 
 
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);
 
2414
        }
 
2415
 
 
2416
        GEN_CALL_SMB(smb_raw_setpathinfo(tree, &parm[i]));
 
2417
 
 
2418
        return true;
 
2419
}
 
2420
 
 
2421
 
 
2422
/*
 
2423
  generate setfileinfo operations
 
2424
*/
 
2425
static bool handler_smb_sfileinfo(int instance)
 
2426
{
 
2427
        union smb_setfileinfo parm[NSERVERS];
 
2428
        NTSTATUS status[NSERVERS];
 
2429
 
 
2430
        parm[0].generic.in.file.fnum = gen_fnum(instance);
 
2431
 
 
2432
        gen_setfileinfo(instance, &parm[0]);
 
2433
 
 
2434
        GEN_COPY_PARM;
 
2435
        GEN_SET_FNUM_SMB(generic.in.file.fnum);
 
2436
        GEN_CALL_SMB(smb_raw_setfileinfo(tree, &parm[i]));
 
2437
 
 
2438
        return true;
 
2439
}
 
2440
 
 
2441
 
 
2442
/*
 
2443
  this is called when a change notify reply comes in
 
2444
*/
 
2445
static void async_notify_smb(struct smbcli_request *req)
 
2446
{
 
2447
        union smb_notify notify;
 
2448
        NTSTATUS status;
 
2449
        int i, j;
 
2450
        uint16_t tid;
 
2451
        struct smbcli_transport *transport = req->transport;
 
2452
 
 
2453
        tid = SVAL(req->in.hdr, HDR_TID);
 
2454
 
 
2455
        notify.nttrans.level = RAW_NOTIFY_NTTRANS;
 
2456
        status = smb_raw_changenotify_recv(req, current_op.mem_ctx, &notify);
 
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", 
 
2459
                       tid, 
 
2460
                       notify.nttrans.out.num_changes,
 
2461
                       notify.nttrans.out.changes[0].action,
 
2462
                       notify.nttrans.out.changes[0].name.s);
 
2463
        }
 
2464
 
 
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;
 
2472
                        }
 
2473
                }
 
2474
        }
 
2475
}
 
2476
 
 
2477
/*
 
2478
  generate change notify operations
 
2479
*/
 
2480
static bool handler_smb_notify(int instance)
 
2481
{
 
2482
        union smb_notify parm[NSERVERS];
 
2483
        int n;
 
2484
 
 
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();
 
2491
 
 
2492
        GEN_COPY_PARM;
 
2493
        GEN_SET_FNUM_SMB(nttrans.in.file.fnum);
 
2494
 
 
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;
 
2499
        }
 
2500
 
 
2501
        return true;
 
2502
}
 
2503
 
 
2504
 
 
2505
/*
 
2506
  generate ntcreatex operations
 
2507
*/
 
2508
static bool handler_smb2_create(int instance)
 
2509
{
 
2510
        struct smb2_create parm[NSERVERS];
 
2511
        NTSTATUS status[NSERVERS];
 
2512
 
 
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();
 
2532
 
 
2533
        if (!options.use_oplocks) {
 
2534
                /* mask out oplocks */
 
2535
                parm[0].in.oplock_level = 0;
 
2536
        }
 
2537
 
 
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;
 
2542
        }
 
2543
 
 
2544
        GEN_COPY_PARM;
 
2545
        GEN_CALL_SMB2(smb2_create(tree, current_op.mem_ctx, &parm[i]));
 
2546
 
 
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);
 
2559
 
 
2560
        /* ntcreatex creates a new file handle */
 
2561
        ADD_HANDLE_SMB2(parm[0].in.fname, out.file.handle);
 
2562
 
 
2563
        return true;
 
2564
}
 
2565
 
 
2566
/*
 
2567
  generate close operations
 
2568
*/
 
2569
static bool handler_smb2_close(int instance)
 
2570
{
 
2571
        struct smb2_close parm[NSERVERS];
 
2572
        NTSTATUS status[NSERVERS];
 
2573
 
 
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);
 
2577
 
 
2578
        GEN_COPY_PARM;
 
2579
        GEN_SET_FNUM_SMB2(in.file.handle);
 
2580
        GEN_CALL_SMB2(smb2_close(tree, &parm[i]));
 
2581
 
 
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);
 
2591
 
 
2592
        REMOVE_HANDLE_SMB2(in.file.handle);
 
2593
 
 
2594
        return true;
 
2595
}
 
2596
 
 
2597
/*
 
2598
  generate read operations
 
2599
*/
 
2600
static bool handler_smb2_read(int instance)
 
2601
{
 
2602
        struct smb2_read parm[NSERVERS];
 
2603
        NTSTATUS status[NSERVERS];
 
2604
 
 
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);
 
2614
 
 
2615
        GEN_COPY_PARM;
 
2616
        GEN_SET_FNUM_SMB2(in.file.handle);
 
2617
        GEN_CALL_SMB2(smb2_read(tree, current_op.mem_ctx, &parm[i]));
 
2618
 
 
2619
        CHECK_EQUAL(out.remaining);
 
2620
        CHECK_EQUAL(out.reserved);
 
2621
        CHECK_EQUAL(out.data.length);
 
2622
 
 
2623
        return true;
 
2624
}
 
2625
 
 
2626
/*
 
2627
  generate write operations
 
2628
*/
 
2629
static bool handler_smb2_write(int instance)
 
2630
{
 
2631
        struct smb2_write parm[NSERVERS];
 
2632
        NTSTATUS status[NSERVERS];
 
2633
 
 
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,
 
2639
                                            gen_io_count());
 
2640
 
 
2641
        GEN_COPY_PARM;
 
2642
        GEN_SET_FNUM_SMB2(in.file.handle);
 
2643
        GEN_CALL_SMB2(smb2_write(tree, &parm[i]));
 
2644
 
 
2645
        CHECK_EQUAL(out._pad);
 
2646
        CHECK_EQUAL(out.nwritten);
 
2647
        CHECK_EQUAL(out.unknown1);
 
2648
 
 
2649
        return true;
 
2650
}
 
2651
 
 
2652
/*
 
2653
  generate lockingx operations
 
2654
*/
 
2655
static bool handler_smb2_lock(int instance)
 
2656
{
 
2657
        struct smb2_lock parm[NSERVERS];
 
2658
        NTSTATUS status[NSERVERS];
 
2659
        int n;
 
2660
 
 
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();
 
2665
        
 
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);
 
2676
        }
 
2677
 
 
2678
        GEN_COPY_PARM;
 
2679
        GEN_SET_FNUM_SMB2(in.file.handle);
 
2680
        GEN_CALL_SMB2(smb2_lock(tree, &parm[i]));
 
2681
 
 
2682
        return true;
 
2683
}
 
2684
 
 
2685
/*
 
2686
  generate flush operations
 
2687
*/
 
2688
static bool handler_smb2_flush(int instance)
 
2689
{
 
2690
        struct smb2_flush parm[NSERVERS];
 
2691
        NTSTATUS status[NSERVERS];
 
2692
 
 
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();
 
2697
 
 
2698
        GEN_COPY_PARM;
 
2699
        GEN_SET_FNUM_SMB2(in.file.handle);
 
2700
        GEN_CALL_SMB2(smb2_flush(tree, &parm[i]));
 
2701
 
 
2702
        CHECK_EQUAL(out.reserved);
 
2703
 
 
2704
        return true;
 
2705
}
 
2706
 
 
2707
/*
 
2708
  generate echo operations
 
2709
*/
 
2710
static bool handler_smb2_echo(int instance)
 
2711
{
 
2712
        NTSTATUS status[NSERVERS];
 
2713
 
 
2714
        GEN_CALL_SMB2(smb2_keepalive(tree->session->transport));
 
2715
 
 
2716
        return true;
 
2717
}
 
2718
 
 
2719
 
 
2720
 
 
2721
/*
 
2722
  generate a fileinfo query structure
 
2723
*/
 
2724
static void gen_fileinfo_smb2(int instance, union smb_fileinfo *info)
 
2725
{
 
2726
        int i;
 
2727
        #define LVL(v) {RAW_FILEINFO_ ## v, "RAW_FILEINFO_" #v}
 
2728
        struct {
 
2729
                enum smb_fileinfo_level level;
 
2730
                const char *name;
 
2731
        }  levels[] = {
 
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),
 
2739
        };
 
2740
        do {
 
2741
                i = gen_int_range(0, ARRAY_SIZE(levels)-1);
 
2742
        } while (ignore_pattern(levels[i].name));
 
2743
 
 
2744
        info->generic.level = levels[i].level;
 
2745
}
 
2746
 
 
2747
/*
 
2748
  generate qfileinfo operations
 
2749
*/
 
2750
static bool handler_smb2_qfileinfo(int instance)
 
2751
{
 
2752
        union smb_fileinfo parm[NSERVERS];
 
2753
        NTSTATUS status[NSERVERS];
 
2754
 
 
2755
        parm[0].generic.in.file.handle.data[0] = gen_fnum(instance);
 
2756
 
 
2757
        gen_fileinfo_smb2(instance, &parm[0]);
 
2758
 
 
2759
        GEN_COPY_PARM;
 
2760
        GEN_SET_FNUM_SMB2(generic.in.file.handle);
 
2761
        GEN_CALL_SMB2(smb2_getinfo_file(tree, current_op.mem_ctx, &parm[i]));
 
2762
 
 
2763
        return cmp_fileinfo(instance, parm, status);
 
2764
}
 
2765
 
 
2766
 
 
2767
/*
 
2768
  generate setfileinfo operations
 
2769
*/
 
2770
static bool handler_smb2_sfileinfo(int instance)
 
2771
{
 
2772
        union smb_setfileinfo parm[NSERVERS];
 
2773
        NTSTATUS status[NSERVERS];
 
2774
 
 
2775
        gen_setfileinfo(instance, &parm[0]);
 
2776
        parm[0].generic.in.file.fnum = gen_fnum(instance);
 
2777
 
 
2778
        GEN_COPY_PARM;
 
2779
        GEN_SET_FNUM_SMB2(generic.in.file.handle);
 
2780
        GEN_CALL_SMB2(smb2_setinfo_file(tree, &parm[i]));
 
2781
 
 
2782
        return true;
 
2783
}
 
2784
 
 
2785
/*
 
2786
  wipe any relevant files
 
2787
*/
 
2788
static void wipe_files(void)
 
2789
{
 
2790
        int i;
 
2791
        NTSTATUS status;
 
2792
 
 
2793
        if (options.skip_cleanup) {
 
2794
                return;
 
2795
        }
 
2796
 
 
2797
        for (i=0;i<NSERVERS;i++) {
 
2798
                int n;
 
2799
                if (options.smb2) {
 
2800
                        n = smb2_deltree(servers[i].smb2_tree[0], "gentest");
 
2801
                } else {
 
2802
                        n = smbcli_deltree(servers[i].smb_tree[0], "gentest");
 
2803
                }
 
2804
                if (n == -1) {
 
2805
                        printf("Failed to wipe tree on server %d\n", i);
 
2806
                        exit(1);
 
2807
                }
 
2808
                if (options.smb2) {
 
2809
                        status = smb2_util_mkdir(servers[i].smb2_tree[0], "gentest");
 
2810
                } else {
 
2811
                        status = smbcli_mkdir(servers[i].smb_tree[0], "gentest");
 
2812
                }
 
2813
                if (NT_STATUS_IS_ERR(status)) {
 
2814
                        printf("Failed to create gentest on server %d - %s\n", i, nt_errstr(status));
 
2815
                        exit(1);
 
2816
                }
 
2817
                if (n > 0) {
 
2818
                        printf("Deleted %d files on server %d\n", n, i);
 
2819
                }
 
2820
        }
 
2821
}
 
2822
 
 
2823
/*
 
2824
  dump the current seeds - useful for continuing a backtrack
 
2825
*/
 
2826
static void dump_seeds(void)
 
2827
{
 
2828
        int i;
 
2829
        FILE *f;
 
2830
 
 
2831
        if (!options.seeds_file) {
 
2832
                return;
 
2833
        }
 
2834
        f = fopen("seeds.tmp", "w");
 
2835
        if (!f) return;
 
2836
 
 
2837
        for (i=0;i<options.numops;i++) {
 
2838
                fprintf(f, "%u\n", op_parms[i].seed);
 
2839
        }
 
2840
        fclose(f);
 
2841
        rename("seeds.tmp", options.seeds_file);
 
2842
}
 
2843
 
 
2844
 
 
2845
 
 
2846
/*
 
2847
  the list of top-level operations that we will generate
 
2848
*/
 
2849
static struct {
 
2850
        const char *name;
 
2851
        bool (*handler)(int instance);
 
2852
        bool smb2;
 
2853
        int count, success_count;
 
2854
} gen_ops[] = {
 
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},
 
2864
 
 
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},
 
2885
};
 
2886
 
 
2887
 
 
2888
/*
 
2889
  run the test with the current set of op_parms parameters
 
2890
  return the number of operations that completed successfully
 
2891
*/
 
2892
static int run_test(struct tevent_context *ev, struct loadparm_context *lp_ctx)
 
2893
{
 
2894
        int op, i;
 
2895
 
 
2896
        if (!connect_servers(ev, lp_ctx)) {
 
2897
                printf("Failed to connect to servers\n");
 
2898
                exit(1);
 
2899
        }
 
2900
 
 
2901
        dump_seeds();
 
2902
 
 
2903
        /* wipe any leftover files from old runs */
 
2904
        wipe_files();
 
2905
 
 
2906
        /* reset the open handles array */
 
2907
        memset(open_handles, 0, options.max_open_handles * sizeof(open_handles[0]));
 
2908
        num_open_handles = 0;
 
2909
 
 
2910
        for (i=0;i<ARRAY_SIZE(gen_ops);i++) {
 
2911
                gen_ops[i].count = 0;
 
2912
                gen_ops[i].success_count = 0;
 
2913
        }
 
2914
 
 
2915
        for (op=0; op<options.numops; op++) {
 
2916
                int instance, which_op;
 
2917
                bool ret;
 
2918
 
 
2919
                if (op_parms[op].disabled) continue;
 
2920
 
 
2921
                srandom(op_parms[op].seed);
 
2922
 
 
2923
                instance = gen_int_range(0, NINSTANCES-1);
 
2924
 
 
2925
                /* generate a non-ignored operation */
 
2926
                do {
 
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);
 
2930
 
 
2931
                DEBUG(3,("Generating op %s on instance %d\n",
 
2932
                         gen_ops[which_op].name, instance));
 
2933
 
 
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);
 
2940
 
 
2941
                ret = gen_ops[which_op].handler(instance);
 
2942
 
 
2943
                gen_ops[which_op].count++;
 
2944
                if (NT_STATUS_IS_OK(current_op.status)) {
 
2945
                        gen_ops[which_op].success_count++;                      
 
2946
                }
 
2947
 
 
2948
                if (!ret) {
 
2949
                        printf("Failed at operation %d - %s\n",
 
2950
                               op, gen_ops[which_op].name);
 
2951
                        return op;
 
2952
                }
 
2953
 
 
2954
                if (op % 100 == 0) {
 
2955
                        printf("%d\n", op);
 
2956
                }
 
2957
        }
 
2958
 
 
2959
        for (i=0;i<ARRAY_SIZE(gen_ops);i++) {
 
2960
                printf("Op %-10s got %d/%d success\n", 
 
2961
                       gen_ops[i].name,
 
2962
                       gen_ops[i].success_count,
 
2963
                       gen_ops[i].count);
 
2964
        }
 
2965
 
 
2966
        return op;
 
2967
}
 
2968
 
 
2969
/* 
 
2970
   perform a backtracking analysis of the minimal set of operations
 
2971
   to generate an error
 
2972
*/
 
2973
static void backtrack_analyze(struct tevent_context *ev,
 
2974
                              struct loadparm_context *lp_ctx)
 
2975
{
 
2976
        int chunk, ret;
 
2977
        const char *mismatch = current_op.mismatch;
 
2978
 
 
2979
        chunk = options.numops / 2;
 
2980
 
 
2981
        do {
 
2982
                int base;
 
2983
                for (base=0; 
 
2984
                     chunk > 0 && base+chunk < options.numops && options.numops > 1; ) {
 
2985
                        int i, max;
 
2986
 
 
2987
                        chunk = MIN(chunk, options.numops / 2);
 
2988
 
 
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;
 
2993
                        }
 
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;
 
3000
                        }
 
3001
                        if (ret == options.numops) {
 
3002
                                /* this chunk is needed */
 
3003
                                base += chunk;
 
3004
                        } else if (mismatch != current_op.mismatch &&
 
3005
                                   strcmp(mismatch, current_op.mismatch)) {
 
3006
                                base += chunk;
 
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;
 
3011
                                base = 0;
 
3012
                        } else {
 
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);
 
3017
                        }
 
3018
                }
 
3019
 
 
3020
                if (chunk == 2) {
 
3021
                        chunk = 1;
 
3022
                } else {
 
3023
                        chunk *= 0.4;
 
3024
                }
 
3025
 
 
3026
                if (options.analyze_continuous && chunk == 0 && options.numops != 1) {
 
3027
                        chunk = 1;
 
3028
                }
 
3029
        } while (chunk > 0);
 
3030
 
 
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);
 
3035
        }
 
3036
}
 
3037
 
 
3038
/* 
 
3039
   start the main gentest process
 
3040
*/
 
3041
static bool start_gentest(struct tevent_context *ev,
 
3042
                          struct loadparm_context *lp_ctx)
 
3043
{
 
3044
        int op;
 
3045
        int ret;
 
3046
 
 
3047
        /* allocate the open_handles array */
 
3048
        open_handles = calloc(options.max_open_handles, sizeof(open_handles[0]));
 
3049
 
 
3050
        srandom(options.seed);
 
3051
        op_parms = calloc(options.numops, sizeof(op_parms[0]));
 
3052
 
 
3053
        /* generate the seeds - after this everything is deterministic */
 
3054
        if (options.use_preset_seeds) {
 
3055
                int numops;
 
3056
                char **preset = file_lines_load(options.seeds_file, &numops, 0, NULL);
 
3057
                if (!preset) {
 
3058
                        printf("Failed to load %s - %s\n", options.seeds_file, strerror(errno));
 
3059
                        exit(1);
 
3060
                }
 
3061
                if (numops < options.numops) {
 
3062
                        options.numops = numops;
 
3063
                }
 
3064
                for (op=0;op<options.numops;op++) {
 
3065
                        if (!preset[op]) {
 
3066
                                printf("Not enough seeds in %s\n", options.seeds_file);
 
3067
                                exit(1);
 
3068
                        }
 
3069
                        op_parms[op].seed = atoi(preset[op]);
 
3070
                }
 
3071
                printf("Loaded %d seeds from %s\n", options.numops, options.seeds_file);
 
3072
        } else {
 
3073
                for (op=0; op<options.numops; op++) {
 
3074
                        op_parms[op].seed = random();
 
3075
                }
 
3076
        }
 
3077
 
 
3078
        ret = run_test(ev, lp_ctx);
 
3079
 
 
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) ;
 
3087
        }
 
3088
 
 
3089
        return ret == options.numops;
 
3090
}
 
3091
 
 
3092
 
 
3093
static void usage(poptContext pc)
 
3094
{
 
3095
        printf(
 
3096
"Usage:\n\
 
3097
  gentest //server1/share1 //server2/share2 [options..]\n\
 
3098
");
 
3099
        poptPrintUsage(pc, stdout, 0);
 
3100
}
 
3101
 
 
3102
/**
 
3103
  split a UNC name into server and share names
 
3104
*/
 
3105
static bool split_unc_name(const char *unc, char **server, char **share)
 
3106
{
 
3107
        char *p = strdup(unc);
 
3108
        if (!p) return false;
 
3109
        all_string_sub(p, "\\", "/", 0);
 
3110
        if (strncmp(p, "//", 2) != 0) return false;
 
3111
 
 
3112
        (*server) = p+2;
 
3113
        p = strchr(*server, '/');
 
3114
        if (!p) return false;
 
3115
 
 
3116
        *p = 0;
 
3117
        (*share) = p+1;
 
3118
        
 
3119
        return true;
 
3120
}
 
3121
 
 
3122
 
 
3123
 
 
3124
/****************************************************************************
 
3125
  main program
 
3126
****************************************************************************/
 
3127
 int main(int argc, char *argv[])
 
3128
{
 
3129
        int opt;
 
3130
        int i, username_count=0;
 
3131
        bool ret;
 
3132
        char *ignore_file=NULL;
 
3133
        struct tevent_context *ev;
 
3134
        struct loadparm_context *lp_ctx;
 
3135
        poptContext pc;
 
3136
        int argc_new;
 
3137
        char **argv_new;
 
3138
        enum {OPT_UNCLIST=1000};
 
3139
        struct poptOption long_options[] = {
 
3140
                POPT_AUTOHELP
 
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},
 
3160
                POPT_COMMON_SAMBA
 
3161
                POPT_COMMON_CONNECTION
 
3162
                POPT_COMMON_CREDENTIALS
 
3163
                POPT_COMMON_VERSION
 
3164
                { NULL }
 
3165
        };
 
3166
 
 
3167
        memset(&bad_smb2_handle, 0xFF, sizeof(bad_smb2_handle));
 
3168
 
 
3169
        setlinebuf(stdout);
 
3170
        options.seed = time(NULL);
 
3171
        options.numops = 1000;
 
3172
        options.max_open_handles = 20;
 
3173
        options.seeds_file = "gentest_seeds.dat";
 
3174
 
 
3175
        pc = poptGetContext("gentest", argc, (const char **) argv, long_options, 
 
3176
                            POPT_CONTEXT_KEEP_FIRST);
 
3177
 
 
3178
        poptSetOtherOptionHelp(pc, "<unc1> <unc2>");
 
3179
 
 
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);
 
3185
 
 
3186
        while((opt = poptGetNextOpt(pc)) != -1) {
 
3187
                switch (opt) {
 
3188
                case OPT_UNCLIST:
 
3189
                        lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
 
3190
                        break;
 
3191
                case 'U':
 
3192
                        if (username_count == 2) {
 
3193
                                usage(pc);
 
3194
                                exit(1);
 
3195
                        }
 
3196
                        cli_credentials_parse_string(servers[username_count].credentials, poptGetOptArg(pc), CRED_SPECIFIED);
 
3197
                        username_count++;
 
3198
                        break;
 
3199
                }
 
3200
        }
 
3201
 
 
3202
        if (ignore_file) {
 
3203
                options.ignore_patterns = file_lines_load(ignore_file, NULL, 0, NULL);
 
3204
        }
 
3205
 
 
3206
        argv_new = discard_const_p(char *, poptGetArgs(pc));
 
3207
        argc_new = argc;
 
3208
        for (i=0; i<argc; i++) {
 
3209
                if (argv_new[i] == NULL) {
 
3210
                        argc_new = i;
 
3211
                        break;
 
3212
                }
 
3213
        }
 
3214
 
 
3215
        if (!(argc_new >= 3)) {
 
3216
                usage(pc);
 
3217
                exit(1);
 
3218
        }
 
3219
 
 
3220
        setlinebuf(stdout);
 
3221
 
 
3222
        setup_logging("gentest", DEBUG_STDOUT);
 
3223
 
 
3224
        if (argc < 3 || argv[1][0] == '-') {
 
3225
                usage(pc);
 
3226
                exit(1);
 
3227
        }
 
3228
 
 
3229
        setup_logging(argv[0], DEBUG_STDOUT);
 
3230
 
 
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);
 
3235
                        return -1;
 
3236
                }
 
3237
        }
 
3238
 
 
3239
        if (username_count == 0) {
 
3240
                usage(pc);
 
3241
                return -1;
 
3242
        }
 
3243
        if (username_count == 1) {
 
3244
                servers[1].credentials = servers[0].credentials;
 
3245
        }
 
3246
 
 
3247
        printf("seed=%u\n", options.seed);
 
3248
 
 
3249
        ev = s4_event_context_init(talloc_autofree_context());
 
3250
 
 
3251
        gensec_init(lp_ctx);
 
3252
 
 
3253
        ret = start_gentest(ev, lp_ctx);
 
3254
 
 
3255
        if (ret) {
 
3256
                printf("gentest completed - no errors\n");
 
3257
        } else {
 
3258
                printf("gentest failed\n");
 
3259
        }
 
3260
 
 
3261
        return ret?0:-1;
 
3262
}