2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "lib/cmdline/popt_common.h"
24 #include "system/time.h"
25 #include "system/wait.h"
26 #include "system/filesys.h"
27 #include "libcli/libcli.h"
28 #include "lib/ldb/include/ldb.h"
29 #include "lib/events/events.h"
31 #include "torture/torture.h"
32 #include "torture/ui.h"
34 #include "dlinklist.h"
35 #include "librpc/rpc/dcerpc.h"
37 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
39 /****************************************************************************
40 run a specified test or "ALL"
41 ****************************************************************************/
42 static BOOL run_test(struct torture_context *torture, const char *name)
48 if (strequal(name,"ALL")) {
49 for (o = torture_ops; o; o = o->next) {
50 if (!run_test(torture, o->name)) {
57 for (o = torture_ops; o; o = o->next) {
58 if (gen_fnmatch(name, o->name) == 0) {
62 printf("Running %s\n", o->name);
65 t = torture_create_procs(o->multi_fn,
69 printf("TEST %s FAILED!\n", o->name);
73 struct timeval tv = timeval_current();
74 if (!o->fn(torture)) {
76 printf("TEST %s FAILED!\n", o->name);
78 t = timeval_elapsed(&tv);
80 printf("%s took %g secs\n\n", o->name, t);
85 printf("Unknown torture operation '%s'\n", name);
92 static void parse_dns(const char *dns)
94 char *userdn, *basedn, *secret;
97 /* retrievieng the userdn */
98 p = strchr_m(dns, '#');
100 lp_set_cmdline("torture:ldap_userdn", "");
101 lp_set_cmdline("torture:ldap_basedn", "");
102 lp_set_cmdline("torture:ldap_secret", "");
105 userdn = strndup(dns, p - dns);
106 lp_set_cmdline("torture:ldap_userdn", userdn);
108 /* retrieve the basedn */
110 p = strchr_m(d, '#');
112 lp_set_cmdline("torture:ldap_basedn", "");
113 lp_set_cmdline("torture:ldap_secret", "");
116 basedn = strndup(d, p - d);
117 lp_set_cmdline("torture:ldap_basedn", basedn);
119 /* retrieve the secret */
122 lp_set_cmdline("torture:ldap_secret", "");
126 lp_set_cmdline("torture:ldap_secret", secret);
128 printf ("%s - %s - %s\n", userdn, basedn, secret);
132 static void usage(poptContext pc)
134 struct torture_op *o;
135 char last_prefix[64];
138 poptPrintUsage(pc, stdout, 0);
141 printf("The binding format is:\n\n");
143 printf(" TRANSPORT:host[flags]\n\n");
145 printf(" where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
146 printf(" or ncalrpc for local connections.\n\n");
148 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
149 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
150 printf(" string.\n\n");
152 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
153 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
154 printf(" will be auto-determined.\n\n");
156 printf(" other recognised flags are:\n\n");
158 printf(" sign : enable ntlmssp signing\n");
159 printf(" seal : enable ntlmssp sealing\n");
160 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
161 printf(" validate: enable the NDR validator\n");
162 printf(" print: enable debugging of the packets\n");
163 printf(" bigendian: use bigendian RPC\n");
164 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
166 printf(" For example, these all connect to the samr pipe:\n\n");
168 printf(" ncacn_np:myserver\n");
169 printf(" ncacn_np:myserver[samr]\n");
170 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
171 printf(" ncacn_np:myserver[/pipe/samr]\n");
172 printf(" ncacn_np:myserver[samr,sign,print]\n");
173 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
174 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
175 printf(" ncacn_np:\n");
176 printf(" ncacn_np:[/pipe/samr]\n\n");
178 printf(" ncacn_ip_tcp:myserver\n");
179 printf(" ncacn_ip_tcp:myserver[1024]\n");
180 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
182 printf(" ncalrpc:\n\n");
184 printf("The UNC format is:\n\n");
186 printf(" //server/share\n\n");
188 printf("Tests are:");
191 last_prefix[0] = '\0';
192 for (o = torture_ops; o; o = o->next) {
195 if ((sep = strchr(o->name, '-'))) {
196 if (strncmp(o->name, last_prefix, sep - o->name) != 0) {
197 strncpy(last_prefix, o->name,
198 MIN(sizeof(last_prefix),
205 if (i + strlen(o->name) >= (MAX_COLS - 2)) {
209 i+=printf("%s ", o->name);
213 printf("The default test is ALL.\n");
218 static BOOL is_binding_string(const char *binding_string)
220 TALLOC_CTX *mem_ctx = talloc_init("is_binding_string");
221 struct dcerpc_binding *binding_struct;
224 status = dcerpc_parse_binding(mem_ctx, binding_string, &binding_struct);
226 talloc_free(mem_ctx);
227 return NT_STATUS_IS_OK(status);
230 static void max_runtime_handler(int sig)
232 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
236 static void simple_test_start (struct torture_test *test)
238 printf("Testing %s...\n", test->name);
241 static void simple_test_result (struct torture_test *test, enum torture_result res, const char *reason)
243 printf("\t %d: %s\n",res, reason?reason:"");
246 static void simple_comment (struct torture_test *test, const char *comment)
248 printf("# %s\n", comment);
251 const static struct torture_ui_ops std_ui_ops = {
252 .comment = simple_comment,
253 .test_start = simple_test_start,
254 .test_result = simple_test_result
258 static void subunit_test_start (struct torture_test *test)
260 printf("test: %s\n", test->name);
263 static void subunit_test_result (struct torture_test *test, enum torture_result res, const char *reason)
267 printf("success: %s\n", test->name);
270 printf("failure: %s [ %s ]\n", test->name, reason);
273 printf("todo: %s\n", test->name);
276 printf("skip: %s\n", test->name);
281 static void subunit_comment (struct torture_test *test, const char *comment)
283 printf("# %s\n", comment);
286 const static struct torture_ui_ops subunit_ui_ops = {
287 .comment = subunit_comment,
288 .test_start = subunit_test_start,
289 .test_result = subunit_test_result
292 static void harness_test_start (struct torture_test *test)
296 static void harness_test_result (struct torture_test *test, enum torture_result res, const char *reason)
300 printf("ok %s - %s\n", test->name, reason);
303 printf("not ok %s - %s\n", test->name, reason);
306 printf("todo %s - %s\n", test->name, reason);
309 printf("skip %s - %s\n", test->name, reason);
314 static void harness_comment (struct torture_test *test, const char *comment)
316 printf("# %s\n", comment);
319 const static struct torture_ui_ops harness_ui_ops = {
320 .comment = harness_comment,
321 .test_start = harness_test_start,
322 .test_result = harness_test_result
325 /****************************************************************************
327 ****************************************************************************/
328 int main(int argc,char *argv[])
335 struct torture_context *torture;
338 static char *ui_ops_name = "simple";
339 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS,
340 OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC};
342 struct poptOption long_options[] = {
344 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit, harness)", NULL },
345 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
346 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "seed", NULL},
347 {"num-progs", 0, POPT_ARG_INT, &torture_nprocs, 0, "num progs", NULL},
348 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
349 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
350 {"use-oplocks", 'L', POPT_ARG_NONE, &use_oplocks, 0, "use oplocks", NULL},
351 {"show-all", 0, POPT_ARG_NONE, &torture_showall, 0, "show all", NULL},
352 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "loadfile", NULL},
353 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
354 {"timelimit", 't', POPT_ARG_STRING, NULL, OPT_TIMELIMIT, "timelimit", NULL},
355 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
356 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
357 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS,
358 "run dangerous tests (eg. wiping out password database)", NULL},
359 {"async", 'a', POPT_ARG_NONE, NULL, OPT_ASYNC,
360 "run async tests", NULL},
361 {"num-async", 0, POPT_ARG_INT, &torture_numasync, 0,
362 "number of simultaneous async requests", NULL},
363 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
364 "set maximum time for smbtorture to live", "seconds"},
366 POPT_COMMON_CONNECTION
367 POPT_COMMON_CREDENTIALS
372 #ifdef HAVE_SETBUFFER
373 setbuffer(stdout, NULL, 0);
376 /* we are never interested in SIGPIPE */
377 BlockSignals(True,SIGPIPE);
379 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
380 POPT_CONTEXT_KEEP_FIRST);
382 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
384 while((opt = poptGetNextOpt(pc)) != -1) {
387 lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
390 lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
393 lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
396 parse_dns(poptGetOptArg(pc));
399 lp_set_cmdline("torture:dangerous", "Yes");
402 lp_set_cmdline("torture:async", "Yes");
405 lp_set_cmdline("smb ports", poptGetOptArg(pc));
408 d_printf("Invalid option %s: %s\n",
409 poptBadOption(pc, 0), poptStrerror(opt));
417 /* this will only work if nobody else uses alarm(),
418 which means it won't work for some tests, but we
419 can't use the event context method we use for smbd
420 as so many tests create their own event
421 context. This will at least catch most cases. */
422 signal(SIGALRM, max_runtime_handler);
429 if (torture_seed == 0) {
430 torture_seed = time(NULL);
432 printf("Using seed %d\n", torture_seed);
433 srandom(torture_seed);
435 argv_new = discard_const_p(char *, poptGetArgs(pc));
438 for (i=0; i<argc; i++) {
439 if (argv_new[i] == NULL) {
450 for(p = argv_new[1]; *p; p++) {
455 /* see if its a RPC transport specifier */
456 if (is_binding_string(argv_new[1])) {
457 lp_set_cmdline("torture:binding", argv_new[1]);
459 char *binding = NULL;
460 char *host = NULL, *share = NULL;
462 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
463 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
467 lp_set_cmdline("torture:host", host);
468 lp_set_cmdline("torture:share", share);
469 asprintf(&binding, "ncacn_np:%s", host);
470 lp_set_cmdline("torture:binding", binding);
473 torture = talloc_zero(NULL, struct torture_context);
474 if (!strcmp(ui_ops_name, "simple")) {
475 torture->ui_ops = &std_ui_ops;
476 } else if (!strcmp(ui_ops_name, "subunit")) {
477 torture->ui_ops = &subunit_ui_ops;
478 } else if (!strcmp(ui_ops_name, "harness")) {
479 torture->ui_ops = &harness_ui_ops;
481 printf("Unknown output format '%s'\n", ui_ops_name);
486 printf("You must specify a test to run, or 'ALL'\n");
488 for (i=2;i<argc_new;i++) {
489 if (!run_test(torture, argv_new[i])) {
495 talloc_free(torture);