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 or ncacn_ip_tcp for RPC/TCP\n\n");
147 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
148 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
149 printf(" string.\n\n");
151 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
152 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
153 printf(" will be auto-determined.\n\n");
155 printf(" other recognised flags are:\n\n");
157 printf(" sign : enable ntlmssp signing\n");
158 printf(" seal : enable ntlmssp sealing\n");
159 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
160 printf(" validate: enable the NDR validator\n");
161 printf(" print: enable debugging of the packets\n");
162 printf(" bigendian: use bigendian RPC\n");
163 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
165 printf(" For example, these all connect to the samr pipe:\n\n");
167 printf(" ncacn_np:myserver\n");
168 printf(" ncacn_np:myserver[samr]\n");
169 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
170 printf(" ncacn_np:myserver[/pipe/samr]\n");
171 printf(" ncacn_np:myserver[samr,sign,print]\n");
172 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
173 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
174 printf(" ncacn_np:\n");
175 printf(" ncacn_np:[/pipe/samr]\n\n");
177 printf(" ncacn_ip_tcp:myserver\n");
178 printf(" ncacn_ip_tcp:myserver[1024]\n");
179 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
181 printf("The UNC format is:\n\n");
183 printf(" //server/share\n\n");
185 printf("Tests are:");
188 last_prefix[0] = '\0';
189 for (o = torture_ops; o; o = o->next) {
192 if ((sep = strchr(o->name, '-'))) {
193 if (strncmp(o->name, last_prefix, sep - o->name) != 0) {
194 strncpy(last_prefix, o->name,
195 MIN(sizeof(last_prefix),
202 if (i + strlen(o->name) >= (MAX_COLS - 2)) {
206 i+=printf("%s ", o->name);
210 printf("The default test is ALL.\n");
215 static BOOL is_binding_string(const char *binding_string)
217 TALLOC_CTX *mem_ctx = talloc_init("is_binding_string");
218 struct dcerpc_binding *binding_struct;
221 status = dcerpc_parse_binding(mem_ctx, binding_string, &binding_struct);
223 talloc_free(mem_ctx);
224 return NT_STATUS_IS_OK(status);
227 static void max_runtime_handler(int sig)
229 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
233 static void simple_test_start (struct torture_test *test)
235 printf("Testing %s...\n", test->name);
238 static void simple_test_result (struct torture_test *test, enum torture_result res)
240 printf("\t %d\n",res);
243 static void simple_comment (struct torture_test *test, const char *comment)
245 printf("# %s\n", comment);
248 const static struct torture_ui_ops std_ui_ops = {
249 .comment = simple_comment,
250 .test_start = simple_test_start,
251 .test_result = simple_test_result
254 /****************************************************************************
256 ****************************************************************************/
257 int main(int argc,char *argv[])
264 struct torture_context *torture;
267 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS,
268 OPT_DANGEROUS,OPT_SMB_PORTS};
270 struct poptOption long_options[] = {
272 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
273 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "seed", NULL},
274 {"num-progs", 0, POPT_ARG_INT, &torture_nprocs, 0, "num progs", NULL},
275 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
276 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
277 {"use-oplocks", 'L', POPT_ARG_NONE, &use_oplocks, 0, "use oplocks", NULL},
278 {"show-all", 0, POPT_ARG_NONE, &torture_showall, 0, "show all", NULL},
279 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "loadfile", NULL},
280 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
281 {"timelimit", 't', POPT_ARG_STRING, NULL, OPT_TIMELIMIT, "timelimit", NULL},
282 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
283 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
284 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS, "dangerous", NULL},
285 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
286 "set maximum time for smbtorture to live", "seconds"},
288 POPT_COMMON_CONNECTION
289 POPT_COMMON_CREDENTIALS
294 #ifdef HAVE_SETBUFFER
295 setbuffer(stdout, NULL, 0);
298 /* we are never interested in SIGPIPE */
299 BlockSignals(True,SIGPIPE);
301 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
302 POPT_CONTEXT_KEEP_FIRST);
304 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
306 while((opt = poptGetNextOpt(pc)) != -1) {
309 lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
312 lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
315 lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
318 parse_dns(poptGetOptArg(pc));
321 lp_set_cmdline("torture:dangerous", "Yes");
324 lp_set_cmdline("smb ports", poptGetOptArg(pc));
327 d_printf("Invalid option %s: %s\n",
328 poptBadOption(pc, 0), poptStrerror(opt));
336 /* this will only work if nobody else uses alarm(),
337 which means it won't work for some tests, but we
338 can't use the event context method we use for smbd
339 as so many tests create their own event
340 context. This will at least catch most cases. */
341 signal(SIGALRM, max_runtime_handler);
348 if (torture_seed == 0) {
349 torture_seed = time(NULL);
351 printf("Using seed %d\n", torture_seed);
352 srandom(torture_seed);
354 argv_new = discard_const_p(char *, poptGetArgs(pc));
357 for (i=0; i<argc; i++) {
358 if (argv_new[i] == NULL) {
369 for(p = argv_new[1]; *p; p++) {
374 /* see if its a RPC transport specifier */
375 if (is_binding_string(argv_new[1])) {
376 lp_set_cmdline("torture:binding", argv_new[1]);
378 char *binding = NULL;
379 char *host = NULL, *share = NULL;
381 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
382 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
386 lp_set_cmdline("torture:host", host);
387 lp_set_cmdline("torture:share", share);
388 asprintf(&binding, "ncacn_np:%s", host);
389 lp_set_cmdline("torture:binding", binding);
392 torture = talloc_zero(NULL, struct torture_context);
393 torture->ui_ops = &std_ui_ops;
396 printf("You must specify a test to run, or 'ALL'\n");
398 for (i=2;i<argc_new;i++) {
399 if (!run_test(torture, argv_new[i])) {
405 talloc_free(torture);