Line data Source code
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/util/util_file.h"
24 : #include "lib/cmdline/cmdline.h"
25 : #include "lib/events/events.h"
26 : #include "system/time.h"
27 : #include "system/filesys.h"
28 : #include "libcli/raw/request.h"
29 : #include "libcli/libcli.h"
30 : #include "libcli/raw/libcliraw.h"
31 : #include "libcli/smb2/smb2.h"
32 : #include "libcli/smb2/smb2_calls.h"
33 : #include "librpc/gen_ndr/security.h"
34 : #include "librpc/gen_ndr/ndr_security.h"
35 : #include "auth/credentials/credentials.h"
36 : #include "libcli/resolve/resolve.h"
37 : #include "auth/gensec/gensec.h"
38 : #include "param/param.h"
39 : #include "dynconfig/dynconfig.h"
40 : #include "libcli/security/security.h"
41 : #include "libcli/raw/raw_proto.h"
42 : #include "../libcli/smb/smbXcli_base.h"
43 :
44 : #define NSERVERS 2
45 : #define NINSTANCES 2
46 :
47 : /* global options */
48 : static struct gentest_options {
49 : int showall;
50 : int analyze;
51 : int analyze_always;
52 : int analyze_continuous;
53 : unsigned int max_open_handles;
54 : unsigned int seed;
55 : unsigned int numops;
56 : int use_oplocks;
57 : char **ignore_patterns;
58 : const char *seeds_file;
59 : int use_preset_seeds;
60 : int fast_reconnect;
61 : int mask_indexing;
62 : int no_eas;
63 : int no_acls;
64 : int skip_cleanup;
65 : int valid;
66 : int smb2;
67 : } options;
68 :
69 : /* mapping between open handles on the server and local handles */
70 : static struct {
71 : bool active;
72 : unsigned int instance;
73 : struct smb2_handle smb2_handle[NSERVERS]; /* SMB2 */
74 : uint16_t smb_handle[NSERVERS]; /* SMB */
75 : const char *name;
76 : } *open_handles;
77 : static unsigned int num_open_handles;
78 :
79 : /* state information for the servers. We open NINSTANCES connections to
80 : each server */
81 : static struct {
82 : struct smb2_tree *smb2_tree[NINSTANCES];
83 : struct smbcli_tree *smb_tree[NINSTANCES];
84 : char *server_name;
85 : char *share_name;
86 : struct cli_credentials *credentials;
87 : } servers[NSERVERS];
88 :
89 : /* the seeds and flags for each operation */
90 : static struct {
91 : unsigned int seed;
92 : bool disabled;
93 : } *op_parms;
94 :
95 :
96 : /* oplock break info */
97 : static struct {
98 : bool got_break;
99 : struct smb2_handle smb2_handle;
100 : uint16_t smb_handle;
101 : uint16_t handle;
102 : uint8_t level;
103 : bool do_close;
104 : } oplocks[NSERVERS][NINSTANCES];
105 :
106 : /* change notify reply info */
107 : static struct {
108 : int notify_count;
109 : NTSTATUS status;
110 : union smb_notify notify;
111 : } notifies[NSERVERS][NINSTANCES];
112 :
113 : /* info relevant to the current operation */
114 : static struct {
115 : const char *name;
116 : unsigned int seed;
117 : NTSTATUS status;
118 : unsigned int opnum;
119 : TALLOC_CTX *mem_ctx;
120 : const char *mismatch;
121 : } current_op;
122 :
123 : static struct smb2_handle bad_smb2_handle;
124 :
125 :
126 : #define BAD_HANDLE 0xFFFE
127 :
128 : static bool oplock_handler_smb2(struct smb2_transport *transport, const struct smb2_handle *handle,
129 : uint8_t level, void *private_data);
130 : static void idle_func_smb2(struct smb2_transport *transport, void *private_data);
131 : static bool oplock_handler_smb(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private_data);
132 : static void idle_func_smb(struct smbcli_transport *transport, void *private_data);
133 :
134 : /*
135 : check if a string should be ignored. This is used as the basis
136 : for all error ignore settings
137 : */
138 209 : static bool ignore_pattern(const char *str)
139 : {
140 : int i;
141 209 : if (!options.ignore_patterns) return false;
142 :
143 834 : for (i=0;options.ignore_patterns[i];i++) {
144 1251 : if (strcmp(options.ignore_patterns[i], str) == 0 ||
145 625 : gen_fnmatch(options.ignore_patterns[i], str) == 0) {
146 1 : DEBUG(2,("Ignoring '%s'\n", str));
147 1 : return true;
148 : }
149 : }
150 208 : return false;
151 : }
152 :
153 : /*****************************************************
154 : connect to the servers
155 : *******************************************************/
156 0 : static bool connect_servers_fast(void)
157 : {
158 : int h, i;
159 :
160 : /* close all open files */
161 0 : for (h=0;h<options.max_open_handles;h++) {
162 0 : if (!open_handles[h].active) continue;
163 0 : for (i=0;i<NSERVERS;i++) {
164 : NTSTATUS status;
165 0 : if (options.smb2) {
166 0 : status = smb2_util_close(servers[i].smb2_tree[open_handles[h].instance],
167 0 : open_handles[h].smb2_handle[i]);
168 : } else {
169 0 : status = smbcli_close(servers[i].smb_tree[open_handles[h].instance],
170 0 : open_handles[h].smb_handle[i]);
171 : }
172 0 : if (NT_STATUS_IS_ERR(status)) {
173 0 : return false;
174 : }
175 0 : open_handles[h].active = false;
176 : }
177 : }
178 :
179 0 : return true;
180 : }
181 :
182 :
183 :
184 :
185 : /*****************************************************
186 : connect to the servers
187 : *******************************************************/
188 1 : static bool connect_servers(struct tevent_context *ev,
189 : struct loadparm_context *lp_ctx)
190 : {
191 : int i, j;
192 :
193 1 : if (options.fast_reconnect && servers[0].smb2_tree[0]) {
194 0 : if (connect_servers_fast()) {
195 0 : return true;
196 : }
197 : }
198 :
199 : /* close any existing connections */
200 3 : for (i=0;i<NSERVERS;i++) {
201 6 : for (j=0;j<NINSTANCES;j++) {
202 4 : if (servers[i].smb2_tree[j]) {
203 0 : smb2_tdis(servers[i].smb2_tree[j]);
204 0 : talloc_free(servers[i].smb2_tree[j]);
205 0 : servers[i].smb2_tree[j] = NULL;
206 : }
207 4 : if (servers[i].smb_tree[j]) {
208 0 : smb_tree_disconnect(servers[i].smb_tree[j]);
209 0 : talloc_free(servers[i].smb_tree[j]);
210 0 : servers[i].smb_tree[j] = NULL;
211 : }
212 : }
213 : }
214 :
215 3 : for (i=0;i<NSERVERS;i++) {
216 6 : for (j=0;j<NINSTANCES;j++) {
217 : NTSTATUS status;
218 : struct smbcli_options smb_options;
219 : struct smbcli_session_options smb_session_options;
220 4 : lpcfg_smbcli_options(lp_ctx, &smb_options);
221 4 : lpcfg_smbcli_session_options(lp_ctx, &smb_session_options);
222 :
223 4 : printf("Connecting to \\\\%s\\%s as %s - instance %d\n",
224 : servers[i].server_name, servers[i].share_name,
225 : cli_credentials_get_username(servers[i].credentials),
226 : j);
227 :
228 4 : cli_credentials_set_workstation(servers[i].credentials,
229 : "gentest", CRED_SPECIFIED);
230 :
231 4 : if (options.smb2) {
232 0 : status = smb2_connect(NULL, servers[i].server_name,
233 : lpcfg_smb_ports(lp_ctx),
234 0 : servers[i].share_name,
235 : lpcfg_resolve_context(lp_ctx),
236 : servers[i].credentials,
237 : &servers[i].smb2_tree[j],
238 : ev, &smb_options,
239 : lpcfg_socket_options(lp_ctx),
240 : lpcfg_gensec_settings(lp_ctx, lp_ctx)
241 : );
242 : } else {
243 4 : status = smbcli_tree_full_connection(NULL,
244 : &servers[i].smb_tree[j],
245 4 : servers[i].server_name,
246 : lpcfg_smb_ports(lp_ctx),
247 4 : servers[i].share_name, "A:",
248 : lpcfg_socket_options(lp_ctx),
249 : servers[i].credentials,
250 : lpcfg_resolve_context(lp_ctx), ev,
251 : &smb_options,
252 : &smb_session_options,
253 : lpcfg_gensec_settings(lp_ctx, lp_ctx));
254 : }
255 4 : if (!NT_STATUS_IS_OK(status)) {
256 0 : printf("Failed to connect to \\\\%s\\%s - %s\n",
257 : servers[i].server_name, servers[i].share_name,
258 : nt_errstr(status));
259 0 : return false;
260 : }
261 :
262 4 : if (options.smb2) {
263 0 : servers[i].smb2_tree[j]->session->transport->oplock.handler = oplock_handler_smb2;
264 0 : servers[i].smb2_tree[j]->session->transport->oplock.private_data = (void *)(uintptr_t)((i<<8)|j);
265 0 : smb2_transport_idle_handler(servers[i].smb2_tree[j]->session->transport,
266 : idle_func_smb2, 50000, NULL);
267 : } else {
268 4 : smbcli_oplock_handler(servers[i].smb_tree[j]->session->transport, oplock_handler_smb,
269 4 : (void *)(uintptr_t)((i<<8)|j));
270 4 : smbcli_transport_idle_handler(servers[i].smb_tree[j]->session->transport, idle_func_smb,
271 4 : 50000, (void *)(uintptr_t)((i<<8)|j));
272 : }
273 : }
274 : }
275 :
276 1 : return true;
277 : }
278 :
279 : /*
280 : work out the time skew between the servers - be conservative
281 : */
282 16 : static unsigned int time_skew(void)
283 : {
284 : unsigned int ret;
285 : NTTIME nt0, nt1;
286 :
287 16 : if (options.smb2) {
288 : struct smbXcli_conn *c0, *c1;
289 :
290 0 : c0 = servers[0].smb2_tree[0]->session->transport->conn;
291 0 : c1 = servers[1].smb2_tree[0]->session->transport->conn;
292 :
293 0 : nt0 = smbXcli_conn_server_system_time(c0);
294 0 : nt1 = smbXcli_conn_server_system_time(c1);
295 : } else {
296 16 : nt0 = servers[0].smb_tree[0]->session->transport->negotiate.server_time;
297 16 : nt1 = servers[1].smb_tree[0]->session->transport->negotiate.server_time;
298 : }
299 : /* Samba's NTTIME is unsigned, abs() won't work! */
300 16 : if (nt0 > nt1){
301 0 : ret = nt0 - nt1;
302 : } else {
303 16 : ret = nt1 - nt0;
304 : }
305 16 : return ret + 300;
306 : }
307 :
308 :
309 0 : static bool smb2_handle_equal(const struct smb2_handle *h1, const struct smb2_handle *h2)
310 : {
311 0 : return memcmp(h1, h2, sizeof(struct smb2_handle)) == 0;
312 : }
313 :
314 : /*
315 : turn a server handle into a local handle
316 : */
317 0 : static unsigned int fnum_to_handle_smb2(int server, int instance, struct smb2_handle server_handle)
318 : {
319 : unsigned int i;
320 0 : for (i=0;i<options.max_open_handles;i++) {
321 0 : if (!open_handles[i].active ||
322 0 : instance != open_handles[i].instance) continue;
323 0 : if (smb2_handle_equal(&open_handles[i].smb2_handle[server], &server_handle)) {
324 0 : return i;
325 : }
326 : }
327 0 : printf("Invalid server handle in fnum_to_handle on server %d instance %d\n",
328 : server, instance);
329 0 : return BAD_HANDLE;
330 : }
331 :
332 : /*
333 : turn a server handle into a local handle
334 : */
335 0 : static unsigned int fnum_to_handle_smb(int server, int instance, uint16_t server_handle)
336 : {
337 : unsigned int i;
338 0 : for (i=0;i<options.max_open_handles;i++) {
339 0 : if (!open_handles[i].active ||
340 0 : instance != open_handles[i].instance) continue;
341 0 : if (open_handles[i].smb_handle[server] == server_handle) {
342 0 : return i;
343 : }
344 : }
345 0 : printf("Invalid server handle in fnum_to_handle on server %d instance %d\n",
346 : server, instance);
347 0 : return BAD_HANDLE;
348 : }
349 :
350 : /*
351 : add some newly opened handles
352 : */
353 0 : static void gen_add_handle_smb2(int instance, const char *name, struct smb2_handle handles[NSERVERS])
354 : {
355 : int i, h;
356 0 : for (h=0;h<options.max_open_handles;h++) {
357 0 : if (!open_handles[h].active) break;
358 : }
359 0 : if (h == options.max_open_handles) {
360 : /* we have to force close a random handle */
361 0 : h = random() % options.max_open_handles;
362 0 : for (i=0;i<NSERVERS;i++) {
363 : NTSTATUS status;
364 0 : status = smb2_util_close(servers[i].smb2_tree[open_handles[h].instance],
365 0 : open_handles[h].smb2_handle[i]);
366 0 : if (NT_STATUS_IS_ERR(status)) {
367 0 : printf("INTERNAL ERROR: Close failed when recovering handle! - %s\n",
368 : nt_errstr(status));
369 : }
370 : }
371 0 : printf("Recovered handle %d\n", h);
372 0 : num_open_handles--;
373 : }
374 0 : for (i=0;i<NSERVERS;i++) {
375 0 : open_handles[h].smb2_handle[i] = handles[i];
376 0 : open_handles[h].instance = instance;
377 0 : open_handles[h].active = true;
378 0 : open_handles[h].name = name;
379 : }
380 0 : num_open_handles++;
381 :
382 0 : printf("OPEN num_open_handles=%d h=%d (%s)\n",
383 : num_open_handles, h, name);
384 0 : }
385 :
386 : /*
387 : add some newly opened handles
388 : */
389 3 : static void gen_add_handle_smb(int instance, const char *name, uint16_t handles[NSERVERS])
390 : {
391 : int i, h;
392 6 : for (h=0;h<options.max_open_handles;h++) {
393 6 : if (!open_handles[h].active) break;
394 : }
395 3 : if (h == options.max_open_handles) {
396 : /* we have to force close a random handle */
397 0 : h = random() % options.max_open_handles;
398 0 : for (i=0;i<NSERVERS;i++) {
399 : NTSTATUS status;
400 0 : status = smbcli_close(servers[i].smb_tree[open_handles[h].instance],
401 0 : open_handles[h].smb_handle[i]);
402 0 : if (NT_STATUS_IS_ERR(status)) {
403 0 : printf("INTERNAL ERROR: Close failed when recovering handle! - %s\n",
404 : nt_errstr(status));
405 : }
406 : }
407 0 : printf("Recovered handle %d\n", h);
408 0 : num_open_handles--;
409 : }
410 9 : for (i=0;i<NSERVERS;i++) {
411 6 : open_handles[h].smb_handle[i] = handles[i];
412 6 : open_handles[h].instance = instance;
413 6 : open_handles[h].active = true;
414 6 : open_handles[h].name = name;
415 : }
416 3 : num_open_handles++;
417 :
418 3 : printf("OPEN num_open_handles=%d h=%d (%s)\n",
419 : num_open_handles, h, name);
420 3 : }
421 :
422 :
423 : /*
424 : remove a closed handle
425 : */
426 0 : static void gen_remove_handle_smb2(int instance, struct smb2_handle handles[NSERVERS])
427 : {
428 : int h;
429 0 : for (h=0;h<options.max_open_handles;h++) {
430 0 : if (instance == open_handles[h].instance &&
431 0 : smb2_handle_equal(&open_handles[h].smb2_handle[0], &handles[0])) {
432 0 : open_handles[h].active = false;
433 0 : num_open_handles--;
434 0 : printf("CLOSE num_open_handles=%d h=%d (%s)\n",
435 : num_open_handles, h,
436 0 : open_handles[h].name);
437 0 : return;
438 : }
439 : }
440 0 : printf("Removing invalid handle!?\n");
441 0 : exit(1);
442 : }
443 :
444 : /*
445 : remove a closed handle
446 : */
447 0 : static void gen_remove_handle_smb(int instance, uint16_t handles[NSERVERS])
448 : {
449 : int h;
450 0 : for (h=0;h<options.max_open_handles;h++) {
451 0 : if (instance == open_handles[h].instance &&
452 0 : open_handles[h].smb_handle[0] == handles[0]) {
453 0 : open_handles[h].active = false;
454 0 : num_open_handles--;
455 0 : printf("CLOSE num_open_handles=%d h=%d (%s)\n",
456 : num_open_handles, h,
457 0 : open_handles[h].name);
458 0 : return;
459 : }
460 : }
461 0 : printf("Removing invalid handle!?\n");
462 0 : exit(1);
463 : }
464 :
465 : /*
466 : return true with 'chance' probability as a percentage
467 : */
468 446 : static bool gen_chance(unsigned int chance)
469 : {
470 446 : return ((random() % 100) <= chance);
471 : }
472 :
473 : /*
474 : map an internal handle number to a server handle
475 : */
476 0 : static struct smb2_handle gen_lookup_handle_smb2(int server, uint16_t handle)
477 : {
478 0 : if (handle == BAD_HANDLE) return bad_smb2_handle;
479 0 : return open_handles[handle].smb2_handle[server];
480 : }
481 :
482 : /*
483 : map an internal handle number to a server handle
484 : */
485 98 : static uint16_t gen_lookup_handle_smb(int server, uint16_t handle)
486 : {
487 98 : if (handle == BAD_HANDLE) return BAD_HANDLE;
488 58 : return open_handles[handle].smb_handle[server];
489 : }
490 :
491 : /*
492 : return a file handle
493 : */
494 85 : static uint16_t gen_fnum(int instance)
495 : {
496 : uint16_t h;
497 85 : int count = 0;
498 :
499 85 : if (gen_chance(20)) return BAD_HANDLE;
500 :
501 1838 : while (num_open_handles > 0 && count++ < 10*options.max_open_handles) {
502 1829 : h = random() % options.max_open_handles;
503 1829 : if (open_handles[h].active &&
504 145 : open_handles[h].instance == instance) {
505 48 : return h;
506 : }
507 : }
508 9 : return BAD_HANDLE;
509 : }
510 :
511 : /*
512 : return a file handle, but skewed so we don't close the last
513 : couple of handles too readily
514 : */
515 5 : static uint16_t gen_fnum_close(int instance)
516 : {
517 5 : if (num_open_handles < 5) {
518 5 : if (gen_chance(90)) return BAD_HANDLE;
519 : }
520 :
521 0 : return gen_fnum(instance);
522 : }
523 :
524 : /*
525 : generate an integer in a specified range
526 : */
527 413 : static int gen_int_range(uint64_t min, uint64_t max)
528 : {
529 413 : unsigned int r = random();
530 413 : return min + (r % (1+max-min));
531 : }
532 :
533 : /*
534 : return a fnum for use as a root fid
535 : be careful to call GEN_SET_FNUM() when you use this!
536 : */
537 8 : static uint16_t gen_root_fid(int instance)
538 : {
539 8 : if (gen_chance(5)) return gen_fnum(instance);
540 8 : return 0;
541 : }
542 :
543 : /*
544 : generate a file offset
545 : */
546 44 : static int gen_offset(void)
547 : {
548 44 : if (gen_chance(20)) return 0;
549 : // if (gen_chance(5)) return gen_int_range(0, 0xFFFFFFFF);
550 35 : return gen_int_range(0, 1024*1024);
551 : }
552 :
553 : /*
554 : generate a io count
555 : */
556 65 : static int gen_io_count(void)
557 : {
558 65 : if (gen_chance(20)) return 0;
559 : // if (gen_chance(5)) return gen_int_range(0, 0xFFFFFFFF);
560 53 : return gen_int_range(0, 4096);
561 : }
562 :
563 : /*
564 : generate a filename
565 : */
566 32 : static const char *gen_fname(void)
567 : {
568 32 : const char *names[] = {"gentest\\gentest.dat",
569 : "gentest\\foo",
570 : "gentest\\foo2.sym",
571 : "gentest\\foo3.dll",
572 : "gentest\\foo4",
573 : "gentest\\foo4:teststream1",
574 : "gentest\\foo4:teststream2",
575 : "gentest\\foo5.exe",
576 : "gentest\\foo5.exe:teststream3",
577 : "gentest\\foo5.exe:teststream4",
578 : "gentest\\foo6.com",
579 : "gentest\\blah",
580 : "gentest\\blah\\blergh.txt",
581 : "gentest\\blah\\blergh2",
582 : "gentest\\blah\\blergh3.txt",
583 : "gentest\\blah\\blergh4",
584 : "gentest\\blah\\blergh5.txt",
585 : "gentest\\blah\\blergh5",
586 : "gentest\\blah\\.",
587 : "gentest\\blah\\..",
588 : "gentest\\a_very_long_name.bin",
589 : "gentest\\x.y",
590 : "gentest\\blah"};
591 : int i;
592 :
593 : do {
594 32 : i = gen_int_range(0, ARRAY_SIZE(names)-1);
595 32 : } while (ignore_pattern(names[i]));
596 :
597 32 : return names[i];
598 : }
599 :
600 : /*
601 : generate a filename with a higher chance of choosing an already
602 : open file
603 : */
604 41 : static const char *gen_fname_open(int instance)
605 : {
606 : uint16_t h;
607 41 : h = gen_fnum(instance);
608 41 : if (h == BAD_HANDLE) {
609 20 : return gen_fname();
610 : }
611 21 : return open_handles[h].name;
612 : }
613 :
614 : /*
615 : generate a wildcard pattern
616 : */
617 11 : static const char *gen_pattern(void)
618 : {
619 : int i;
620 11 : const char *names[] = {"gentest\\*.dat",
621 : "gentest\\*",
622 : "gentest\\*.*",
623 : "gentest\\blah\\*.*",
624 : "gentest\\blah\\*",
625 : "gentest\\?"};
626 :
627 11 : if (gen_chance(50)) return gen_fname();
628 :
629 : do {
630 7 : i = gen_int_range(0, ARRAY_SIZE(names)-1);
631 7 : } while (ignore_pattern(names[i]));
632 :
633 7 : return names[i];
634 : }
635 :
636 0 : static uint32_t gen_bits_levels(int nlevels, ...)
637 : {
638 : va_list ap;
639 : uint32_t pct;
640 : uint32_t mask;
641 : int i;
642 0 : va_start(ap, nlevels);
643 0 : for (i=0;i<nlevels;i++) {
644 0 : pct = va_arg(ap, uint32_t);
645 0 : mask = va_arg(ap, uint32_t);
646 0 : if (pct == 100 || gen_chance(pct)) {
647 0 : va_end(ap);
648 0 : return mask & random();
649 : }
650 : }
651 0 : va_end(ap);
652 0 : return 0;
653 : }
654 :
655 : /*
656 : generate a bitmask
657 : */
658 132 : static uint32_t gen_bits_mask(unsigned int mask)
659 : {
660 132 : unsigned int ret = random();
661 132 : return ret & mask;
662 : }
663 :
664 : /*
665 : generate a bitmask with high probability of the first mask
666 : and low of the second
667 : */
668 55 : static uint32_t gen_bits_mask2(uint32_t mask1, uint32_t mask2)
669 : {
670 55 : if (!options.valid && gen_chance(10)) return gen_bits_mask(mask2);
671 48 : return gen_bits_mask(mask1);
672 : }
673 :
674 : /*
675 : generate reserved values
676 : */
677 0 : static uint64_t gen_reserved8(void)
678 : {
679 0 : if (options.valid) return 0;
680 0 : return gen_bits_mask(0xFF);
681 : }
682 :
683 0 : static uint64_t gen_reserved16(void)
684 : {
685 0 : if (options.valid) return 0;
686 0 : return gen_bits_mask(0xFFFF);
687 : }
688 :
689 0 : static uint64_t gen_reserved32(void)
690 : {
691 0 : if (options.valid) return 0;
692 0 : return gen_bits_mask(0xFFFFFFFF);
693 : }
694 :
695 0 : static uint64_t gen_reserved64(void)
696 : {
697 0 : if (options.valid) return 0;
698 0 : return gen_bits_mask(0xFFFFFFFF) | (((uint64_t)gen_bits_mask(0xFFFFFFFF))<<32);
699 : }
700 :
701 :
702 :
703 : /*
704 : generate a boolean
705 : */
706 14 : static bool gen_bool(void)
707 : {
708 14 : return gen_bits_mask2(0x1, 0xFF);
709 : }
710 :
711 : /*
712 : generate ntrename flags
713 : */
714 4 : static uint16_t gen_rename_flags(void)
715 : {
716 4 : if (gen_chance(30)) return RENAME_FLAG_RENAME;
717 3 : if (gen_chance(30)) return RENAME_FLAG_HARD_LINK;
718 3 : if (gen_chance(30)) return RENAME_FLAG_COPY;
719 3 : return gen_bits_mask(0xFFFF);
720 : }
721 :
722 : /*
723 : generate a pid
724 : */
725 18 : static uint16_t gen_pid(void)
726 : {
727 18 : if (gen_chance(10)) return gen_bits_mask(0xFFFF);
728 16 : return getpid();
729 : }
730 :
731 : /*
732 : return a set of lock flags
733 : */
734 0 : static uint16_t gen_lock_flags_smb2(void)
735 : {
736 0 : if (!options.valid && gen_chance(5)) return gen_bits_mask(0xFFFF);
737 0 : if (gen_chance(20)) return gen_bits_mask(0x1F);
738 0 : if (gen_chance(50)) return SMB2_LOCK_FLAG_UNLOCK;
739 0 : return gen_bits_mask(SMB2_LOCK_FLAG_SHARED |
740 : SMB2_LOCK_FLAG_EXCLUSIVE |
741 : SMB2_LOCK_FLAG_FAIL_IMMEDIATELY);
742 : }
743 :
744 : /*
745 : generate a lock count
746 : */
747 12 : static off_t gen_lock_count(void)
748 : {
749 12 : return gen_int_range(0, 3);
750 : }
751 :
752 : /*
753 : generate a NT access mask
754 : */
755 8 : static uint32_t gen_access_mask(void)
756 : {
757 : uint32_t ret;
758 8 : if (gen_chance(70)) return SEC_FLAG_MAXIMUM_ALLOWED;
759 3 : if (gen_chance(70)) return SEC_FILE_ALL;
760 0 : ret = gen_bits_mask(0xFFFFFFFF);
761 0 : if (options.valid) ret &= ~SEC_MASK_INVALID;
762 0 : return ret;
763 : }
764 :
765 : /*
766 : return a lockingx lock mode
767 : */
768 6 : static uint16_t gen_lock_mode(void)
769 : {
770 6 : if (!options.valid && gen_chance(5)) return gen_bits_mask(0xFFFF);
771 5 : if (gen_chance(20)) return gen_bits_mask(0x1F);
772 4 : return gen_bits_mask(LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES);
773 : }
774 :
775 : /*
776 : generate a ntcreatex flags field
777 : */
778 8 : static uint32_t gen_ntcreatex_flags(void)
779 : {
780 8 : if (gen_chance(70)) return NTCREATEX_FLAGS_EXTENDED;
781 0 : return gen_bits_mask2(0x1F, 0xFFFFFFFF);
782 : }
783 :
784 : /*
785 : generate a ntcreatex create options bitfield
786 : */
787 8 : static uint32_t gen_create_options(void)
788 : {
789 8 : if (!options.valid && gen_chance(20)) return gen_bits_mask(0xFFFFFFFF);
790 6 : if (gen_chance(50)) return 0;
791 2 : return gen_bits_mask(NTCREATEX_OPTIONS_DELETE_ON_CLOSE | NTCREATEX_OPTIONS_DIRECTORY);
792 : }
793 :
794 : /*
795 : generate a ntcreatex open disposition
796 : */
797 8 : static uint32_t gen_open_disp(void)
798 : {
799 8 : if (gen_chance(50)) return NTCREATEX_DISP_OPEN_IF;
800 5 : if (!options.valid && gen_chance(10)) return gen_bits_mask(0xFFFFFFFF);
801 4 : return gen_int_range(0, 5);
802 : }
803 :
804 : /*
805 : generate an openx open mode
806 : */
807 5 : static uint16_t gen_openx_mode(void)
808 : {
809 5 : if (!options.valid && gen_chance(20)) return gen_bits_mask(0xFFFF);
810 5 : if (gen_chance(20)) return gen_bits_mask(0xFF);
811 4 : return OPENX_MODE_DENY_NONE | gen_bits_mask(0x3);
812 : }
813 :
814 : /*
815 : generate an openx flags field
816 : */
817 5 : static uint16_t gen_openx_flags(void)
818 : {
819 5 : if (!options.valid && gen_chance(20)) return gen_bits_mask(0xFFFF);
820 4 : return gen_bits_mask(0x7);
821 : }
822 :
823 : /*
824 : generate an openx open function
825 : */
826 5 : static uint16_t gen_openx_func(void)
827 : {
828 5 : if (!options.valid && gen_chance(20)) return gen_bits_mask(0xFFFF);
829 3 : return gen_bits_mask(0x13);
830 : }
831 :
832 : /*
833 : generate a file attrib combination
834 : */
835 32 : static uint32_t gen_attrib(void)
836 : {
837 : uint32_t ret;
838 32 : if (gen_chance(20)) {
839 6 : ret = gen_bits_mask(0xFFFFFFFF);
840 6 : if (options.valid) ret &= FILE_ATTRIBUTE_ALL_MASK;
841 6 : return ret;
842 : }
843 26 : return gen_bits_mask(FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY);
844 : }
845 :
846 : /*
847 : generate a unix timestamp
848 : */
849 10 : static time_t gen_timet(void)
850 : {
851 10 : if (gen_chance(30)) return 0;
852 7 : return (time_t)random();
853 : }
854 :
855 : /*
856 : generate a milliseconds protocol timeout
857 : */
858 11 : static uint32_t gen_timeout(void)
859 : {
860 11 : if (gen_chance(98)) return 0;
861 0 : return random() % 50;
862 : }
863 :
864 : /*
865 : generate a timestamp
866 : */
867 0 : static NTTIME gen_nttime(void)
868 : {
869 : NTTIME ret;
870 0 : unix_to_nt_time(&ret, gen_timet());
871 0 : return ret;
872 : }
873 :
874 : /*
875 : generate a timewarp value
876 : */
877 0 : static NTTIME gen_timewarp(void)
878 : {
879 0 : NTTIME ret = gen_nttime();
880 0 : if (gen_chance(98)) ret = 0;
881 0 : return ret;
882 : }
883 :
884 : /*
885 : generate a file allocation size
886 : */
887 10 : static unsigned int gen_alloc_size(void)
888 : {
889 : unsigned int ret;
890 :
891 10 : if (gen_chance(30)) return 0;
892 :
893 4 : ret = random() % 4*1024*1024;
894 : /* give a high chance of a round number */
895 4 : if (gen_chance(60)) {
896 3 : ret &= ~(1024*1024 - 1);
897 : }
898 4 : return ret;
899 : }
900 :
901 : /*
902 : generate an ea_struct
903 : */
904 1 : static struct ea_struct gen_ea_struct(void)
905 : {
906 : struct ea_struct ea;
907 1 : const char *names[] = {"EAONE",
908 : "",
909 : "FOO!",
910 : " WITH SPACES ",
911 : ".",
912 : "AVERYLONGATTRIBUTENAME"};
913 1 : const char *values[] = {"VALUE1",
914 : "",
915 : "NOT MUCH FOO",
916 : " LEADING SPACES ",
917 : ":",
918 : "ASOMEWHATLONGERATTRIBUTEVALUE"};
919 : int i;
920 :
921 1 : ZERO_STRUCT(ea);
922 :
923 : do {
924 1 : i = gen_int_range(0, ARRAY_SIZE(names)-1);
925 1 : } while (ignore_pattern(names[i]));
926 :
927 1 : ea.name.s = names[i];
928 :
929 : do {
930 1 : i = gen_int_range(0, ARRAY_SIZE(values)-1);
931 1 : } while (ignore_pattern(values[i]));
932 :
933 1 : ea.value = data_blob(values[i], strlen(values[i]));
934 :
935 1 : if (gen_chance(10)) ea.flags = gen_bits_mask(0xFF);
936 1 : ea.flags = 0;
937 :
938 1 : return ea;
939 : }
940 :
941 : /*
942 : generate an ea_struct
943 : */
944 1 : static struct smb_ea_list gen_ea_list(void)
945 : {
946 : struct smb_ea_list eas;
947 : int i;
948 1 : if (options.no_eas) {
949 0 : ZERO_STRUCT(eas);
950 0 : return eas;
951 : }
952 1 : eas.num_eas = gen_int_range(0, 3);
953 1 : eas.eas = talloc_array(current_op.mem_ctx, struct ea_struct, eas.num_eas);
954 1 : for (i=0;i<eas.num_eas;i++) {
955 0 : eas.eas[i] = gen_ea_struct();
956 : }
957 1 : return eas;
958 : }
959 :
960 : /* generate a security descriptor */
961 0 : static struct security_descriptor *gen_sec_desc(void)
962 : {
963 : struct security_descriptor *sd;
964 0 : if (options.no_acls || gen_chance(90)) return NULL;
965 :
966 0 : sd = security_descriptor_dacl_create(current_op.mem_ctx,
967 : 0, NULL, NULL,
968 : NULL,
969 : SEC_ACE_TYPE_ACCESS_ALLOWED,
970 : SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
971 : SEC_ACE_FLAG_OBJECT_INHERIT,
972 : SID_WORLD,
973 : SEC_ACE_TYPE_ACCESS_ALLOWED,
974 : SEC_FILE_ALL | SEC_STD_ALL,
975 : 0,
976 : NULL);
977 0 : return sd;
978 : }
979 :
980 :
981 0 : static void oplock_handler_close_recv_smb(struct smbcli_request *req)
982 : {
983 : NTSTATUS status;
984 0 : status = smbcli_request_simple_recv(req);
985 0 : if (!NT_STATUS_IS_OK(status)) {
986 0 : printf("close failed in oplock_handler\n");
987 0 : smb_panic("close failed in oplock_handler");
988 : }
989 0 : }
990 :
991 : /*
992 : the oplock handler will either ack the break or close the file
993 : */
994 0 : static bool oplock_handler_smb(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private_data)
995 : {
996 : union smb_close io;
997 : int i, j;
998 : bool do_close;
999 0 : struct smbcli_tree *tree = NULL;
1000 : struct smbcli_request *req;
1001 :
1002 0 : srandom(current_op.seed);
1003 0 : do_close = gen_chance(50);
1004 :
1005 0 : for (i=0;i<NSERVERS;i++) {
1006 0 : for (j=0;j<NINSTANCES;j++) {
1007 0 : if (transport == servers[i].smb_tree[j]->session->transport &&
1008 0 : tid == servers[i].smb_tree[j]->tid) {
1009 0 : oplocks[i][j].got_break = true;
1010 0 : oplocks[i][j].smb_handle = fnum;
1011 0 : oplocks[i][j].handle = fnum_to_handle_smb(i, j, fnum);
1012 0 : oplocks[i][j].level = level;
1013 0 : oplocks[i][j].do_close = do_close;
1014 0 : tree = servers[i].smb_tree[j];
1015 : }
1016 : }
1017 : }
1018 :
1019 0 : if (!tree) {
1020 0 : printf("Oplock break not for one of our trees!?\n");
1021 0 : return false;
1022 : }
1023 :
1024 0 : if (!do_close) {
1025 0 : printf("oplock ack fnum=%d\n", fnum);
1026 0 : return smbcli_oplock_ack(tree, fnum, level);
1027 : }
1028 :
1029 0 : printf("oplock close fnum=%d\n", fnum);
1030 :
1031 0 : io.close.level = RAW_CLOSE_CLOSE;
1032 0 : io.close.in.file.fnum = fnum;
1033 0 : io.close.in.write_time = 0;
1034 0 : req = smb_raw_close_send(tree, &io);
1035 :
1036 0 : if (req == NULL) {
1037 0 : printf("WARNING: close failed in oplock_handler_close\n");
1038 0 : return false;
1039 : }
1040 :
1041 0 : req->async.fn = oplock_handler_close_recv_smb;
1042 0 : req->async.private_data = NULL;
1043 :
1044 0 : return true;
1045 : }
1046 :
1047 :
1048 : /*
1049 : the idle function tries to cope with getting an oplock break on a connection, and
1050 : an operation on another connection blocking until that break is acked
1051 : we check for operations on all transports in the idle function
1052 : */
1053 153 : static void idle_func_smb(struct smbcli_transport *transport, void *private_data)
1054 : {
1055 : int i, j;
1056 459 : for (i=0;i<NSERVERS;i++) {
1057 918 : for (j=0;j<NINSTANCES;j++) {
1058 612 : if (servers[i].smb_tree[j] &&
1059 611 : transport != servers[i].smb_tree[j]->session->transport) {
1060 458 : smbcli_transport_process(servers[i].smb_tree[j]->session->transport);
1061 : }
1062 : }
1063 : }
1064 :
1065 153 : }
1066 :
1067 0 : static void oplock_handler_close_recv_smb2(struct smb2_request *req)
1068 : {
1069 : NTSTATUS status;
1070 : struct smb2_close io;
1071 0 : status = smb2_close_recv(req, &io);
1072 0 : if (!NT_STATUS_IS_OK(status)) {
1073 0 : printf("close failed in oplock_handler\n");
1074 0 : smb_panic("close failed in oplock_handler");
1075 : }
1076 0 : }
1077 :
1078 0 : static void oplock_handler_ack_callback_smb2(struct smb2_request *req)
1079 : {
1080 : NTSTATUS status;
1081 : struct smb2_break br;
1082 :
1083 0 : status = smb2_break_recv(req, &br);
1084 0 : if (!NT_STATUS_IS_OK(status)) {
1085 0 : printf("oplock break ack failed in oplock_handler\n");
1086 0 : smb_panic("oplock break ack failed in oplock_handler");
1087 : }
1088 0 : }
1089 :
1090 0 : static bool send_oplock_ack_smb2(struct smb2_tree *tree, struct smb2_handle handle,
1091 : uint8_t level)
1092 : {
1093 : struct smb2_break br;
1094 : struct smb2_request *req;
1095 :
1096 0 : ZERO_STRUCT(br);
1097 0 : br.in.file.handle = handle;
1098 0 : br.in.oplock_level = level;
1099 0 : br.in.reserved = gen_reserved8();
1100 0 : br.in.reserved2 = gen_reserved32();
1101 :
1102 0 : req = smb2_break_send(tree, &br);
1103 0 : if (req == NULL) return false;
1104 0 : req->async.fn = oplock_handler_ack_callback_smb2;
1105 0 : req->async.private_data = NULL;
1106 0 : return true;
1107 : }
1108 :
1109 : /*
1110 : the oplock handler will either ack the break or close the file
1111 : */
1112 0 : static bool oplock_handler_smb2(struct smb2_transport *transport, const struct smb2_handle *handle,
1113 : uint8_t level, void *private_data)
1114 : {
1115 : struct smb2_close io;
1116 : unsigned i, j;
1117 : bool do_close;
1118 0 : struct smb2_tree *tree = NULL;
1119 : struct smb2_request *req;
1120 :
1121 0 : srandom(current_op.seed);
1122 0 : do_close = gen_chance(50);
1123 :
1124 0 : i = ((uintptr_t)private_data) >> 8;
1125 0 : j = ((uintptr_t)private_data) & 0xFF;
1126 :
1127 0 : if (i >= NSERVERS || j >= NINSTANCES) {
1128 0 : printf("Bad private_data in oplock_handler\n");
1129 0 : return false;
1130 : }
1131 :
1132 0 : oplocks[i][j].got_break = true;
1133 0 : oplocks[i][j].smb2_handle = *handle;
1134 0 : oplocks[i][j].handle = fnum_to_handle_smb2(i, j, *handle);
1135 0 : oplocks[i][j].level = level;
1136 0 : oplocks[i][j].do_close = do_close;
1137 0 : tree = talloc_get_type(servers[i].smb2_tree[j], struct smb2_tree);
1138 :
1139 0 : if (!tree) {
1140 0 : printf("Oplock break not for one of our trees!?\n");
1141 0 : return false;
1142 : }
1143 :
1144 0 : if (!do_close) {
1145 0 : printf("oplock ack handle=%d\n", oplocks[i][j].handle);
1146 0 : return send_oplock_ack_smb2(tree, *handle, level);
1147 : }
1148 :
1149 0 : printf("oplock close fnum=%d\n", oplocks[i][j].handle);
1150 :
1151 0 : ZERO_STRUCT(io);
1152 0 : io.in.file.handle = *handle;
1153 0 : io.in.flags = 0;
1154 0 : req = smb2_close_send(tree, &io);
1155 :
1156 0 : if (req == NULL) {
1157 0 : printf("WARNING: close failed in oplock_handler_close\n");
1158 0 : return false;
1159 : }
1160 :
1161 0 : req->async.fn = oplock_handler_close_recv_smb2;
1162 0 : req->async.private_data = NULL;
1163 :
1164 0 : return true;
1165 : }
1166 :
1167 :
1168 : /*
1169 : the idle function tries to cope with getting an oplock break on a connection, and
1170 : an operation on another connection blocking until that break is acked
1171 : we check for operations on all transports in the idle function
1172 : */
1173 0 : static void idle_func_smb2(struct smb2_transport *transport, void *private_data)
1174 : {
1175 : int i, j;
1176 0 : for (i=0;i<NSERVERS;i++) {
1177 0 : for (j=0;j<NINSTANCES;j++) {
1178 : if (servers[i].smb2_tree[j] &&
1179 : transport != servers[i].smb2_tree[j]->session->transport) {
1180 : // smb2_transport_process(servers[i].smb2_tree[j]->session->transport);
1181 : }
1182 : }
1183 : }
1184 :
1185 0 : }
1186 :
1187 :
1188 : /*
1189 : compare NTSTATUS, using checking ignored patterns
1190 : */
1191 95 : static bool compare_status(NTSTATUS status1, NTSTATUS status2)
1192 : {
1193 : char *s;
1194 :
1195 95 : if (NT_STATUS_EQUAL(status1, status2)) return true;
1196 :
1197 : /* one code being an error and the other OK is always an error */
1198 0 : if (NT_STATUS_IS_OK(status1) || NT_STATUS_IS_OK(status2)) {
1199 0 : current_op.mismatch = nt_errstr(status1);
1200 0 : return false;
1201 : }
1202 :
1203 : /* if we are ignoring one of the status codes then consider this a match */
1204 0 : if (ignore_pattern(nt_errstr(status1)) ||
1205 0 : ignore_pattern(nt_errstr(status2))) {
1206 0 : return true;
1207 : }
1208 :
1209 : /* also support ignore patterns of the form NT_STATUS_XX:NT_STATUS_YY
1210 : meaning that the first server returns NT_STATUS_XX and the 2nd
1211 : returns NT_STATUS_YY */
1212 0 : s = talloc_asprintf(current_op.mem_ctx, "%s:%s",
1213 : nt_errstr(status1),
1214 : nt_errstr(status2));
1215 0 : if (ignore_pattern(s)) {
1216 0 : return true;
1217 : }
1218 :
1219 0 : current_op.mismatch = nt_errstr(status1);
1220 0 : return false;
1221 : }
1222 :
1223 : /*
1224 : check for pending packets on all connections
1225 : */
1226 95 : static void check_pending(void)
1227 : {
1228 : int i, j;
1229 :
1230 95 : smb_msleep(20);
1231 :
1232 285 : for (j=0;j<NINSTANCES;j++) {
1233 570 : for (i=0;i<NSERVERS;i++) {
1234 : // smb2_transport_process(servers[i].smb2_tree[j]->session->transport);
1235 : }
1236 : }
1237 95 : }
1238 :
1239 : /*
1240 : check that the same oplock breaks have been received by all instances
1241 : */
1242 95 : static bool check_oplocks(const char *call)
1243 : {
1244 : int i, j;
1245 95 : int tries = 0;
1246 :
1247 95 : if (!options.use_oplocks || options.smb2) {
1248 : /* no smb2 oplocks in gentest yet */
1249 95 : return true;
1250 : }
1251 :
1252 0 : again:
1253 0 : check_pending();
1254 :
1255 0 : for (j=0;j<NINSTANCES;j++) {
1256 0 : for (i=1;i<NSERVERS;i++) {
1257 0 : if (oplocks[0][j].got_break != oplocks[i][j].got_break ||
1258 0 : oplocks[0][j].handle != oplocks[i][j].handle ||
1259 0 : oplocks[0][j].level != oplocks[i][j].level) {
1260 0 : if (tries++ < 10) goto again;
1261 0 : printf("oplock break inconsistent - %d/%d/%d vs %d/%d/%d\n",
1262 0 : oplocks[0][j].got_break,
1263 0 : oplocks[0][j].handle,
1264 0 : oplocks[0][j].level,
1265 0 : oplocks[i][j].got_break,
1266 0 : oplocks[i][j].handle,
1267 0 : oplocks[i][j].level);
1268 0 : current_op.mismatch = "oplock break";
1269 0 : return false;
1270 : }
1271 : }
1272 : }
1273 :
1274 : /* if we got a break and closed then remove the handle */
1275 0 : for (j=0;j<NINSTANCES;j++) {
1276 0 : if (oplocks[0][j].got_break &&
1277 0 : oplocks[0][j].do_close) {
1278 : uint16_t fnums[NSERVERS];
1279 0 : for (i=0;i<NSERVERS;i++) {
1280 0 : fnums[i] = oplocks[i][j].smb_handle;
1281 : }
1282 0 : gen_remove_handle_smb(j, fnums);
1283 0 : break;
1284 : }
1285 : }
1286 0 : return true;
1287 : }
1288 :
1289 :
1290 : /*
1291 : check that the same change notify info has been received by all instances
1292 : */
1293 95 : static bool check_notifies(const char *call)
1294 : {
1295 : int i, j;
1296 95 : int tries = 0;
1297 :
1298 95 : if (options.smb2) {
1299 : /* no smb2 notifies in gentest yet */
1300 0 : return true;
1301 : }
1302 :
1303 95 : again:
1304 95 : check_pending();
1305 :
1306 285 : for (j=0;j<NINSTANCES;j++) {
1307 380 : for (i=1;i<NSERVERS;i++) {
1308 : int n;
1309 : union smb_notify not1, not2;
1310 :
1311 190 : if (notifies[0][j].notify_count != notifies[i][j].notify_count) {
1312 0 : if (tries++ < 10) goto again;
1313 0 : printf("Notify count inconsistent %d %d\n",
1314 : notifies[0][j].notify_count,
1315 : notifies[i][j].notify_count);
1316 0 : current_op.mismatch = "notify count";
1317 0 : return false;
1318 : }
1319 :
1320 195 : if (notifies[0][j].notify_count == 0) continue;
1321 :
1322 5 : if (!NT_STATUS_EQUAL(notifies[0][j].status,
1323 : notifies[i][j].status)) {
1324 0 : printf("Notify status mismatch - %s - %s\n",
1325 : nt_errstr(notifies[0][j].status),
1326 : nt_errstr(notifies[i][j].status));
1327 0 : current_op.mismatch = "Notify status";
1328 0 : return false;
1329 : }
1330 :
1331 5 : if (!NT_STATUS_IS_OK(notifies[0][j].status)) {
1332 5 : continue;
1333 : }
1334 :
1335 0 : not1 = notifies[0][j].notify;
1336 0 : not2 = notifies[i][j].notify;
1337 :
1338 0 : for (n=0;n<not1.nttrans.out.num_changes;n++) {
1339 0 : if (not1.nttrans.out.changes[n].action !=
1340 0 : not2.nttrans.out.changes[n].action) {
1341 0 : printf("Notify action %d inconsistent %d %d\n", n,
1342 0 : not1.nttrans.out.changes[n].action,
1343 0 : not2.nttrans.out.changes[n].action);
1344 0 : current_op.mismatch = "notify action";
1345 0 : return false;
1346 : }
1347 0 : if (strcmp(not1.nttrans.out.changes[n].name.s,
1348 0 : not2.nttrans.out.changes[n].name.s)) {
1349 0 : printf("Notify name %d inconsistent %s %s\n", n,
1350 0 : not1.nttrans.out.changes[n].name.s,
1351 0 : not2.nttrans.out.changes[n].name.s);
1352 0 : current_op.mismatch = "notify name";
1353 0 : return false;
1354 : }
1355 0 : if (not1.nttrans.out.changes[n].name.private_length !=
1356 0 : not2.nttrans.out.changes[n].name.private_length) {
1357 0 : printf("Notify name length %d inconsistent %d %d\n", n,
1358 0 : not1.nttrans.out.changes[n].name.private_length,
1359 0 : not2.nttrans.out.changes[n].name.private_length);
1360 0 : current_op.mismatch = "notify name length";
1361 0 : return false;
1362 : }
1363 : }
1364 : }
1365 : }
1366 :
1367 95 : ZERO_STRUCT(notifies);
1368 :
1369 95 : return true;
1370 : }
1371 :
1372 : #define GEN_COPY_PARM do { \
1373 : int i; \
1374 : for (i=1;i<NSERVERS;i++) { \
1375 : parm[i] = parm[0]; \
1376 : } \
1377 : } while (0)
1378 :
1379 : #define GEN_CALL(call, treetype, treefield) do { \
1380 : int i; \
1381 : ZERO_STRUCT(oplocks); \
1382 : ZERO_STRUCT(notifies); \
1383 : for (i=0;i<NSERVERS;i++) { \
1384 : struct treetype *tree = servers[i].treefield[instance]; \
1385 : status[i] = call; \
1386 : } \
1387 : current_op.status = status[0]; \
1388 : for (i=1;i<NSERVERS;i++) { \
1389 : if (!compare_status(status[0], status[1])) { \
1390 : printf("status different in %s - %s %s\n", #call, \
1391 : nt_errstr(status[0]), nt_errstr(status[i])); \
1392 : current_op.mismatch = nt_errstr(status[0]); \
1393 : return false; \
1394 : } \
1395 : } \
1396 : if (!check_oplocks(#call)) return false; \
1397 : if (!check_notifies(#call)) return false; \
1398 : if (!NT_STATUS_IS_OK(status[0])) { \
1399 : return true; \
1400 : } \
1401 : } while(0)
1402 :
1403 : #define GEN_CALL_SMB(call) GEN_CALL(call, smbcli_tree, smb_tree)
1404 : #define GEN_CALL_SMB2(call) GEN_CALL(call, smb2_tree, smb2_tree)
1405 :
1406 : #define ADD_HANDLE_SMB2(name, field) do { \
1407 : struct smb2_handle handles[NSERVERS]; \
1408 : int i; \
1409 : for (i=0;i<NSERVERS;i++) { \
1410 : handles[i] = parm[i].field; \
1411 : } \
1412 : gen_add_handle_smb2(instance, name, handles); \
1413 : } while(0)
1414 :
1415 : #define REMOVE_HANDLE_SMB2(field) do { \
1416 : struct smb2_handle handles[NSERVERS]; \
1417 : int i; \
1418 : for (i=0;i<NSERVERS;i++) { \
1419 : handles[i] = parm[i].field; \
1420 : } \
1421 : gen_remove_handle_smb2(instance, handles); \
1422 : } while(0)
1423 :
1424 : #define ADD_HANDLE_SMB(name, field) do { \
1425 : uint16_t handles[NSERVERS]; \
1426 : int i; \
1427 : for (i=0;i<NSERVERS;i++) { \
1428 : handles[i] = parm[i].field; \
1429 : } \
1430 : gen_add_handle_smb(instance, name, handles); \
1431 : } while(0)
1432 :
1433 : #define REMOVE_HANDLE_SMB(field) do { \
1434 : uint16_t handles[NSERVERS]; \
1435 : int i; \
1436 : for (i=0;i<NSERVERS;i++) { \
1437 : handles[i] = parm[i].field; \
1438 : } \
1439 : gen_remove_handle_smb(instance, handles); \
1440 : } while(0)
1441 :
1442 : #define GEN_SET_FNUM_SMB2(field) do { \
1443 : int i; \
1444 : for (i=0;i<NSERVERS;i++) { \
1445 : parm[i].field = gen_lookup_handle_smb2(i, parm[i].field.data[0]); \
1446 : } \
1447 : } while(0)
1448 :
1449 : #define GEN_SET_FNUM_SMB(field) do { \
1450 : int i; \
1451 : for (i=0;i<NSERVERS;i++) { \
1452 : parm[i].field = gen_lookup_handle_smb(i, parm[i].field); \
1453 : } \
1454 : } while(0)
1455 :
1456 : #define CHECK_EQUAL(field) do { \
1457 : if (parm[0].field != parm[1].field && !ignore_pattern(#field)) { \
1458 : current_op.mismatch = #field; \
1459 : printf("Mismatch in %s - 0x%llx 0x%llx\n", #field, \
1460 : (unsigned long long)parm[0].field, (unsigned long long)parm[1].field); \
1461 : return false; \
1462 : } \
1463 : } while(0)
1464 :
1465 : #define CHECK_SECDESC(field) do { \
1466 : if (!security_acl_equal(parm[0].field->dacl, parm[1].field->dacl) && !ignore_pattern(#field)) { \
1467 : current_op.mismatch = #field; \
1468 : printf("Mismatch in %s\n", #field); \
1469 : return false; \
1470 : } \
1471 : } while(0)
1472 :
1473 : #define CHECK_ATTRIB(field) do { \
1474 : if (!options.mask_indexing) { \
1475 : CHECK_EQUAL(field); \
1476 : } else if ((~FILE_ATTRIBUTE_NONINDEXED & parm[0].field) != (~FILE_ATTRIBUTE_NONINDEXED & parm[1].field) && !ignore_pattern(#field)) { \
1477 : current_op.mismatch = #field; \
1478 : printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
1479 : (int)parm[0].field, (int)parm[1].field); \
1480 : return false; \
1481 : } \
1482 : } while(0)
1483 :
1484 : #define CHECK_WSTR_EQUAL(field) do { \
1485 : if ((!parm[0].field.s && parm[1].field.s) || (parm[0].field.s && !parm[1].field.s)) { \
1486 : current_op.mismatch = #field; \
1487 : printf("%s is NULL!\n", #field); \
1488 : return false; \
1489 : } \
1490 : if (parm[0].field.s && strcmp(parm[0].field.s, parm[1].field.s) != 0 && !ignore_pattern(#field)) { \
1491 : current_op.mismatch = #field; \
1492 : printf("Mismatch in %s - %s %s\n", #field, \
1493 : parm[0].field.s, parm[1].field.s); \
1494 : return false; \
1495 : } \
1496 : CHECK_EQUAL(field.private_length); \
1497 : } while(0)
1498 :
1499 : #define CHECK_BLOB_EQUAL(field) do { \
1500 : if (((parm[0].field.data == NULL && parm[1].field.data != NULL) || \
1501 : (parm[1].field.data == NULL && parm[0].field.data != NULL) || \
1502 : (memcmp(parm[0].field.data, parm[1].field.data, parm[0].field.length) != 0)) && !ignore_pattern(#field)) { \
1503 : current_op.mismatch = #field; \
1504 : printf("Mismatch in %s\n", #field); \
1505 : return false; \
1506 : } \
1507 : CHECK_EQUAL(field.length); \
1508 : } while(0)
1509 :
1510 : #define CHECK_TIMES_EQUAL(field) do { \
1511 : if (labs(parm[0].field - parm[1].field) > time_skew() && \
1512 : !ignore_pattern(#field)) { \
1513 : current_op.mismatch = #field; \
1514 : printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
1515 : (int)parm[0].field, (int)parm[1].field); \
1516 : return false; \
1517 : } \
1518 : } while(0)
1519 :
1520 : #define CHECK_NTTIMES_EQUAL(field) do { \
1521 : if (labs(nt_time_to_unix(parm[0].field) - \
1522 : nt_time_to_unix(parm[1].field)) > time_skew() && \
1523 : !ignore_pattern(#field)) { \
1524 : current_op.mismatch = #field; \
1525 : printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
1526 : (int)nt_time_to_unix(parm[0].field), \
1527 : (int)nt_time_to_unix(parm[1].field)); \
1528 : return false; \
1529 : } \
1530 : } while(0)
1531 :
1532 :
1533 : /*
1534 : compare returned fileinfo structures
1535 : */
1536 6 : static bool cmp_fileinfo(int instance,
1537 : union smb_fileinfo parm[NSERVERS],
1538 : NTSTATUS status[NSERVERS])
1539 : {
1540 : int i;
1541 6 : enum smb_fileinfo_level level = parm[0].generic.level;
1542 :
1543 6 : if (level == RAW_FILEINFO_ALL_INFORMATION &&
1544 0 : options.smb2) {
1545 0 : level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
1546 : }
1547 :
1548 6 : switch (level) {
1549 0 : case RAW_FILEINFO_GENERIC:
1550 0 : return false;
1551 :
1552 0 : case RAW_FILEINFO_GETATTR:
1553 0 : CHECK_ATTRIB(getattr.out.attrib);
1554 0 : CHECK_EQUAL(getattr.out.size);
1555 0 : CHECK_TIMES_EQUAL(getattr.out.write_time);
1556 0 : break;
1557 :
1558 0 : case RAW_FILEINFO_GETATTRE:
1559 0 : CHECK_TIMES_EQUAL(getattre.out.create_time);
1560 0 : CHECK_TIMES_EQUAL(getattre.out.access_time);
1561 0 : CHECK_TIMES_EQUAL(getattre.out.write_time);
1562 0 : CHECK_EQUAL(getattre.out.size);
1563 0 : CHECK_EQUAL(getattre.out.alloc_size);
1564 0 : CHECK_ATTRIB(getattre.out.attrib);
1565 0 : break;
1566 :
1567 1 : case RAW_FILEINFO_STANDARD:
1568 1 : CHECK_TIMES_EQUAL(standard.out.create_time);
1569 1 : CHECK_TIMES_EQUAL(standard.out.access_time);
1570 1 : CHECK_TIMES_EQUAL(standard.out.write_time);
1571 1 : CHECK_EQUAL(standard.out.size);
1572 1 : CHECK_EQUAL(standard.out.alloc_size);
1573 1 : CHECK_ATTRIB(standard.out.attrib);
1574 1 : break;
1575 :
1576 0 : case RAW_FILEINFO_EA_SIZE:
1577 0 : CHECK_TIMES_EQUAL(ea_size.out.create_time);
1578 0 : CHECK_TIMES_EQUAL(ea_size.out.access_time);
1579 0 : CHECK_TIMES_EQUAL(ea_size.out.write_time);
1580 0 : CHECK_EQUAL(ea_size.out.size);
1581 0 : CHECK_EQUAL(ea_size.out.alloc_size);
1582 0 : CHECK_ATTRIB(ea_size.out.attrib);
1583 0 : CHECK_EQUAL(ea_size.out.ea_size);
1584 0 : break;
1585 :
1586 0 : case RAW_FILEINFO_ALL_EAS:
1587 0 : CHECK_EQUAL(all_eas.out.num_eas);
1588 0 : for (i=0;i<parm[0].all_eas.out.num_eas;i++) {
1589 0 : CHECK_EQUAL(all_eas.out.eas[i].flags);
1590 0 : CHECK_WSTR_EQUAL(all_eas.out.eas[i].name);
1591 0 : CHECK_BLOB_EQUAL(all_eas.out.eas[i].value);
1592 : }
1593 0 : break;
1594 :
1595 1 : case RAW_FILEINFO_IS_NAME_VALID:
1596 1 : break;
1597 :
1598 1 : case RAW_FILEINFO_BASIC_INFO:
1599 : case RAW_FILEINFO_BASIC_INFORMATION:
1600 1 : CHECK_NTTIMES_EQUAL(basic_info.out.create_time);
1601 1 : CHECK_NTTIMES_EQUAL(basic_info.out.access_time);
1602 1 : CHECK_NTTIMES_EQUAL(basic_info.out.write_time);
1603 1 : CHECK_NTTIMES_EQUAL(basic_info.out.change_time);
1604 1 : CHECK_ATTRIB(basic_info.out.attrib);
1605 1 : break;
1606 :
1607 0 : case RAW_FILEINFO_STANDARD_INFO:
1608 : case RAW_FILEINFO_STANDARD_INFORMATION:
1609 0 : CHECK_EQUAL(standard_info.out.alloc_size);
1610 0 : CHECK_EQUAL(standard_info.out.size);
1611 0 : CHECK_EQUAL(standard_info.out.nlink);
1612 0 : CHECK_EQUAL(standard_info.out.delete_pending);
1613 0 : CHECK_EQUAL(standard_info.out.directory);
1614 0 : break;
1615 :
1616 0 : case RAW_FILEINFO_EA_INFO:
1617 : case RAW_FILEINFO_EA_INFORMATION:
1618 0 : CHECK_EQUAL(ea_info.out.ea_size);
1619 0 : break;
1620 :
1621 0 : case RAW_FILEINFO_NAME_INFO:
1622 : case RAW_FILEINFO_NAME_INFORMATION:
1623 0 : CHECK_WSTR_EQUAL(name_info.out.fname);
1624 0 : break;
1625 :
1626 0 : case RAW_FILEINFO_ALL_INFO:
1627 : case RAW_FILEINFO_ALL_INFORMATION:
1628 0 : CHECK_NTTIMES_EQUAL(all_info.out.create_time);
1629 0 : CHECK_NTTIMES_EQUAL(all_info.out.access_time);
1630 0 : CHECK_NTTIMES_EQUAL(all_info.out.write_time);
1631 0 : CHECK_NTTIMES_EQUAL(all_info.out.change_time);
1632 0 : CHECK_ATTRIB(all_info.out.attrib);
1633 0 : CHECK_EQUAL(all_info.out.alloc_size);
1634 0 : CHECK_EQUAL(all_info.out.size);
1635 0 : CHECK_EQUAL(all_info.out.nlink);
1636 0 : CHECK_EQUAL(all_info.out.delete_pending);
1637 0 : CHECK_EQUAL(all_info.out.directory);
1638 0 : CHECK_EQUAL(all_info.out.ea_size);
1639 0 : CHECK_WSTR_EQUAL(all_info.out.fname);
1640 0 : break;
1641 :
1642 1 : case RAW_FILEINFO_ALT_NAME_INFO:
1643 : case RAW_FILEINFO_ALT_NAME_INFORMATION:
1644 : case RAW_FILEINFO_SMB2_ALT_NAME_INFORMATION:
1645 1 : CHECK_WSTR_EQUAL(alt_name_info.out.fname);
1646 1 : break;
1647 :
1648 0 : case RAW_FILEINFO_STREAM_INFO:
1649 : case RAW_FILEINFO_STREAM_INFORMATION:
1650 0 : CHECK_EQUAL(stream_info.out.num_streams);
1651 0 : for (i=0;i<parm[0].stream_info.out.num_streams;i++) {
1652 0 : CHECK_EQUAL(stream_info.out.streams[i].size);
1653 0 : CHECK_EQUAL(stream_info.out.streams[i].alloc_size);
1654 0 : CHECK_WSTR_EQUAL(stream_info.out.streams[i].stream_name);
1655 : }
1656 0 : break;
1657 :
1658 1 : case RAW_FILEINFO_COMPRESSION_INFO:
1659 : case RAW_FILEINFO_COMPRESSION_INFORMATION:
1660 1 : CHECK_EQUAL(compression_info.out.compressed_size);
1661 1 : CHECK_EQUAL(compression_info.out.format);
1662 1 : CHECK_EQUAL(compression_info.out.unit_shift);
1663 1 : CHECK_EQUAL(compression_info.out.chunk_shift);
1664 1 : CHECK_EQUAL(compression_info.out.cluster_shift);
1665 1 : break;
1666 :
1667 1 : case RAW_FILEINFO_INTERNAL_INFORMATION:
1668 1 : CHECK_EQUAL(internal_information.out.file_id);
1669 1 : break;
1670 :
1671 0 : case RAW_FILEINFO_ACCESS_INFORMATION:
1672 0 : CHECK_EQUAL(access_information.out.access_flags);
1673 0 : break;
1674 :
1675 0 : case RAW_FILEINFO_POSITION_INFORMATION:
1676 0 : CHECK_EQUAL(position_information.out.position);
1677 0 : break;
1678 :
1679 0 : case RAW_FILEINFO_MODE_INFORMATION:
1680 0 : CHECK_EQUAL(mode_information.out.mode);
1681 0 : break;
1682 :
1683 0 : case RAW_FILEINFO_ALIGNMENT_INFORMATION:
1684 0 : CHECK_EQUAL(alignment_information.out.alignment_requirement);
1685 0 : break;
1686 :
1687 0 : case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
1688 0 : CHECK_NTTIMES_EQUAL(network_open_information.out.create_time);
1689 0 : CHECK_NTTIMES_EQUAL(network_open_information.out.access_time);
1690 0 : CHECK_NTTIMES_EQUAL(network_open_information.out.write_time);
1691 0 : CHECK_NTTIMES_EQUAL(network_open_information.out.change_time);
1692 0 : CHECK_EQUAL(network_open_information.out.alloc_size);
1693 0 : CHECK_EQUAL(network_open_information.out.size);
1694 0 : CHECK_ATTRIB(network_open_information.out.attrib);
1695 0 : break;
1696 :
1697 0 : case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
1698 0 : CHECK_ATTRIB(attribute_tag_information.out.attrib);
1699 0 : CHECK_EQUAL(attribute_tag_information.out.reparse_tag);
1700 0 : break;
1701 :
1702 0 : case RAW_FILEINFO_NORMALIZED_NAME_INFORMATION:
1703 0 : CHECK_WSTR_EQUAL(normalized_name_info.out.fname);
1704 0 : break;
1705 :
1706 0 : case RAW_FILEINFO_SMB2_ALL_INFORMATION:
1707 0 : CHECK_NTTIMES_EQUAL(all_info2.out.create_time);
1708 0 : CHECK_NTTIMES_EQUAL(all_info2.out.access_time);
1709 0 : CHECK_NTTIMES_EQUAL(all_info2.out.write_time);
1710 0 : CHECK_NTTIMES_EQUAL(all_info2.out.change_time);
1711 0 : CHECK_ATTRIB(all_info2.out.attrib);
1712 0 : CHECK_EQUAL(all_info2.out.unknown1);
1713 0 : CHECK_EQUAL(all_info2.out.alloc_size);
1714 0 : CHECK_EQUAL(all_info2.out.size);
1715 0 : CHECK_EQUAL(all_info2.out.nlink);
1716 0 : CHECK_EQUAL(all_info2.out.delete_pending);
1717 0 : CHECK_EQUAL(all_info2.out.directory);
1718 0 : CHECK_EQUAL(all_info2.out.file_id);
1719 0 : CHECK_EQUAL(all_info2.out.ea_size);
1720 0 : CHECK_EQUAL(all_info2.out.access_mask);
1721 0 : CHECK_EQUAL(all_info2.out.position);
1722 0 : CHECK_EQUAL(all_info2.out.mode);
1723 0 : CHECK_EQUAL(all_info2.out.alignment_requirement);
1724 0 : CHECK_WSTR_EQUAL(all_info2.out.fname);
1725 0 : break;
1726 :
1727 0 : case RAW_FILEINFO_SMB2_ALL_EAS:
1728 0 : CHECK_EQUAL(all_eas.out.num_eas);
1729 0 : for (i=0;i<parm[0].all_eas.out.num_eas;i++) {
1730 0 : CHECK_EQUAL(all_eas.out.eas[i].flags);
1731 0 : CHECK_WSTR_EQUAL(all_eas.out.eas[i].name);
1732 0 : CHECK_BLOB_EQUAL(all_eas.out.eas[i].value);
1733 : }
1734 0 : break;
1735 :
1736 0 : case RAW_FILEINFO_SEC_DESC:
1737 0 : CHECK_SECDESC(query_secdesc.out.sd);
1738 0 : break;
1739 :
1740 : /* Unhandled levels */
1741 0 : case RAW_FILEINFO_EA_LIST:
1742 : case RAW_FILEINFO_UNIX_BASIC:
1743 : case RAW_FILEINFO_UNIX_LINK:
1744 : case RAW_FILEINFO_UNIX_INFO2:
1745 0 : break;
1746 : }
1747 :
1748 6 : return true;
1749 : }
1750 :
1751 :
1752 :
1753 : /*
1754 : generate openx operations
1755 : */
1756 5 : static bool handler_smb_openx(int instance)
1757 : {
1758 : union smb_open parm[NSERVERS];
1759 : NTSTATUS status[NSERVERS];
1760 :
1761 5 : parm[0].openx.level = RAW_OPEN_OPENX;
1762 5 : parm[0].openx.in.flags = gen_openx_flags();
1763 5 : parm[0].openx.in.open_mode = gen_openx_mode();
1764 5 : parm[0].openx.in.search_attrs = gen_attrib();
1765 5 : parm[0].openx.in.file_attrs = gen_attrib();
1766 5 : parm[0].openx.in.write_time = gen_timet();
1767 5 : parm[0].openx.in.open_func = gen_openx_func();
1768 5 : parm[0].openx.in.size = gen_io_count();
1769 5 : parm[0].openx.in.timeout = gen_timeout();
1770 5 : parm[0].openx.in.fname = gen_fname_open(instance);
1771 :
1772 5 : if (!options.use_oplocks) {
1773 : /* mask out oplocks */
1774 5 : parm[0].openx.in.flags &= ~(OPENX_FLAGS_REQUEST_OPLOCK|
1775 : OPENX_FLAGS_REQUEST_BATCH_OPLOCK);
1776 : }
1777 :
1778 10 : GEN_COPY_PARM;
1779 20 : GEN_CALL_SMB(smb_raw_open(tree, current_op.mem_ctx, &parm[i]));
1780 :
1781 1 : CHECK_ATTRIB(openx.out.attrib);
1782 1 : CHECK_EQUAL(openx.out.size);
1783 1 : CHECK_EQUAL(openx.out.access);
1784 1 : CHECK_EQUAL(openx.out.ftype);
1785 1 : CHECK_EQUAL(openx.out.devstate);
1786 1 : CHECK_EQUAL(openx.out.action);
1787 1 : CHECK_EQUAL(openx.out.access_mask);
1788 1 : CHECK_EQUAL(openx.out.unknown);
1789 1 : CHECK_TIMES_EQUAL(openx.out.write_time);
1790 :
1791 : /* open creates a new file handle */
1792 3 : ADD_HANDLE_SMB(parm[0].openx.in.fname, openx.out.file.fnum);
1793 :
1794 1 : return true;
1795 : }
1796 :
1797 :
1798 : /*
1799 : generate open operations
1800 : */
1801 4 : static bool handler_smb_open(int instance)
1802 : {
1803 : union smb_open parm[NSERVERS];
1804 : NTSTATUS status[NSERVERS];
1805 :
1806 4 : parm[0].openold.level = RAW_OPEN_OPEN;
1807 4 : parm[0].openold.in.open_mode = gen_bits_mask2(0xF, 0xFFFF);
1808 4 : parm[0].openold.in.search_attrs = gen_attrib();
1809 4 : parm[0].openold.in.fname = gen_fname_open(instance);
1810 :
1811 4 : if (!options.use_oplocks) {
1812 : /* mask out oplocks */
1813 4 : parm[0].openold.in.open_mode &= ~(OPENX_FLAGS_REQUEST_OPLOCK|
1814 : OPENX_FLAGS_REQUEST_BATCH_OPLOCK);
1815 : }
1816 :
1817 8 : GEN_COPY_PARM;
1818 16 : GEN_CALL_SMB(smb_raw_open(tree, current_op.mem_ctx, &parm[i]));
1819 :
1820 0 : CHECK_ATTRIB(openold.out.attrib);
1821 0 : CHECK_TIMES_EQUAL(openold.out.write_time);
1822 0 : CHECK_EQUAL(openold.out.size);
1823 0 : CHECK_EQUAL(openold.out.rmode);
1824 :
1825 : /* open creates a new file handle */
1826 0 : ADD_HANDLE_SMB(parm[0].openold.in.fname, openold.out.file.fnum);
1827 :
1828 0 : return true;
1829 : }
1830 :
1831 :
1832 : /*
1833 : generate ntcreatex operations
1834 : */
1835 8 : static bool handler_smb_ntcreatex(int instance)
1836 : {
1837 : union smb_open parm[NSERVERS];
1838 : NTSTATUS status[NSERVERS];
1839 :
1840 8 : parm[0].ntcreatex.level = RAW_OPEN_NTCREATEX;
1841 8 : parm[0].ntcreatex.in.flags = gen_ntcreatex_flags();
1842 8 : parm[0].ntcreatex.in.root_fid.fnum = gen_root_fid(instance);
1843 8 : parm[0].ntcreatex.in.access_mask = gen_access_mask();
1844 8 : parm[0].ntcreatex.in.alloc_size = gen_alloc_size();
1845 8 : parm[0].ntcreatex.in.file_attr = gen_attrib();
1846 8 : parm[0].ntcreatex.in.share_access = gen_bits_mask2(0x7, 0xFFFFFFFF);
1847 8 : parm[0].ntcreatex.in.open_disposition = gen_open_disp();
1848 8 : parm[0].ntcreatex.in.create_options = gen_create_options();
1849 8 : parm[0].ntcreatex.in.impersonation = gen_bits_mask2(0, 0xFFFFFFFF);
1850 8 : parm[0].ntcreatex.in.security_flags = gen_bits_mask2(0, 0xFF);
1851 8 : parm[0].ntcreatex.in.fname = gen_fname_open(instance);
1852 :
1853 8 : if (!options.use_oplocks) {
1854 : /* mask out oplocks */
1855 8 : parm[0].ntcreatex.in.flags &= ~(NTCREATEX_FLAGS_REQUEST_OPLOCK|
1856 : NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK);
1857 : }
1858 :
1859 16 : GEN_COPY_PARM;
1860 8 : if (parm[0].ntcreatex.in.root_fid.fnum != 0) {
1861 0 : GEN_SET_FNUM_SMB(ntcreatex.in.root_fid.fnum);
1862 : }
1863 32 : GEN_CALL_SMB(smb_raw_open(tree, current_op.mem_ctx, &parm[i]));
1864 :
1865 2 : CHECK_EQUAL(ntcreatex.out.oplock_level);
1866 2 : CHECK_EQUAL(ntcreatex.out.create_action);
1867 2 : CHECK_NTTIMES_EQUAL(ntcreatex.out.create_time);
1868 2 : CHECK_NTTIMES_EQUAL(ntcreatex.out.access_time);
1869 2 : CHECK_NTTIMES_EQUAL(ntcreatex.out.write_time);
1870 2 : CHECK_NTTIMES_EQUAL(ntcreatex.out.change_time);
1871 2 : CHECK_ATTRIB(ntcreatex.out.attrib);
1872 2 : CHECK_EQUAL(ntcreatex.out.alloc_size);
1873 2 : CHECK_EQUAL(ntcreatex.out.size);
1874 2 : CHECK_EQUAL(ntcreatex.out.file_type);
1875 2 : CHECK_EQUAL(ntcreatex.out.ipc_state);
1876 2 : CHECK_EQUAL(ntcreatex.out.is_directory);
1877 :
1878 : /* ntcreatex creates a new file handle */
1879 6 : ADD_HANDLE_SMB(parm[0].ntcreatex.in.fname, ntcreatex.out.file.fnum);
1880 :
1881 2 : return true;
1882 : }
1883 :
1884 : /*
1885 : generate close operations
1886 : */
1887 5 : static bool handler_smb_close(int instance)
1888 : {
1889 : union smb_close parm[NSERVERS];
1890 : NTSTATUS status[NSERVERS];
1891 :
1892 5 : parm[0].close.level = RAW_CLOSE_CLOSE;
1893 5 : parm[0].close.in.file.fnum = gen_fnum_close(instance);
1894 5 : parm[0].close.in.write_time = gen_timet();
1895 :
1896 10 : GEN_COPY_PARM;
1897 15 : GEN_SET_FNUM_SMB(close.in.file.fnum);
1898 20 : GEN_CALL_SMB(smb_raw_close(tree, &parm[i]));
1899 :
1900 0 : REMOVE_HANDLE_SMB(close.in.file.fnum);
1901 :
1902 0 : return true;
1903 : }
1904 :
1905 : /*
1906 : generate unlink operations
1907 : */
1908 1 : static bool handler_smb_unlink(int instance)
1909 : {
1910 : union smb_unlink parm[NSERVERS];
1911 : NTSTATUS status[NSERVERS];
1912 :
1913 1 : parm[0].unlink.in.pattern = gen_pattern();
1914 1 : parm[0].unlink.in.attrib = gen_attrib();
1915 :
1916 2 : GEN_COPY_PARM;
1917 4 : GEN_CALL_SMB(smb_raw_unlink(tree, &parm[i]));
1918 :
1919 0 : return true;
1920 : }
1921 :
1922 : /*
1923 : generate chkpath operations
1924 : */
1925 5 : static bool handler_smb_chkpath(int instance)
1926 : {
1927 : union smb_chkpath parm[NSERVERS];
1928 : NTSTATUS status[NSERVERS];
1929 :
1930 5 : parm[0].chkpath.in.path = gen_fname_open(instance);
1931 :
1932 10 : GEN_COPY_PARM;
1933 20 : GEN_CALL_SMB(smb_raw_chkpath(tree, &parm[i]));
1934 :
1935 0 : return true;
1936 : }
1937 :
1938 : /*
1939 : generate mkdir operations
1940 : */
1941 2 : static bool handler_smb_mkdir(int instance)
1942 : {
1943 : union smb_mkdir parm[NSERVERS];
1944 : NTSTATUS status[NSERVERS];
1945 :
1946 2 : parm[0].mkdir.level = RAW_MKDIR_MKDIR;
1947 2 : parm[0].mkdir.in.path = gen_fname_open(instance);
1948 :
1949 4 : GEN_COPY_PARM;
1950 8 : GEN_CALL_SMB(smb_raw_mkdir(tree, &parm[i]));
1951 :
1952 0 : return true;
1953 : }
1954 :
1955 : /*
1956 : generate rmdir operations
1957 : */
1958 5 : static bool handler_smb_rmdir(int instance)
1959 : {
1960 : struct smb_rmdir parm[NSERVERS];
1961 : NTSTATUS status[NSERVERS];
1962 :
1963 5 : parm[0].in.path = gen_fname_open(instance);
1964 :
1965 10 : GEN_COPY_PARM;
1966 20 : GEN_CALL_SMB(smb_raw_rmdir(tree, &parm[i]));
1967 :
1968 0 : return true;
1969 : }
1970 :
1971 : /*
1972 : generate rename operations
1973 : */
1974 5 : static bool handler_smb_rename(int instance)
1975 : {
1976 : union smb_rename parm[NSERVERS];
1977 : NTSTATUS status[NSERVERS];
1978 :
1979 5 : parm[0].generic.level = RAW_RENAME_RENAME;
1980 5 : parm[0].rename.in.pattern1 = gen_pattern();
1981 5 : parm[0].rename.in.pattern2 = gen_pattern();
1982 5 : parm[0].rename.in.attrib = gen_attrib();
1983 :
1984 10 : GEN_COPY_PARM;
1985 20 : GEN_CALL_SMB(smb_raw_rename(tree, &parm[i]));
1986 :
1987 1 : return true;
1988 : }
1989 :
1990 : /*
1991 : generate ntrename operations
1992 : */
1993 4 : static bool handler_smb_ntrename(int instance)
1994 : {
1995 : union smb_rename parm[NSERVERS];
1996 : NTSTATUS status[NSERVERS];
1997 :
1998 4 : parm[0].generic.level = RAW_RENAME_NTRENAME;
1999 4 : parm[0].ntrename.in.old_name = gen_fname();
2000 4 : parm[0].ntrename.in.new_name = gen_fname();
2001 4 : parm[0].ntrename.in.attrib = gen_attrib();
2002 4 : parm[0].ntrename.in.cluster_size = gen_bits_mask2(0, 0xFFFFFFF);
2003 4 : parm[0].ntrename.in.flags = gen_rename_flags();
2004 :
2005 8 : GEN_COPY_PARM;
2006 16 : GEN_CALL_SMB(smb_raw_rename(tree, &parm[i]));
2007 :
2008 0 : return true;
2009 : }
2010 :
2011 :
2012 : /*
2013 : generate seek operations
2014 : */
2015 9 : static bool handler_smb_seek(int instance)
2016 : {
2017 : union smb_seek parm[NSERVERS];
2018 : NTSTATUS status[NSERVERS];
2019 :
2020 9 : parm[0].lseek.in.file.fnum = gen_fnum(instance);
2021 9 : parm[0].lseek.in.mode = gen_bits_mask2(0x3, 0xFFFF);
2022 9 : parm[0].lseek.in.offset = gen_offset();
2023 :
2024 18 : GEN_COPY_PARM;
2025 27 : GEN_SET_FNUM_SMB(lseek.in.file.fnum);
2026 36 : GEN_CALL_SMB(smb_raw_seek(tree, &parm[i]));
2027 :
2028 2 : CHECK_EQUAL(lseek.out.offset);
2029 :
2030 2 : return true;
2031 : }
2032 :
2033 :
2034 : /*
2035 : generate readx operations
2036 : */
2037 7 : static bool handler_smb_readx(int instance)
2038 : {
2039 : union smb_read parm[NSERVERS];
2040 : NTSTATUS status[NSERVERS];
2041 :
2042 7 : parm[0].readx.level = RAW_READ_READX;
2043 7 : parm[0].readx.in.file.fnum = gen_fnum(instance);
2044 7 : parm[0].readx.in.offset = gen_offset();
2045 7 : parm[0].readx.in.mincnt = gen_io_count();
2046 7 : parm[0].readx.in.maxcnt = gen_io_count();
2047 7 : parm[0].readx.in.remaining = gen_io_count();
2048 7 : parm[0].readx.in.read_for_execute = gen_bool();
2049 7 : parm[0].readx.out.data = talloc_array(current_op.mem_ctx, uint8_t,
2050 : MAX(parm[0].readx.in.mincnt, parm[0].readx.in.maxcnt));
2051 :
2052 14 : GEN_COPY_PARM;
2053 21 : GEN_SET_FNUM_SMB(readx.in.file.fnum);
2054 28 : GEN_CALL_SMB(smb_raw_read(tree, &parm[i]));
2055 :
2056 4 : CHECK_EQUAL(readx.out.remaining);
2057 4 : CHECK_EQUAL(readx.out.compaction_mode);
2058 4 : CHECK_EQUAL(readx.out.nread);
2059 :
2060 4 : return true;
2061 : }
2062 :
2063 : /*
2064 : generate writex operations
2065 : */
2066 8 : static bool handler_smb_writex(int instance)
2067 : {
2068 : union smb_write parm[NSERVERS];
2069 : NTSTATUS status[NSERVERS];
2070 :
2071 8 : parm[0].writex.level = RAW_WRITE_WRITEX;
2072 8 : parm[0].writex.in.file.fnum = gen_fnum(instance);
2073 8 : parm[0].writex.in.offset = gen_offset();
2074 8 : parm[0].writex.in.wmode = gen_bits_mask(0xFFFF);
2075 8 : parm[0].writex.in.remaining = gen_io_count();
2076 8 : parm[0].writex.in.count = gen_io_count();
2077 8 : parm[0].writex.in.data = talloc_zero_array(current_op.mem_ctx, uint8_t, parm[0].writex.in.count);
2078 :
2079 16 : GEN_COPY_PARM;
2080 24 : GEN_SET_FNUM_SMB(writex.in.file.fnum);
2081 32 : GEN_CALL_SMB(smb_raw_write(tree, &parm[i]));
2082 :
2083 7 : CHECK_EQUAL(writex.out.nwritten);
2084 7 : CHECK_EQUAL(writex.out.remaining);
2085 :
2086 7 : return true;
2087 : }
2088 :
2089 : /*
2090 : generate lockingx operations
2091 : */
2092 6 : static bool handler_smb_lockingx(int instance)
2093 : {
2094 : union smb_lock parm[NSERVERS];
2095 : NTSTATUS status[NSERVERS];
2096 : int n, nlocks;
2097 :
2098 6 : parm[0].lockx.level = RAW_LOCK_LOCKX;
2099 6 : parm[0].lockx.in.file.fnum = gen_fnum(instance);
2100 6 : parm[0].lockx.in.mode = gen_lock_mode();
2101 6 : parm[0].lockx.in.timeout = gen_timeout();
2102 : do {
2103 : /* make sure we don't accidentally generate an oplock
2104 : break ack - otherwise the server can just block forever */
2105 6 : parm[0].lockx.in.ulock_cnt = gen_lock_count();
2106 6 : parm[0].lockx.in.lock_cnt = gen_lock_count();
2107 6 : nlocks = parm[0].lockx.in.ulock_cnt + parm[0].lockx.in.lock_cnt;
2108 6 : } while (nlocks == 0);
2109 :
2110 6 : if (nlocks > 0) {
2111 6 : parm[0].lockx.in.locks = talloc_array(current_op.mem_ctx,
2112 : struct smb_lock_entry,
2113 : nlocks);
2114 24 : for (n=0;n<nlocks;n++) {
2115 18 : parm[0].lockx.in.locks[n].pid = gen_pid();
2116 18 : parm[0].lockx.in.locks[n].offset = gen_offset();
2117 18 : parm[0].lockx.in.locks[n].count = gen_io_count();
2118 : }
2119 : }
2120 :
2121 12 : GEN_COPY_PARM;
2122 18 : GEN_SET_FNUM_SMB(lockx.in.file.fnum);
2123 24 : GEN_CALL_SMB(smb_raw_lock(tree, &parm[i]));
2124 :
2125 2 : return true;
2126 : }
2127 :
2128 : #if 0
2129 : /*
2130 : generate a fileinfo query structure
2131 : */
2132 : static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
2133 : {
2134 : int i;
2135 : #undef LVL
2136 : #define LVL(v) {RAW_SFILEINFO_ ## v, "RAW_SFILEINFO_" #v}
2137 : struct {
2138 : enum smb_setfileinfo_level level;
2139 : const char *name;
2140 : } levels[] = {
2141 : #if 0
2142 : /* disabled until win2003 can handle them ... */
2143 : LVL(EA_SET), LVL(BASIC_INFO), LVL(DISPOSITION_INFO),
2144 : LVL(STANDARD), LVL(ALLOCATION_INFO), LVL(END_OF_FILE_INFO),
2145 : #endif
2146 : LVL(SETATTR), LVL(SETATTRE), LVL(BASIC_INFORMATION),
2147 : LVL(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION),
2148 : LVL(POSITION_INFORMATION), LVL(MODE_INFORMATION),
2149 : LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION),
2150 : LVL(1023), LVL(1025), LVL(1029), LVL(1032), LVL(1039), LVL(1040)
2151 : };
2152 : do {
2153 : i = gen_int_range(0, ARRAY_SIZE(levels)-1);
2154 : } while (ignore_pattern(levels[i].name));
2155 :
2156 : info->generic.level = levels[i].level;
2157 :
2158 : switch (info->generic.level) {
2159 : case RAW_SFILEINFO_SETATTR:
2160 : info->setattr.in.attrib = gen_attrib();
2161 : info->setattr.in.write_time = gen_timet();
2162 : break;
2163 : case RAW_SFILEINFO_SETATTRE:
2164 : info->setattre.in.create_time = gen_timet();
2165 : info->setattre.in.access_time = gen_timet();
2166 : info->setattre.in.write_time = gen_timet();
2167 : break;
2168 : case RAW_SFILEINFO_STANDARD:
2169 : info->standard.in.create_time = gen_timet();
2170 : info->standard.in.access_time = gen_timet();
2171 : info->standard.in.write_time = gen_timet();
2172 : break;
2173 : case RAW_SFILEINFO_EA_SET: {
2174 : static struct ea_struct ea;
2175 : info->ea_set.in.num_eas = 1;
2176 : info->ea_set.in.eas = &ea;
2177 : info->ea_set.in.eas[0] = gen_ea_struct();
2178 : }
2179 : break;
2180 : case RAW_SFILEINFO_BASIC_INFO:
2181 : case RAW_SFILEINFO_BASIC_INFORMATION:
2182 : info->basic_info.in.create_time = gen_nttime();
2183 : info->basic_info.in.access_time = gen_nttime();
2184 : info->basic_info.in.write_time = gen_nttime();
2185 : info->basic_info.in.change_time = gen_nttime();
2186 : info->basic_info.in.attrib = gen_attrib();
2187 : break;
2188 : case RAW_SFILEINFO_DISPOSITION_INFO:
2189 : case RAW_SFILEINFO_DISPOSITION_INFORMATION:
2190 : info->disposition_info.in.delete_on_close = gen_bool();
2191 : break;
2192 : case RAW_SFILEINFO_ALLOCATION_INFO:
2193 : case RAW_SFILEINFO_ALLOCATION_INFORMATION:
2194 : info->allocation_info.in.alloc_size = gen_alloc_size();
2195 : break;
2196 : case RAW_SFILEINFO_END_OF_FILE_INFO:
2197 : case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
2198 : info->end_of_file_info.in.size = gen_offset();
2199 : break;
2200 : case RAW_SFILEINFO_RENAME_INFORMATION:
2201 : case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
2202 : info->rename_information.in.overwrite = gen_bool();
2203 : info->rename_information.in.root_fid = gen_root_fid(instance);
2204 : info->rename_information.in.new_name = gen_fname_open(instance);
2205 : break;
2206 : case RAW_SFILEINFO_POSITION_INFORMATION:
2207 : info->position_information.in.position = gen_offset();
2208 : break;
2209 : case RAW_SFILEINFO_MODE_INFORMATION:
2210 : info->mode_information.in.mode = gen_bits_mask(0xFFFFFFFF);
2211 : break;
2212 : case RAW_SFILEINFO_FULL_EA_INFORMATION:
2213 : info->full_ea_information.in.eas = gen_ea_list();
2214 : break;
2215 : case RAW_SFILEINFO_GENERIC:
2216 : case RAW_SFILEINFO_SEC_DESC:
2217 : case RAW_SFILEINFO_UNIX_BASIC:
2218 : case RAW_SFILEINFO_UNIX_LINK:
2219 : case RAW_SFILEINFO_UNIX_HLINK:
2220 : case RAW_SFILEINFO_1023:
2221 : case RAW_SFILEINFO_1025:
2222 : case RAW_SFILEINFO_1029:
2223 : case RAW_SFILEINFO_1032:
2224 : case RAW_SFILEINFO_1039:
2225 : case RAW_SFILEINFO_1040:
2226 : case RAW_SFILEINFO_UNIX_INFO2:
2227 : /* Untested */
2228 : break;
2229 : }
2230 : }
2231 : #endif
2232 :
2233 : /*
2234 : generate a fileinfo query structure
2235 : */
2236 11 : static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
2237 : {
2238 : int i;
2239 : #undef LVL
2240 : #define LVL(v) {RAW_SFILEINFO_ ## v, "RAW_SFILEINFO_" #v}
2241 : struct levels {
2242 : enum smb_setfileinfo_level level;
2243 : const char *name;
2244 : };
2245 11 : struct levels smb_levels[] = {
2246 : LVL(EA_SET), LVL(BASIC_INFO), LVL(DISPOSITION_INFO),
2247 : LVL(STANDARD), LVL(ALLOCATION_INFO), LVL(END_OF_FILE_INFO),
2248 : LVL(SETATTR), LVL(SETATTRE), LVL(BASIC_INFORMATION),
2249 : LVL(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION),
2250 : LVL(POSITION_INFORMATION), LVL(FULL_EA_INFORMATION), LVL(MODE_INFORMATION),
2251 : LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION),
2252 : LVL(PIPE_INFORMATION), LVL(VALID_DATA_INFORMATION), LVL(SHORT_NAME_INFORMATION),
2253 : LVL(1025), LVL(1027), LVL(1029), LVL(1030), LVL(1031), LVL(1032), LVL(1036),
2254 : LVL(1041), LVL(1042), LVL(1043), LVL(1044),
2255 : };
2256 11 : struct levels smb2_levels[] = {
2257 : LVL(BASIC_INFORMATION),
2258 : LVL(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION),
2259 : LVL(POSITION_INFORMATION), LVL(FULL_EA_INFORMATION), LVL(MODE_INFORMATION),
2260 : LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION),
2261 : LVL(PIPE_INFORMATION), LVL(VALID_DATA_INFORMATION), LVL(SHORT_NAME_INFORMATION),
2262 : LVL(1025), LVL(1027), LVL(1029), LVL(1030), LVL(1031), LVL(1032), LVL(1036),
2263 : LVL(1041), LVL(1042), LVL(1043), LVL(1044),
2264 : };
2265 11 : struct levels *levels = options.smb2?smb2_levels:smb_levels;
2266 11 : uint32_t num_levels = options.smb2?ARRAY_SIZE(smb2_levels):ARRAY_SIZE(smb_levels);
2267 :
2268 : do {
2269 11 : i = gen_int_range(0, num_levels-1);
2270 11 : } while (ignore_pattern(levels[i].name));
2271 :
2272 11 : ZERO_STRUCTP(info);
2273 11 : info->generic.level = levels[i].level;
2274 :
2275 11 : switch (info->generic.level) {
2276 0 : case RAW_SFILEINFO_SETATTR:
2277 0 : info->setattr.in.attrib = gen_attrib();
2278 0 : info->setattr.in.write_time = gen_timet();
2279 0 : break;
2280 0 : case RAW_SFILEINFO_SETATTRE:
2281 0 : info->setattre.in.create_time = gen_timet();
2282 0 : info->setattre.in.access_time = gen_timet();
2283 0 : info->setattre.in.write_time = gen_timet();
2284 0 : break;
2285 0 : case RAW_SFILEINFO_STANDARD:
2286 0 : info->standard.in.create_time = gen_timet();
2287 0 : info->standard.in.access_time = gen_timet();
2288 0 : info->standard.in.write_time = gen_timet();
2289 0 : break;
2290 1 : case RAW_SFILEINFO_EA_SET: {
2291 : static struct ea_struct ea;
2292 1 : info->ea_set.in.num_eas = 1;
2293 1 : info->ea_set.in.eas = &ea;
2294 1 : info->ea_set.in.eas[0] = gen_ea_struct();
2295 1 : break;
2296 : }
2297 0 : case RAW_SFILEINFO_BASIC_INFO:
2298 : case RAW_SFILEINFO_BASIC_INFORMATION:
2299 0 : info->basic_info.in.create_time = gen_nttime();
2300 0 : info->basic_info.in.access_time = gen_nttime();
2301 0 : info->basic_info.in.write_time = gen_nttime();
2302 0 : info->basic_info.in.change_time = gen_nttime();
2303 0 : info->basic_info.in.attrib = gen_attrib();
2304 0 : break;
2305 2 : case RAW_SFILEINFO_DISPOSITION_INFO:
2306 : case RAW_SFILEINFO_DISPOSITION_INFORMATION:
2307 2 : info->disposition_info.in.delete_on_close = gen_bool();
2308 2 : break;
2309 2 : case RAW_SFILEINFO_ALLOCATION_INFO:
2310 : case RAW_SFILEINFO_ALLOCATION_INFORMATION:
2311 2 : info->allocation_info.in.alloc_size = gen_alloc_size();
2312 2 : break;
2313 0 : case RAW_SFILEINFO_END_OF_FILE_INFO:
2314 : case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
2315 0 : info->end_of_file_info.in.size = gen_offset();
2316 0 : break;
2317 0 : case RAW_SFILEINFO_RENAME_INFORMATION:
2318 : case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
2319 0 : info->rename_information.in.overwrite = gen_bool();
2320 0 : info->rename_information.in.root_fid = gen_root_fid(instance);
2321 0 : info->rename_information.in.new_name = gen_fname_open(instance);
2322 0 : break;
2323 2 : case RAW_SFILEINFO_POSITION_INFORMATION:
2324 2 : info->position_information.in.position = gen_offset();
2325 2 : break;
2326 1 : case RAW_SFILEINFO_MODE_INFORMATION:
2327 1 : info->mode_information.in.mode = gen_bits_mask(0xFFFFFFFF);
2328 1 : break;
2329 1 : case RAW_SFILEINFO_FULL_EA_INFORMATION:
2330 1 : info->full_ea_information.in.eas = gen_ea_list();
2331 1 : break;
2332 :
2333 2 : case RAW_SFILEINFO_GENERIC:
2334 : case RAW_SFILEINFO_SEC_DESC:
2335 : case RAW_SFILEINFO_1025:
2336 : case RAW_SFILEINFO_1029:
2337 : case RAW_SFILEINFO_1032:
2338 : case RAW_SFILEINFO_UNIX_BASIC:
2339 : case RAW_SFILEINFO_UNIX_INFO2:
2340 : case RAW_SFILEINFO_UNIX_LINK:
2341 : case RAW_SFILEINFO_UNIX_HLINK:
2342 : case RAW_SFILEINFO_LINK_INFORMATION:
2343 : case RAW_SFILEINFO_PIPE_INFORMATION:
2344 : case RAW_SFILEINFO_VALID_DATA_INFORMATION:
2345 : case RAW_SFILEINFO_SHORT_NAME_INFORMATION:
2346 : case RAW_SFILEINFO_1027:
2347 : case RAW_SFILEINFO_1030:
2348 : case RAW_SFILEINFO_1031:
2349 : case RAW_SFILEINFO_1036:
2350 : case RAW_SFILEINFO_1041:
2351 : case RAW_SFILEINFO_1042:
2352 : case RAW_SFILEINFO_1043:
2353 : case RAW_SFILEINFO_1044:
2354 : /* Untested */
2355 2 : break;
2356 : }
2357 11 : }
2358 :
2359 :
2360 :
2361 : /*
2362 : generate a fileinfo query structure
2363 : */
2364 10 : static void gen_fileinfo_smb(int instance, union smb_fileinfo *info)
2365 : {
2366 : int i;
2367 : #undef LVL
2368 : #define LVL(v) {RAW_FILEINFO_ ## v, "RAW_FILEINFO_" #v}
2369 : struct {
2370 : enum smb_fileinfo_level level;
2371 : const char *name;
2372 10 : } levels[] = {
2373 : LVL(GETATTR), LVL(GETATTRE), LVL(STANDARD),
2374 : LVL(EA_SIZE), LVL(ALL_EAS), LVL(IS_NAME_VALID),
2375 : LVL(BASIC_INFO), LVL(STANDARD_INFO), LVL(EA_INFO),
2376 : LVL(NAME_INFO), LVL(ALL_INFO), LVL(ALT_NAME_INFO),
2377 : LVL(STREAM_INFO), LVL(COMPRESSION_INFO), LVL(BASIC_INFORMATION),
2378 : LVL(STANDARD_INFORMATION), LVL(INTERNAL_INFORMATION), LVL(EA_INFORMATION),
2379 : LVL(ACCESS_INFORMATION), LVL(NAME_INFORMATION), LVL(POSITION_INFORMATION),
2380 : LVL(MODE_INFORMATION), LVL(ALIGNMENT_INFORMATION), LVL(ALL_INFORMATION),
2381 : LVL(ALT_NAME_INFORMATION), LVL(STREAM_INFORMATION), LVL(COMPRESSION_INFORMATION),
2382 : LVL(NETWORK_OPEN_INFORMATION), LVL(ATTRIBUTE_TAG_INFORMATION)
2383 : };
2384 : do {
2385 10 : i = gen_int_range(0, ARRAY_SIZE(levels)-1);
2386 10 : } while (ignore_pattern(levels[i].name));
2387 :
2388 10 : info->generic.level = levels[i].level;
2389 10 : }
2390 :
2391 : /*
2392 : generate qpathinfo operations
2393 : */
2394 7 : static bool handler_smb_qpathinfo(int instance)
2395 : {
2396 : union smb_fileinfo parm[NSERVERS];
2397 : NTSTATUS status[NSERVERS];
2398 :
2399 7 : parm[0].generic.in.file.path = gen_fname_open(instance);
2400 :
2401 7 : gen_fileinfo_smb(instance, &parm[0]);
2402 :
2403 14 : GEN_COPY_PARM;
2404 28 : GEN_CALL_SMB(smb_raw_pathinfo(tree, current_op.mem_ctx, &parm[i]));
2405 :
2406 4 : return cmp_fileinfo(instance, parm, status);
2407 : }
2408 :
2409 : /*
2410 : generate qfileinfo operations
2411 : */
2412 3 : static bool handler_smb_qfileinfo(int instance)
2413 : {
2414 : union smb_fileinfo parm[NSERVERS];
2415 : NTSTATUS status[NSERVERS];
2416 :
2417 3 : parm[0].generic.in.file.fnum = gen_fnum(instance);
2418 :
2419 3 : gen_fileinfo_smb(instance, &parm[0]);
2420 :
2421 6 : GEN_COPY_PARM;
2422 9 : GEN_SET_FNUM_SMB(generic.in.file.fnum);
2423 12 : GEN_CALL_SMB(smb_raw_fileinfo(tree, current_op.mem_ctx, &parm[i]));
2424 :
2425 2 : return cmp_fileinfo(instance, parm, status);
2426 : }
2427 :
2428 :
2429 : /*
2430 : generate setpathinfo operations
2431 : */
2432 5 : static bool handler_smb_spathinfo(int instance)
2433 : {
2434 : union smb_setfileinfo parm[NSERVERS];
2435 : NTSTATUS status[NSERVERS];
2436 :
2437 5 : gen_setfileinfo(instance, &parm[0]);
2438 5 : parm[0].generic.in.file.path = gen_fname_open(instance);
2439 :
2440 10 : GEN_COPY_PARM;
2441 :
2442 : /* a special case for the fid in a RENAME */
2443 5 : if (parm[0].generic.level == RAW_SFILEINFO_RENAME_INFORMATION &&
2444 0 : parm[0].rename_information.in.root_fid != 0) {
2445 0 : GEN_SET_FNUM_SMB(rename_information.in.root_fid);
2446 : }
2447 :
2448 20 : GEN_CALL_SMB(smb_raw_setpathinfo(tree, &parm[i]));
2449 :
2450 0 : return true;
2451 : }
2452 :
2453 :
2454 : /*
2455 : generate setfileinfo operations
2456 : */
2457 6 : static bool handler_smb_sfileinfo(int instance)
2458 : {
2459 : union smb_setfileinfo parm[NSERVERS];
2460 : NTSTATUS status[NSERVERS];
2461 :
2462 6 : parm[0].generic.in.file.fnum = gen_fnum(instance);
2463 :
2464 6 : gen_setfileinfo(instance, &parm[0]);
2465 :
2466 12 : GEN_COPY_PARM;
2467 18 : GEN_SET_FNUM_SMB(generic.in.file.fnum);
2468 24 : GEN_CALL_SMB(smb_raw_setfileinfo(tree, &parm[i]));
2469 :
2470 2 : return true;
2471 : }
2472 :
2473 :
2474 : /*
2475 : this is called when a change notify reply comes in
2476 : */
2477 10 : static void async_notify_smb(struct smbcli_request *req)
2478 : {
2479 : union smb_notify notify;
2480 : NTSTATUS status;
2481 : int i, j;
2482 10 : uint16_t tid = 0;
2483 10 : struct smbcli_transport *transport = req->transport;
2484 :
2485 10 : if (req->tree) {
2486 10 : tid = req->tree->tid;
2487 : }
2488 :
2489 10 : notify.nttrans.level = RAW_NOTIFY_NTTRANS;
2490 10 : status = smb_raw_changenotify_recv(req, current_op.mem_ctx, ¬ify);
2491 10 : if (NT_STATUS_IS_OK(status) && notify.nttrans.out.num_changes > 0) {
2492 0 : printf("notify tid=%d num_changes=%d action=%d name=%s\n",
2493 : tid,
2494 : notify.nttrans.out.num_changes,
2495 0 : notify.nttrans.out.changes[0].action,
2496 0 : notify.nttrans.out.changes[0].name.s);
2497 : }
2498 :
2499 30 : for (i=0;i<NSERVERS;i++) {
2500 60 : for (j=0;j<NINSTANCES;j++) {
2501 40 : if (transport == servers[i].smb_tree[j]->session->transport &&
2502 10 : tid == servers[i].smb_tree[j]->tid) {
2503 10 : notifies[i][j].notify_count++;
2504 10 : notifies[i][j].status = status;
2505 10 : notifies[i][j].notify = notify;
2506 : }
2507 : }
2508 : }
2509 10 : }
2510 :
2511 : /*
2512 : generate change notify operations
2513 : */
2514 5 : static bool handler_smb_notify(int instance)
2515 : {
2516 : union smb_notify parm[NSERVERS];
2517 : int n;
2518 :
2519 5 : ZERO_STRUCT(parm[0]);
2520 5 : parm[0].nttrans.level = RAW_NOTIFY_NTTRANS;
2521 5 : parm[0].nttrans.in.buffer_size = gen_io_count();
2522 5 : parm[0].nttrans.in.completion_filter = gen_bits_mask(0xFF);
2523 5 : parm[0].nttrans.in.file.fnum = gen_fnum(instance);
2524 5 : parm[0].nttrans.in.recursive = gen_bool();
2525 :
2526 10 : GEN_COPY_PARM;
2527 15 : GEN_SET_FNUM_SMB(nttrans.in.file.fnum);
2528 :
2529 15 : for (n=0;n<NSERVERS;n++) {
2530 : struct smbcli_request *req;
2531 10 : req = smb_raw_changenotify_send(servers[n].smb_tree[instance], &parm[n]);
2532 10 : req->async.fn = async_notify_smb;
2533 : }
2534 :
2535 5 : return true;
2536 : }
2537 :
2538 :
2539 : /*
2540 : generate ntcreatex operations
2541 : */
2542 0 : static bool handler_smb2_create(int instance)
2543 : {
2544 : struct smb2_create parm[NSERVERS];
2545 : NTSTATUS status[NSERVERS];
2546 :
2547 0 : ZERO_STRUCT(parm[0]);
2548 0 : parm[0].in.security_flags = gen_bits_levels(3, 90, 0x0, 70, 0x3, 100, 0xFF);
2549 0 : parm[0].in.oplock_level = gen_bits_levels(3, 90, 0x0, 70, 0x9, 100, 0xFF);
2550 0 : parm[0].in.impersonation_level = gen_bits_levels(3, 90, 0x0, 70, 0x3, 100, 0xFFFFFFFF);
2551 0 : parm[0].in.create_flags = gen_reserved64();
2552 0 : parm[0].in.reserved = gen_reserved64();
2553 0 : parm[0].in.desired_access = gen_access_mask();
2554 0 : parm[0].in.file_attributes = gen_attrib();
2555 0 : parm[0].in.share_access = gen_bits_mask2(0x7, 0xFFFFFFFF);
2556 0 : parm[0].in.create_disposition = gen_open_disp();
2557 0 : parm[0].in.create_options = gen_create_options();
2558 0 : parm[0].in.fname = gen_fname_open(instance);
2559 0 : parm[0].in.eas = gen_ea_list();
2560 0 : parm[0].in.alloc_size = gen_alloc_size();
2561 0 : parm[0].in.durable_open = gen_bool();
2562 0 : parm[0].in.query_maximal_access = gen_bool();
2563 0 : parm[0].in.timewarp = gen_timewarp();
2564 0 : parm[0].in.query_on_disk_id = gen_bool();
2565 0 : parm[0].in.sec_desc = gen_sec_desc();
2566 :
2567 0 : if (!options.use_oplocks) {
2568 : /* mask out oplocks */
2569 0 : parm[0].in.oplock_level = 0;
2570 : }
2571 :
2572 0 : if (options.valid) {
2573 0 : parm[0].in.security_flags &= 3;
2574 0 : parm[0].in.oplock_level &= 9;
2575 0 : parm[0].in.impersonation_level &= 3;
2576 : }
2577 :
2578 0 : GEN_COPY_PARM;
2579 0 : GEN_CALL_SMB2(smb2_create(tree, current_op.mem_ctx, &parm[i]));
2580 :
2581 0 : CHECK_EQUAL(out.oplock_level);
2582 0 : CHECK_EQUAL(out.reserved);
2583 0 : CHECK_EQUAL(out.create_action);
2584 0 : CHECK_NTTIMES_EQUAL(out.create_time);
2585 0 : CHECK_NTTIMES_EQUAL(out.access_time);
2586 0 : CHECK_NTTIMES_EQUAL(out.write_time);
2587 0 : CHECK_NTTIMES_EQUAL(out.change_time);
2588 0 : CHECK_EQUAL(out.alloc_size);
2589 0 : CHECK_EQUAL(out.size);
2590 0 : CHECK_ATTRIB(out.file_attr);
2591 0 : CHECK_EQUAL(out.reserved2);
2592 0 : CHECK_EQUAL(out.maximal_access);
2593 :
2594 : /* ntcreatex creates a new file handle */
2595 0 : ADD_HANDLE_SMB2(parm[0].in.fname, out.file.handle);
2596 :
2597 0 : return true;
2598 : }
2599 :
2600 : /*
2601 : generate close operations
2602 : */
2603 0 : static bool handler_smb2_close(int instance)
2604 : {
2605 : struct smb2_close parm[NSERVERS];
2606 : NTSTATUS status[NSERVERS];
2607 :
2608 0 : ZERO_STRUCT(parm[0]);
2609 0 : parm[0].in.file.handle.data[0] = gen_fnum_close(instance);
2610 0 : parm[0].in.flags = gen_bits_mask2(0x1, 0xFFFF);
2611 :
2612 0 : GEN_COPY_PARM;
2613 0 : GEN_SET_FNUM_SMB2(in.file.handle);
2614 0 : GEN_CALL_SMB2(smb2_close(tree, &parm[i]));
2615 :
2616 0 : CHECK_EQUAL(out.flags);
2617 0 : CHECK_EQUAL(out._pad);
2618 0 : CHECK_NTTIMES_EQUAL(out.create_time);
2619 0 : CHECK_NTTIMES_EQUAL(out.access_time);
2620 0 : CHECK_NTTIMES_EQUAL(out.write_time);
2621 0 : CHECK_NTTIMES_EQUAL(out.change_time);
2622 0 : CHECK_EQUAL(out.alloc_size);
2623 0 : CHECK_EQUAL(out.size);
2624 0 : CHECK_ATTRIB(out.file_attr);
2625 :
2626 0 : REMOVE_HANDLE_SMB2(in.file.handle);
2627 :
2628 0 : return true;
2629 : }
2630 :
2631 : /*
2632 : generate read operations
2633 : */
2634 0 : static bool handler_smb2_read(int instance)
2635 : {
2636 : struct smb2_read parm[NSERVERS];
2637 : NTSTATUS status[NSERVERS];
2638 :
2639 0 : parm[0].in.file.handle.data[0] = gen_fnum(instance);
2640 0 : parm[0].in.reserved = gen_reserved8();
2641 0 : parm[0].in.length = gen_io_count();
2642 0 : parm[0].in.offset = gen_offset();
2643 0 : parm[0].in.min_count = gen_io_count();
2644 0 : parm[0].in.channel = gen_bits_mask2(0x0, 0xFFFFFFFF);
2645 0 : parm[0].in.remaining = gen_bits_mask2(0x0, 0xFFFFFFFF);
2646 0 : parm[0].in.channel_offset = gen_bits_mask2(0x0, 0xFFFF);
2647 0 : parm[0].in.channel_length = gen_bits_mask2(0x0, 0xFFFF);
2648 :
2649 0 : GEN_COPY_PARM;
2650 0 : GEN_SET_FNUM_SMB2(in.file.handle);
2651 0 : GEN_CALL_SMB2(smb2_read(tree, current_op.mem_ctx, &parm[i]));
2652 :
2653 0 : CHECK_EQUAL(out.remaining);
2654 0 : CHECK_EQUAL(out.reserved);
2655 0 : CHECK_EQUAL(out.data.length);
2656 :
2657 0 : return true;
2658 : }
2659 :
2660 : /*
2661 : generate write operations
2662 : */
2663 0 : static bool handler_smb2_write(int instance)
2664 : {
2665 : struct smb2_write parm[NSERVERS];
2666 : NTSTATUS status[NSERVERS];
2667 :
2668 0 : parm[0].in.file.handle.data[0] = gen_fnum(instance);
2669 0 : parm[0].in.offset = gen_offset();
2670 0 : parm[0].in.unknown1 = gen_bits_mask2(0, 0xFFFFFFFF);
2671 0 : parm[0].in.unknown2 = gen_bits_mask2(0, 0xFFFFFFFF);
2672 0 : parm[0].in.data = data_blob_talloc(current_op.mem_ctx, NULL,
2673 : gen_io_count());
2674 :
2675 0 : GEN_COPY_PARM;
2676 0 : GEN_SET_FNUM_SMB2(in.file.handle);
2677 0 : GEN_CALL_SMB2(smb2_write(tree, &parm[i]));
2678 :
2679 0 : CHECK_EQUAL(out._pad);
2680 0 : CHECK_EQUAL(out.nwritten);
2681 0 : CHECK_EQUAL(out.unknown1);
2682 :
2683 0 : return true;
2684 : }
2685 :
2686 : /*
2687 : generate lockingx operations
2688 : */
2689 0 : static bool handler_smb2_lock(int instance)
2690 : {
2691 : struct smb2_lock parm[NSERVERS];
2692 : NTSTATUS status[NSERVERS];
2693 : int n;
2694 :
2695 0 : parm[0].level = RAW_LOCK_LOCKX;
2696 0 : parm[0].in.file.handle.data[0] = gen_fnum(instance);
2697 0 : parm[0].in.lock_count = gen_lock_count();
2698 0 : parm[0].in.lock_sequence = gen_reserved32();
2699 :
2700 0 : parm[0].in.locks = talloc_array(current_op.mem_ctx,
2701 : struct smb2_lock_element,
2702 : parm[0].in.lock_count);
2703 0 : for (n=0;n<parm[0].in.lock_count;n++) {
2704 0 : parm[0].in.locks[n].offset = gen_offset();
2705 0 : parm[0].in.locks[n].length = gen_io_count();
2706 : /* don't yet cope with async replies */
2707 0 : parm[0].in.locks[n].flags = gen_lock_flags_smb2() |
2708 : SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
2709 0 : parm[0].in.locks[n].reserved = gen_bits_mask2(0x0, 0xFFFFFFFF);
2710 : }
2711 :
2712 0 : GEN_COPY_PARM;
2713 0 : GEN_SET_FNUM_SMB2(in.file.handle);
2714 0 : GEN_CALL_SMB2(smb2_lock(tree, &parm[i]));
2715 :
2716 0 : return true;
2717 : }
2718 :
2719 : /*
2720 : generate flush operations
2721 : */
2722 0 : static bool handler_smb2_flush(int instance)
2723 : {
2724 : struct smb2_flush parm[NSERVERS];
2725 : NTSTATUS status[NSERVERS];
2726 :
2727 0 : ZERO_STRUCT(parm[0]);
2728 0 : parm[0].in.file.handle.data[0] = gen_fnum(instance);
2729 0 : parm[0].in.reserved1 = gen_reserved16();
2730 0 : parm[0].in.reserved2 = gen_reserved32();
2731 :
2732 0 : GEN_COPY_PARM;
2733 0 : GEN_SET_FNUM_SMB2(in.file.handle);
2734 0 : GEN_CALL_SMB2(smb2_flush(tree, &parm[i]));
2735 :
2736 0 : CHECK_EQUAL(out.reserved);
2737 :
2738 0 : return true;
2739 : }
2740 :
2741 : /*
2742 : generate echo operations
2743 : */
2744 0 : static bool handler_smb2_echo(int instance)
2745 : {
2746 : NTSTATUS status[NSERVERS];
2747 :
2748 0 : GEN_CALL_SMB2(smb2_keepalive(tree->session->transport));
2749 :
2750 0 : return true;
2751 : }
2752 :
2753 :
2754 :
2755 : /*
2756 : generate a fileinfo query structure
2757 : */
2758 0 : static void gen_fileinfo_smb2(int instance, union smb_fileinfo *info)
2759 : {
2760 : int i;
2761 : #define LVL(v) {RAW_FILEINFO_ ## v, "RAW_FILEINFO_" #v}
2762 : struct {
2763 : enum smb_fileinfo_level level;
2764 : const char *name;
2765 0 : } levels[] = {
2766 : LVL(BASIC_INFORMATION),
2767 : LVL(STANDARD_INFORMATION), LVL(INTERNAL_INFORMATION), LVL(EA_INFORMATION),
2768 : LVL(ACCESS_INFORMATION), LVL(NAME_INFORMATION), LVL(POSITION_INFORMATION),
2769 : LVL(MODE_INFORMATION), LVL(ALIGNMENT_INFORMATION), LVL(SMB2_ALL_INFORMATION),
2770 : LVL(ALT_NAME_INFORMATION), LVL(STREAM_INFORMATION), LVL(COMPRESSION_INFORMATION),
2771 : LVL(NETWORK_OPEN_INFORMATION), LVL(ATTRIBUTE_TAG_INFORMATION),
2772 : LVL(SMB2_ALL_EAS), LVL(SMB2_ALL_INFORMATION), LVL(SEC_DESC),
2773 : };
2774 : do {
2775 0 : i = gen_int_range(0, ARRAY_SIZE(levels)-1);
2776 0 : } while (ignore_pattern(levels[i].name));
2777 :
2778 0 : info->generic.level = levels[i].level;
2779 0 : }
2780 :
2781 : /*
2782 : generate qfileinfo operations
2783 : */
2784 0 : static bool handler_smb2_qfileinfo(int instance)
2785 : {
2786 : union smb_fileinfo parm[NSERVERS];
2787 : NTSTATUS status[NSERVERS];
2788 :
2789 0 : parm[0].generic.in.file.handle.data[0] = gen_fnum(instance);
2790 :
2791 0 : gen_fileinfo_smb2(instance, &parm[0]);
2792 :
2793 0 : GEN_COPY_PARM;
2794 0 : GEN_SET_FNUM_SMB2(generic.in.file.handle);
2795 0 : GEN_CALL_SMB2(smb2_getinfo_file(tree, current_op.mem_ctx, &parm[i]));
2796 :
2797 0 : return cmp_fileinfo(instance, parm, status);
2798 : }
2799 :
2800 :
2801 : /*
2802 : generate setfileinfo operations
2803 : */
2804 0 : static bool handler_smb2_sfileinfo(int instance)
2805 : {
2806 : union smb_setfileinfo parm[NSERVERS];
2807 : NTSTATUS status[NSERVERS];
2808 :
2809 0 : gen_setfileinfo(instance, &parm[0]);
2810 0 : parm[0].generic.in.file.fnum = gen_fnum(instance);
2811 :
2812 0 : GEN_COPY_PARM;
2813 0 : GEN_SET_FNUM_SMB2(generic.in.file.handle);
2814 0 : GEN_CALL_SMB2(smb2_setinfo_file(tree, &parm[i]));
2815 :
2816 0 : return true;
2817 : }
2818 :
2819 : /*
2820 : wipe any relevant files
2821 : */
2822 1 : static void wipe_files(void)
2823 : {
2824 : int i;
2825 : NTSTATUS status;
2826 :
2827 1 : if (options.skip_cleanup) {
2828 0 : return;
2829 : }
2830 :
2831 3 : for (i=0;i<NSERVERS;i++) {
2832 : int n;
2833 2 : if (options.smb2) {
2834 0 : n = smb2_deltree(servers[i].smb2_tree[0], "gentest");
2835 : } else {
2836 2 : n = smbcli_deltree(servers[i].smb_tree[0], "gentest");
2837 : }
2838 2 : if (n == -1) {
2839 0 : printf("Failed to wipe tree on server %d\n", i);
2840 0 : exit(1);
2841 : }
2842 2 : if (options.smb2) {
2843 0 : status = smb2_util_mkdir(servers[i].smb2_tree[0], "gentest");
2844 : } else {
2845 2 : status = smbcli_mkdir(servers[i].smb_tree[0], "gentest");
2846 : }
2847 2 : if (NT_STATUS_IS_ERR(status)) {
2848 0 : printf("Failed to create gentest on server %d - %s\n", i, nt_errstr(status));
2849 0 : exit(1);
2850 : }
2851 2 : if (n > 0) {
2852 0 : printf("Deleted %d files on server %d\n", n, i);
2853 : }
2854 : }
2855 : }
2856 :
2857 : /*
2858 : dump the current seeds - useful for continuing a backtrack
2859 : */
2860 1 : static void dump_seeds(void)
2861 : {
2862 : int i;
2863 : FILE *f;
2864 :
2865 1 : if (!options.seeds_file) {
2866 0 : return;
2867 : }
2868 1 : f = fopen("seeds.tmp", "w");
2869 1 : if (!f) return;
2870 :
2871 101 : for (i=0;i<options.numops;i++) {
2872 100 : fprintf(f, "%u\n", op_parms[i].seed);
2873 : }
2874 1 : fclose(f);
2875 1 : rename("seeds.tmp", options.seeds_file);
2876 : }
2877 :
2878 :
2879 :
2880 : /*
2881 : the list of top-level operations that we will generate
2882 : */
2883 : static struct {
2884 : const char *name;
2885 : bool (*handler)(int instance);
2886 : bool smb2;
2887 : int count, success_count;
2888 : } gen_ops[] = {
2889 : {
2890 : .name = "CREATE",
2891 : .handler = handler_smb2_create,
2892 : .smb2 = true,
2893 : },
2894 : {
2895 : .name = "CLOSE",
2896 : .handler = handler_smb2_close,
2897 : .smb2 = true,
2898 : },
2899 : {
2900 : .name = "READ",
2901 : .handler = handler_smb2_read,
2902 : .smb2 = true,
2903 : },
2904 : {
2905 : .name = "WRITE",
2906 : .handler = handler_smb2_write,
2907 : .smb2 = true,
2908 : },
2909 : {
2910 : .name = "LOCK",
2911 : .handler = handler_smb2_lock,
2912 : .smb2 = true,
2913 : },
2914 : {
2915 : .name = "FLUSH",
2916 : .handler = handler_smb2_flush,
2917 : .smb2 = true,
2918 : },
2919 : {
2920 : .name = "ECHO",
2921 : .handler = handler_smb2_echo,
2922 : .smb2 = true,
2923 : },
2924 : {
2925 : .name = "QFILEINFO",
2926 : .handler = handler_smb2_qfileinfo,
2927 : .smb2 = true,
2928 : },
2929 : {
2930 : .name = "SFILEINFO",
2931 : .handler = handler_smb2_sfileinfo,
2932 : .smb2 = true,
2933 : },
2934 :
2935 : {
2936 : .name = "OPEN",
2937 : .handler = handler_smb_open,
2938 : .smb2 = false,
2939 : },
2940 : {
2941 : .name = "OPENX",
2942 : .handler = handler_smb_openx,
2943 : .smb2 = false,
2944 : },
2945 : {
2946 : .name = "NTCREATEX",
2947 : .handler = handler_smb_ntcreatex,
2948 : .smb2 = false,
2949 : },
2950 : {
2951 : .name = "CLOSE",
2952 : .handler = handler_smb_close,
2953 : .smb2 = false,
2954 : },
2955 : {
2956 : .name = "UNLINK",
2957 : .handler = handler_smb_unlink,
2958 : .smb2 = false,
2959 : },
2960 : {
2961 : .name = "MKDIR",
2962 : .handler = handler_smb_mkdir,
2963 : .smb2 = false,
2964 : },
2965 : {
2966 : .name = "RMDIR",
2967 : .handler = handler_smb_rmdir,
2968 : .smb2 = false,
2969 : },
2970 : {
2971 : .name = "RENAME",
2972 : .handler = handler_smb_rename,
2973 : .smb2 = false,
2974 : },
2975 : {
2976 : .name = "NTRENAME",
2977 : .handler = handler_smb_ntrename,
2978 : .smb2 = false,
2979 : },
2980 : {
2981 : .name = "READX",
2982 : .handler = handler_smb_readx,
2983 : .smb2 = false,
2984 : },
2985 : {
2986 : .name = "WRITEX",
2987 : .handler = handler_smb_writex,
2988 : .smb2 = false,
2989 : },
2990 : {
2991 : .name = "CHKPATH",
2992 : .handler = handler_smb_chkpath,
2993 : .smb2 = false,
2994 : },
2995 : {
2996 : .name = "SEEK",
2997 : .handler = handler_smb_seek,
2998 : .smb2 = false,
2999 : },
3000 : {
3001 : .name = "LOCKINGX",
3002 : .handler = handler_smb_lockingx,
3003 : .smb2 = false,
3004 : },
3005 : {
3006 : .name = "QPATHINFO",
3007 : .handler = handler_smb_qpathinfo,
3008 : .smb2 = false,
3009 : },
3010 : {
3011 : .name = "QFILEINFO",
3012 : .handler = handler_smb_qfileinfo,
3013 : .smb2 = false,
3014 : },
3015 : {
3016 : .name = "SPATHINFO",
3017 : .handler = handler_smb_spathinfo,
3018 : .smb2 = false,
3019 : },
3020 : {
3021 : .name = "SFILEINFO",
3022 : .handler = handler_smb_sfileinfo,
3023 : .smb2 = false,
3024 : },
3025 : {
3026 : .name = "NOTIFY",
3027 : .handler = handler_smb_notify,
3028 : .smb2 = false,
3029 : },
3030 : };
3031 :
3032 :
3033 : /*
3034 : run the test with the current set of op_parms parameters
3035 : return the number of operations that completed successfully
3036 : */
3037 1 : static int run_test(struct tevent_context *ev, struct loadparm_context *lp_ctx)
3038 : {
3039 : int op, i;
3040 :
3041 1 : if (!connect_servers(ev, lp_ctx)) {
3042 0 : printf("Failed to connect to servers\n");
3043 0 : exit(1);
3044 : }
3045 :
3046 1 : dump_seeds();
3047 :
3048 : /* wipe any leftover files from old runs */
3049 1 : wipe_files();
3050 :
3051 : /* reset the open handles array */
3052 1 : memset(open_handles, 0, options.max_open_handles * sizeof(open_handles[0]));
3053 1 : num_open_handles = 0;
3054 :
3055 : /* reset the counts from previous runs */
3056 29 : for (i=0;i<ARRAY_SIZE(gen_ops);i++) {
3057 28 : gen_ops[i].count = 0;
3058 28 : gen_ops[i].success_count = 0;
3059 : }
3060 :
3061 101 : for (op=0; op<options.numops; op++) {
3062 : int instance, which_op;
3063 : bool ret;
3064 :
3065 100 : if (op_parms[op].disabled) continue;
3066 :
3067 100 : srandom(op_parms[op].seed);
3068 :
3069 100 : instance = gen_int_range(0, NINSTANCES-1);
3070 :
3071 : /* generate a non-ignored operation */
3072 : do {
3073 146 : which_op = gen_int_range(0, ARRAY_SIZE(gen_ops)-1);
3074 146 : } while (ignore_pattern(gen_ops[which_op].name) ||
3075 146 : gen_ops[which_op].smb2 != options.smb2);
3076 :
3077 100 : DEBUG(3,("Generating op %s on instance %d\n",
3078 : gen_ops[which_op].name, instance));
3079 :
3080 100 : current_op.seed = op_parms[op].seed;
3081 100 : current_op.opnum = op;
3082 100 : current_op.name = gen_ops[which_op].name;
3083 100 : current_op.status = NT_STATUS_OK;
3084 100 : talloc_free(current_op.mem_ctx);
3085 100 : current_op.mem_ctx = talloc_named(NULL, 0, "%s", current_op.name);
3086 :
3087 100 : ret = gen_ops[which_op].handler(instance);
3088 :
3089 100 : gen_ops[which_op].count++;
3090 100 : if (NT_STATUS_IS_OK(current_op.status)) {
3091 32 : gen_ops[which_op].success_count++;
3092 : }
3093 :
3094 100 : if (!ret) {
3095 0 : printf("Failed at operation %d - %s\n",
3096 : op, gen_ops[which_op].name);
3097 0 : return op;
3098 : }
3099 :
3100 100 : if (op % 100 == 0) {
3101 1 : printf("%d\n", op);
3102 : }
3103 : }
3104 :
3105 29 : for (i=0;i<ARRAY_SIZE(gen_ops);i++) {
3106 28 : printf("Op %-10s got %d/%d success\n",
3107 : gen_ops[i].name,
3108 : gen_ops[i].success_count,
3109 : gen_ops[i].count);
3110 : }
3111 :
3112 1 : return op;
3113 : }
3114 :
3115 : /*
3116 : perform a backtracking analysis of the minimal set of operations
3117 : to generate an error
3118 : */
3119 0 : static void backtrack_analyze(struct tevent_context *ev,
3120 : struct loadparm_context *lp_ctx)
3121 : {
3122 : int chunk, ret;
3123 0 : const char *mismatch = current_op.mismatch;
3124 :
3125 0 : chunk = options.numops / 2;
3126 :
3127 : do {
3128 : int base;
3129 0 : for (base=0;
3130 0 : chunk > 0 && base+chunk < options.numops && options.numops > 1; ) {
3131 : int i, max;
3132 :
3133 0 : chunk = MIN(chunk, options.numops / 2);
3134 :
3135 : /* mark this range as disabled */
3136 0 : max = MIN(options.numops, base+chunk);
3137 0 : for (i=base;i<max; i++) {
3138 0 : op_parms[i].disabled = true;
3139 : }
3140 0 : printf("Testing %d ops with %d-%d disabled\n",
3141 : options.numops, base, max-1);
3142 0 : ret = run_test(ev, lp_ctx);
3143 0 : printf("Completed %d of %d ops\n", ret, options.numops);
3144 0 : for (i=base;i<max; i++) {
3145 0 : op_parms[i].disabled = false;
3146 : }
3147 0 : if (ret == options.numops) {
3148 : /* this chunk is needed */
3149 0 : base += chunk;
3150 0 : } else if (mismatch != current_op.mismatch &&
3151 0 : strcmp(mismatch, current_op.mismatch)) {
3152 0 : base += chunk;
3153 0 : printf("Different error in backtracking\n");
3154 0 : } else if (ret < base) {
3155 0 : printf("damn - inconsistent errors! found early error\n");
3156 0 : options.numops = ret+1;
3157 0 : base = 0;
3158 : } else {
3159 : /* it failed - this chunk isn't needed for a failure */
3160 0 : memmove(&op_parms[base], &op_parms[max],
3161 0 : sizeof(op_parms[0]) * (options.numops - max));
3162 0 : options.numops = (ret+1) - (max - base);
3163 : }
3164 : }
3165 :
3166 0 : if (chunk == 2) {
3167 0 : chunk = 1;
3168 : } else {
3169 0 : chunk *= 0.4;
3170 : }
3171 :
3172 0 : if (options.analyze_continuous && chunk == 0 && options.numops != 1) {
3173 0 : chunk = 1;
3174 : }
3175 0 : } while (chunk > 0);
3176 :
3177 0 : printf("Reduced to %d ops\n", options.numops);
3178 0 : ret = run_test(ev, lp_ctx);
3179 0 : if (ret != options.numops - 1) {
3180 0 : printf("Inconsistent result? ret=%d numops=%d\n", ret, options.numops);
3181 : }
3182 0 : }
3183 :
3184 : /*
3185 : start the main gentest process
3186 : */
3187 1 : static bool start_gentest(struct tevent_context *ev,
3188 : struct loadparm_context *lp_ctx)
3189 : {
3190 : int op;
3191 : int ret;
3192 :
3193 : /* allocate the open_handles array */
3194 1 : open_handles = calloc(options.max_open_handles, sizeof(open_handles[0]));
3195 1 : if (open_handles == NULL) {
3196 0 : printf("Unable to allocate memory for open_handles array.\n");
3197 0 : exit(1);
3198 : }
3199 :
3200 1 : srandom(options.seed);
3201 1 : op_parms = calloc(options.numops, sizeof(op_parms[0]));
3202 1 : if (op_parms == NULL) {
3203 0 : printf("Unable to allocate memory for op_parms.\n");
3204 0 : exit(1);
3205 : }
3206 :
3207 : /* generate the seeds - after this everything is deterministic */
3208 1 : if (options.use_preset_seeds) {
3209 : int numops;
3210 0 : char **preset = file_lines_load(options.seeds_file, &numops, 0, NULL);
3211 0 : if (!preset) {
3212 0 : printf("Failed to load %s - %s\n", options.seeds_file, strerror(errno));
3213 0 : exit(1);
3214 : }
3215 0 : if (numops < options.numops) {
3216 0 : options.numops = numops;
3217 : }
3218 0 : for (op=0;op<options.numops;op++) {
3219 0 : if (!preset[op]) {
3220 0 : printf("Not enough seeds in %s\n", options.seeds_file);
3221 0 : exit(1);
3222 : }
3223 0 : op_parms[op].seed = atoi(preset[op]);
3224 : }
3225 0 : printf("Loaded %d seeds from %s\n", options.numops, options.seeds_file);
3226 : } else {
3227 101 : for (op=0; op<options.numops; op++) {
3228 100 : op_parms[op].seed = random();
3229 : }
3230 : }
3231 :
3232 1 : ret = run_test(ev, lp_ctx);
3233 :
3234 1 : if (ret != options.numops && options.analyze) {
3235 0 : options.numops = ret+1;
3236 0 : backtrack_analyze(ev, lp_ctx);
3237 1 : } else if (options.analyze_always) {
3238 0 : backtrack_analyze(ev, lp_ctx);
3239 1 : } else if (options.analyze_continuous) {
3240 0 : while (run_test(ev, lp_ctx) == options.numops) ;
3241 : }
3242 :
3243 1 : return ret == options.numops;
3244 : }
3245 :
3246 :
3247 0 : static void usage(poptContext pc)
3248 : {
3249 0 : printf(
3250 : "Usage:\n\
3251 : gentest //server1/share1 //server2/share2 [options..]\n\
3252 : ");
3253 0 : poptPrintUsage(pc, stdout, 0);
3254 0 : }
3255 :
3256 : /**
3257 : split a UNC name into server and share names
3258 : */
3259 2 : static bool split_unc_name(const char *unc, char **server, char **share)
3260 : {
3261 2 : char *p = strdup(unc);
3262 2 : if (!p) return false;
3263 2 : all_string_sub(p, "\\", "/", 0);
3264 2 : if (strncmp(p, "//", 2) != 0) return false;
3265 :
3266 2 : (*server) = p+2;
3267 2 : p = strchr(*server, '/');
3268 2 : if (!p) return false;
3269 :
3270 2 : *p = 0;
3271 2 : (*share) = p+1;
3272 :
3273 2 : return true;
3274 : }
3275 :
3276 :
3277 :
3278 : /****************************************************************************
3279 : main program
3280 : ****************************************************************************/
3281 1 : int main(int argc, const char *argv[])
3282 : {
3283 : int opt;
3284 1 : int i, username_count=0;
3285 : bool ret;
3286 1 : char *ignore_file=NULL;
3287 : struct tevent_context *ev;
3288 : struct loadparm_context *lp_ctx;
3289 : poptContext pc;
3290 : int argc_new;
3291 : char **argv_new;
3292 : enum {
3293 : OPT_UNCLIST=1000,
3294 : OPT_USER1,
3295 : OPT_USER2,
3296 : };
3297 6 : struct poptOption long_options[] = {
3298 : POPT_AUTOHELP
3299 : {"smb2", 0, POPT_ARG_NONE, &options.smb2, 0, "use SMB2 protocol", NULL},
3300 : {"seed", 0, POPT_ARG_INT, &options.seed, 0, "Seed to use for randomizer", NULL},
3301 : {"num-ops", 0, POPT_ARG_INT, &options.numops, 0, "num ops", NULL},
3302 : {"oplocks", 0, POPT_ARG_NONE, &options.use_oplocks,0, "use oplocks", NULL},
3303 : {"showall", 0, POPT_ARG_NONE, &options.showall, 0, "display all operations", NULL},
3304 : {"analyse", 0, POPT_ARG_NONE, &options.analyze, 0, "do backtrack analysis", NULL},
3305 : {"analysealways", 0, POPT_ARG_NONE, &options.analyze_always, 0, "analysis always", NULL},
3306 : {"analysecontinuous", 0, POPT_ARG_NONE, &options.analyze_continuous, 0, "analysis continuous", NULL},
3307 : {"ignore", 0, POPT_ARG_STRING, &ignore_file, 0, "ignore from file", NULL},
3308 : {"preset", 0, POPT_ARG_NONE, &options.use_preset_seeds, 0, "use preset seeds", NULL},
3309 : {"fast", 0, POPT_ARG_NONE, &options.fast_reconnect, 0, "use fast reconnect", NULL},
3310 : {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
3311 : {"seedsfile", 0, POPT_ARG_STRING, &options.seeds_file, 0, "seed file", NULL},
3312 : {"user1", 0, POPT_ARG_STRING, NULL, OPT_USER1, "Set first network username", "[DOMAIN/]USERNAME[%PASSWORD]" },
3313 : {"user2", 0, POPT_ARG_STRING, NULL, OPT_USER2, "Set second network username", "[DOMAIN/]USERNAME[%PASSWORD]" },
3314 : {"maskindexing", 0, POPT_ARG_NONE, &options.mask_indexing, 0, "mask out the indexed file attrib", NULL},
3315 : {"noeas", 0, POPT_ARG_NONE, &options.no_eas, 0, "don't use extended attributes", NULL},
3316 : {"noacls", 0, POPT_ARG_NONE, &options.no_acls, 0, "don't use ACLs", NULL},
3317 : {"skip-cleanup", 0, POPT_ARG_NONE, &options.skip_cleanup, 0, "don't delete files at start", NULL},
3318 : {"valid", 0, POPT_ARG_NONE, &options.valid, 0, "generate only valid fields", NULL},
3319 1 : POPT_COMMON_SAMBA
3320 1 : POPT_COMMON_CONNECTION
3321 1 : POPT_COMMON_CREDENTIALS
3322 1 : POPT_COMMON_VERSION
3323 1 : POPT_LEGACY_S4
3324 : POPT_TABLEEND
3325 : };
3326 1 : TALLOC_CTX *mem_ctx = NULL;
3327 : bool ok;
3328 :
3329 1 : memset(&bad_smb2_handle, 0xFF, sizeof(bad_smb2_handle));
3330 :
3331 1 : setlinebuf(stdout);
3332 1 : options.seed = time(NULL);
3333 1 : options.numops = 1000;
3334 1 : options.max_open_handles = 20;
3335 1 : options.seeds_file = "gentest_seeds.dat";
3336 :
3337 1 : mem_ctx = talloc_named_const(NULL, 0, "gentest_ctx");
3338 1 : if (mem_ctx == NULL) {
3339 0 : printf("Unable to allocate gentest_ctx\n");
3340 0 : exit(1);
3341 : }
3342 :
3343 1 : ok = samba_cmdline_init(mem_ctx,
3344 : SAMBA_CMDLINE_CONFIG_CLIENT,
3345 : false /* require_smbconf */);
3346 1 : if (!ok) {
3347 0 : DBG_ERR("Failed to init cmdline parser!\n");
3348 0 : TALLOC_FREE(mem_ctx);
3349 0 : exit(1);
3350 : }
3351 :
3352 1 : pc = samba_popt_get_context(getprogname(),
3353 : argc,
3354 : argv,
3355 : long_options,
3356 : POPT_CONTEXT_KEEP_FIRST);
3357 1 : if (pc == NULL) {
3358 0 : DBG_ERR("Failed to setup popt context!\n");
3359 0 : TALLOC_FREE(mem_ctx);
3360 0 : exit(1);
3361 : }
3362 :
3363 1 : poptSetOtherOptionHelp(pc, "<unc1> <unc2>");
3364 :
3365 1 : lp_ctx = samba_cmdline_get_lp_ctx();
3366 1 : servers[0].credentials = cli_credentials_init(mem_ctx);
3367 1 : servers[1].credentials = cli_credentials_init(mem_ctx);
3368 1 : cli_credentials_guess(servers[0].credentials, lp_ctx);
3369 1 : cli_credentials_guess(servers[1].credentials, lp_ctx);
3370 :
3371 3 : while((opt = poptGetNextOpt(pc)) != -1) {
3372 2 : switch (opt) {
3373 0 : case OPT_UNCLIST:
3374 0 : lpcfg_set_cmdline(lp_ctx, "torture:unclist", poptGetOptArg(pc));
3375 0 : break;
3376 1 : case OPT_USER1:
3377 1 : cli_credentials_parse_string(servers[0].credentials,
3378 1 : poptGetOptArg(pc),
3379 : CRED_SPECIFIED);
3380 1 : username_count++;
3381 1 : break;
3382 1 : case OPT_USER2:
3383 1 : cli_credentials_parse_string(servers[1].credentials,
3384 1 : poptGetOptArg(pc),
3385 : CRED_SPECIFIED);
3386 1 : username_count++;
3387 1 : break;
3388 0 : case POPT_ERROR_BADOPT:
3389 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
3390 : poptBadOption(pc, 0), poptStrerror(opt));
3391 0 : poptPrintUsage(pc, stderr, 0);
3392 0 : exit(1);
3393 : }
3394 : }
3395 :
3396 1 : if (ignore_file) {
3397 1 : options.ignore_patterns = file_lines_load(ignore_file, NULL, 0, NULL);
3398 : }
3399 :
3400 1 : argv_new = discard_const_p(char *, poptGetArgs(pc));
3401 1 : argc_new = argc;
3402 4 : for (i=0; i<argc; i++) {
3403 4 : if (argv_new[i] == NULL) {
3404 1 : argc_new = i;
3405 1 : break;
3406 : }
3407 : }
3408 :
3409 1 : if (!(argc_new >= 3)) {
3410 0 : usage(pc);
3411 0 : talloc_free(mem_ctx);
3412 0 : exit(1);
3413 : }
3414 :
3415 1 : setlinebuf(stdout);
3416 :
3417 1 : setup_logging("gentest", DEBUG_STDOUT);
3418 :
3419 1 : if (argc < 3 || argv[1][0] == '-') {
3420 0 : usage(pc);
3421 0 : talloc_free(mem_ctx);
3422 0 : exit(1);
3423 : }
3424 :
3425 1 : setup_logging(argv[0], DEBUG_STDOUT);
3426 :
3427 3 : for (i=0;i<NSERVERS;i++) {
3428 2 : const char *share = argv[1+i];
3429 2 : if (!split_unc_name(share, &servers[i].server_name, &servers[i].share_name)) {
3430 0 : printf("Invalid share name '%s'\n", share);
3431 0 : poptFreeContext(pc);
3432 0 : talloc_free(mem_ctx);
3433 0 : return -1;
3434 : }
3435 : }
3436 :
3437 1 : if (username_count == 0) {
3438 0 : usage(pc);
3439 0 : poptFreeContext(pc);
3440 0 : talloc_free(mem_ctx);
3441 0 : return -1;
3442 : }
3443 1 : if (username_count == 1) {
3444 0 : servers[1].credentials = servers[0].credentials;
3445 : }
3446 :
3447 1 : printf("seed=%u\n", options.seed);
3448 :
3449 1 : ev = s4_event_context_init(mem_ctx);
3450 :
3451 1 : gensec_init();
3452 :
3453 1 : ret = start_gentest(ev, lp_ctx);
3454 :
3455 1 : if (ret) {
3456 1 : printf("gentest completed - no errors\n");
3457 : } else {
3458 0 : printf("gentest failed\n");
3459 : }
3460 :
3461 1 : poptFreeContext(pc);
3462 1 : talloc_free(mem_ctx);
3463 1 : return ret?0:-1;
3464 : }
|