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 "libcli/raw/libcliraw.h"
25 #include "system/time.h"
26 #include "system/wait.h"
27 #include "system/filesys.h"
28 #include "libcli/raw/ioctl.h"
29 #include "libcli/libcli.h"
30 #include "lib/ldb/include/ldb.h"
31 #include "lib/events/events.h"
32 #include "libcli/resolve/resolve.h"
33 #include "auth/credentials/credentials.h"
34 #include "libcli/ldap/ldap_client.h"
35 #include "librpc/gen_ndr/ndr_nbt.h"
37 #include "torture/raw/proto.h"
38 #include "torture/smb2/proto.h"
39 #include "torture/rap/proto.h"
40 #include "torture/auth/proto.h"
41 #include "torture/local/proto.h"
42 #include "torture/nbench/proto.h"
43 #include "torture/ldap/proto.h"
44 #include "torture/com/proto.h"
45 #include "torture/nbt/proto.h"
46 #include "torture/libnet/proto.h"
47 #include "torture/torture.h"
49 #include "dlinklist.h"
52 _PUBLIC_ int torture_numops=10;
53 _PUBLIC_ int torture_entries=1000;
54 _PUBLIC_ int torture_failures=1;
55 _PUBLIC_ int torture_seed=0;
56 static int procnum; /* records process count number when forking */
57 static struct smbcli_state *current_cli;
58 static BOOL use_oplocks;
59 static BOOL use_level_II_oplocks;
60 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
62 _PUBLIC_ BOOL torture_showall = False;
64 BOOL torture_open_connection_share(TALLOC_CTX *mem_ctx,
65 struct smbcli_state **c,
67 const char *sharename,
68 struct event_context *ev)
72 status = smbcli_full_connection(mem_ctx, c, hostname,
74 cmdline_credentials, ev);
75 if (!NT_STATUS_IS_OK(status)) {
76 printf("Failed to open connection - %s\n", nt_errstr(status));
80 (*c)->transport->options.use_oplocks = use_oplocks;
81 (*c)->transport->options.use_level2_oplocks = use_level_II_oplocks;
86 _PUBLIC_ BOOL torture_open_connection(struct smbcli_state **c)
88 const char *host = lp_parm_string(-1, "torture", "host");
89 const char *share = lp_parm_string(-1, "torture", "share");
91 return torture_open_connection_share(NULL, c, host, share, NULL);
96 _PUBLIC_ BOOL torture_close_connection(struct smbcli_state *c)
100 if (NT_STATUS_IS_ERR(smbcli_tdis(c))) {
101 printf("tdis failed (%s)\n", smbcli_errstr(c->tree));
109 /* check if the server produced the expected error code */
110 _PUBLIC_ BOOL check_error(const char *location, struct smbcli_state *c,
111 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
115 status = smbcli_nt_error(c->tree);
116 if (NT_STATUS_IS_DOS(status)) {
118 class = NT_STATUS_DOS_CLASS(status);
119 num = NT_STATUS_DOS_CODE(status);
120 if (eclass != class || ecode != num) {
121 printf("unexpected error code %s\n", nt_errstr(status));
122 printf(" expected %s or %s (at %s)\n",
123 nt_errstr(NT_STATUS_DOS(eclass, ecode)),
124 nt_errstr(nterr), location);
128 if (!NT_STATUS_EQUAL(nterr, status)) {
129 printf("unexpected error code %s\n", nt_errstr(status));
130 printf(" expected %s (at %s)\n", nt_errstr(nterr), location);
139 static BOOL wait_lock(struct smbcli_state *c, int fnum, uint32_t offset, uint32_t len)
141 while (NT_STATUS_IS_ERR(smbcli_lock(c->tree, fnum, offset, len, -1, WRITE_LOCK))) {
142 if (!check_error(__location__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
148 static BOOL rw_torture(struct smbcli_state *c)
150 const char *lockfname = "\\torture.lck";
154 pid_t pid2, pid = getpid();
159 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL,
162 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
164 printf("open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree));
169 for (i=0;i<torture_numops;i++) {
170 uint_t n = (uint_t)random()%10;
172 printf("%d\r", i); fflush(stdout);
174 asprintf(&fname, "\\torture.%u", n);
176 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
180 fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
182 printf("open failed (%s)\n", smbcli_errstr(c->tree));
187 if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) {
188 printf("write failed (%s)\n", smbcli_errstr(c->tree));
193 if (smbcli_write(c->tree, fnum, 0, buf,
194 sizeof(pid)+(j*sizeof(buf)),
195 sizeof(buf)) != sizeof(buf)) {
196 printf("write failed (%s)\n", smbcli_errstr(c->tree));
203 if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) {
204 printf("read failed (%s)\n", smbcli_errstr(c->tree));
209 printf("data corruption!\n");
213 if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
214 printf("close failed (%s)\n", smbcli_errstr(c->tree));
218 if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) {
219 printf("unlink failed (%s)\n", smbcli_errstr(c->tree));
223 if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
224 printf("unlock failed (%s)\n", smbcli_errstr(c->tree));
230 smbcli_close(c->tree, fnum2);
231 smbcli_unlink(c->tree, lockfname);
238 static BOOL run_torture(struct smbcli_state *cli, int dummy)
242 ret = rw_torture(cli);
244 if (!torture_close_connection(cli)) {
253 see how many RPC pipes we can open at once
255 static BOOL run_pipe_number(void)
257 struct smbcli_state *cli1;
258 const char *pipe_name = "\\WKSSVC";
262 printf("starting pipenumber test\n");
263 if (!torture_open_connection(&cli1)) {
268 fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
269 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
272 printf("Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
276 printf("%d\r", num_pipes);
280 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
281 torture_close_connection(cli1);
289 open N connections to the server and just hold them open
290 used for testing performance when there are N idle users
293 static BOOL torture_holdcon(void)
296 struct smbcli_state **cli;
299 printf("Opening %d connections\n", torture_numops);
301 cli = malloc_array_p(struct smbcli_state *, torture_numops);
303 for (i=0;i<torture_numops;i++) {
304 if (!torture_open_connection(&cli[i])) {
307 printf("opened %d connections\r", i);
311 printf("\nStarting pings\n");
314 for (i=0;i<torture_numops;i++) {
317 status = smbcli_chkpath(cli[i]->tree, "\\");
318 if (!NT_STATUS_IS_OK(status)) {
319 printf("Connection %d is dead\n", i);
327 if (num_dead == torture_numops) {
328 printf("All connections dead - finishing\n");
340 test how many open files this server supports on the one socket
342 static BOOL run_maxfidtest(struct smbcli_state *cli, int dummy)
344 #define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d"
346 int fnums[0x11000], i;
347 int retries=4, maxfid;
351 printf("failed to connect\n");
355 if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
356 printf("Failed to deltree \\maxfid - %s\n",
357 smbcli_errstr(cli->tree));
360 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) {
361 printf("Failed to mkdir \\maxfid, error=%s\n",
362 smbcli_errstr(cli->tree));
366 printf("Testing maximum number of open files\n");
368 for (i=0; i<0x11000; i++) {
370 asprintf(&fname, "\\maxfid\\fid%d", i/1000);
371 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) {
372 printf("Failed to mkdir %s, error=%s\n",
373 fname, smbcli_errstr(cli->tree));
378 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
379 if ((fnums[i] = smbcli_open(cli->tree, fname,
380 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
382 printf("open of %s failed (%s)\n",
383 fname, smbcli_errstr(cli->tree));
384 printf("maximum fnum is %d\n", i);
395 printf("cleaning up\n");
396 for (i=0;i<maxfid/2;i++) {
397 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
398 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) {
399 printf("Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree));
401 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
402 printf("unlink of %s failed (%s)\n",
403 fname, smbcli_errstr(cli->tree));
408 asprintf(&fname, MAXFID_TEMPLATE, (maxfid-i)/1000, maxfid-i,(int)getpid());
409 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[maxfid-i]))) {
410 printf("Close of fnum %d failed - %s\n", fnums[maxfid-i], smbcli_errstr(cli->tree));
412 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
413 printf("unlink of %s failed (%s)\n",
414 fname, smbcli_errstr(cli->tree));
419 printf("%6d %6d\r", i, maxfid-i);
423 if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
424 printf("Failed to deltree \\maxfid - %s\n",
425 smbcli_errstr(cli->tree));
429 printf("maxfid test finished\n");
430 if (!torture_close_connection(cli)) {
434 #undef MAXFID_TEMPLATE
440 sees what IOCTLs are supported
442 BOOL torture_ioctl_test(void)
444 struct smbcli_state *cli;
445 uint16_t device, function;
447 const char *fname = "\\ioctl.dat";
449 union smb_ioctl parms;
452 if (!torture_open_connection(&cli)) {
456 mem_ctx = talloc_init("ioctl_test");
458 printf("starting ioctl test\n");
460 smbcli_unlink(cli->tree, fname);
462 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
464 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
468 parms.ioctl.level = RAW_IOCTL_IOCTL;
469 parms.ioctl.in.file.fnum = fnum;
470 parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
471 status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
472 printf("ioctl job info: %s\n", smbcli_errstr(cli->tree));
474 for (device=0;device<0x100;device++) {
475 printf("testing device=0x%x\n", device);
476 for (function=0;function<0x100;function++) {
477 parms.ioctl.in.request = (device << 16) | function;
478 status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
480 if (NT_STATUS_IS_OK(status)) {
481 printf("ioctl device=0x%x function=0x%x OK : %d bytes\n",
482 device, function, (int)parms.ioctl.out.blob.length);
487 if (!torture_close_connection(cli)) {
495 static void sigcont(int sig)
499 double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result)
502 volatile pid_t *child_status;
503 volatile BOOL *child_status_out;
506 double start_time_limit = 10 + (torture_nprocs * 1.5);
507 char **unc_list = NULL;
509 int num_unc_names = 0;
516 signal(SIGCONT, sigcont);
518 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
520 printf("Failed to setup shared memory\n");
524 child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*torture_nprocs);
525 if (!child_status_out) {
526 printf("Failed to setup result status shared memory\n");
530 p = lp_parm_string(-1, "torture", "unclist");
532 unc_list = file_lines_load(p, &num_unc_names, NULL);
533 if (!unc_list || num_unc_names <= 0) {
534 printf("Failed to load unc names list from '%s'\n", p);
539 for (i = 0; i < torture_nprocs; i++) {
541 child_status_out[i] = True;
544 tv = timeval_current();
546 for (i=0;i<torture_nprocs;i++) {
550 char *hostname=NULL, *sharename;
552 pid_t mypid = getpid();
553 srandom(((int)mypid) ^ ((int)time(NULL)));
555 asprintf(&myname, "CLIENT%d", i);
556 lp_set_cmdline("netbios name", myname);
561 if (!smbcli_parse_unc(unc_list[i % num_unc_names],
562 NULL, &hostname, &sharename)) {
563 printf("Failed to parse UNC name %s\n",
564 unc_list[i % num_unc_names]);
571 if (torture_open_connection_share(NULL,
578 } else if (torture_open_connection(¤t_cli)) {
582 printf("pid %d failed to start\n", (int)getpid());
588 child_status[i] = getpid();
592 if (child_status[i]) {
593 printf("Child %d failed to start!\n", i);
594 child_status_out[i] = 1;
598 child_status_out[i] = fn(current_cli, i);
605 for (i=0;i<torture_nprocs;i++) {
606 if (child_status[i]) synccount++;
608 if (synccount == torture_nprocs) break;
610 } while (timeval_elapsed(&tv) < start_time_limit);
612 if (synccount != torture_nprocs) {
613 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
615 return timeval_elapsed(&tv);
618 printf("Starting %d clients\n", torture_nprocs);
620 /* start the client load */
621 tv = timeval_current();
622 for (i=0;i<torture_nprocs;i++) {
626 printf("%d clients started\n", torture_nprocs);
630 for (i=0;i<torture_nprocs;i++) {
632 while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ;
633 if (ret == -1 || WEXITSTATUS(status) != 0) {
640 for (i=0;i<torture_nprocs;i++) {
641 if (!child_status_out[i]) {
645 return timeval_elapsed(&tv);
648 #define FLAG_MULTIPROC 1
653 BOOL (*multi_fn)(struct smbcli_state *, int );
654 } builtin_torture_ops[] = {
655 /* benchmarking tests */
656 {"BENCH-HOLDCON", torture_holdcon, 0},
657 {"BENCH-NBENCH", torture_nbench, 0},
658 {"BENCH-TORTURE", NULL, run_torture},
659 {"BENCH-NBT", torture_bench_nbt, 0},
660 {"BENCH-WINS", torture_bench_wins, 0},
661 {"BENCH-CLDAP", torture_bench_cldap, 0},
664 {"RAW-QFSINFO", torture_raw_qfsinfo, 0},
665 {"RAW-QFILEINFO", torture_raw_qfileinfo, 0},
666 {"RAW-SFILEINFO", torture_raw_sfileinfo, 0},
667 {"RAW-SFILEINFO-BUG", torture_raw_sfileinfo_bug, 0},
668 {"RAW-SEARCH", torture_raw_search, 0},
669 {"RAW-CLOSE", torture_raw_close, 0},
670 {"RAW-OPEN", torture_raw_open, 0},
671 {"RAW-MKDIR", torture_raw_mkdir, 0},
672 {"RAW-OPLOCK", torture_raw_oplock, 0},
673 {"RAW-NOTIFY", torture_raw_notify, 0},
674 {"RAW-MUX", torture_raw_mux, 0},
675 {"RAW-IOCTL", torture_raw_ioctl, 0},
676 {"RAW-CHKPATH", torture_raw_chkpath, 0},
677 {"RAW-UNLINK", torture_raw_unlink, 0},
678 {"RAW-READ", torture_raw_read, 0},
679 {"RAW-WRITE", torture_raw_write, 0},
680 {"RAW-LOCK", torture_raw_lock, 0},
681 {"RAW-CONTEXT", torture_raw_context, 0},
682 {"RAW-RENAME", torture_raw_rename, 0},
683 {"RAW-SEEK", torture_raw_seek, 0},
684 {"RAW-EAS", torture_raw_eas, 0},
685 {"RAW-EAMAX", torture_max_eas, 0},
686 {"RAW-STREAMS", torture_raw_streams, 0},
687 {"RAW-ACLS", torture_raw_acls, 0},
688 {"RAW-RAP", torture_raw_rap, 0},
689 {"RAW-COMPOSITE", torture_raw_composite, 0},
692 {"SMB2-CONNECT", torture_smb2_connect, 0},
693 {"SMB2-SCAN", torture_smb2_scan, 0},
694 {"SMB2-SCANGETINFO", torture_smb2_getinfo_scan, 0},
695 {"SMB2-SCANSETINFO", torture_smb2_setinfo_scan, 0},
696 {"SMB2-SCANFIND", torture_smb2_find_scan, 0},
697 {"SMB2-GETINFO", torture_smb2_getinfo, 0},
698 {"SMB2-SETINFO", torture_smb2_setinfo, 0},
699 {"SMB2-FIND", torture_smb2_find, 0},
701 /* protocol scanners */
702 {"SCAN-MAXFID", NULL, run_maxfidtest},
703 {"SCAN-PIPE_NUMBER", run_pipe_number, 0},
704 {"SCAN-IOCTL", torture_ioctl_test, 0},
705 {"SCAN-RAP", torture_rap_scan, 0},
707 /* local (no server) testers */
708 {"LOCAL-NTLMSSP", torture_ntlmssp_self_check, 0},
709 {"LOCAL-ICONV", torture_local_iconv, 0},
710 {"LOCAL-TALLOC", torture_local_talloc, 0},
711 {"LOCAL-MESSAGING", torture_local_messaging, 0},
712 {"LOCAL-IRPC", torture_local_irpc, 0},
713 {"LOCAL-BINDING", torture_local_binding_string, 0},
714 {"LOCAL-STRLIST", torture_local_util_strlist, 0},
715 {"LOCAL-FILE", torture_local_util_file, 0},
716 {"LOCAL-IDTREE", torture_local_idtree, 0},
717 {"LOCAL-SOCKET", torture_local_socket, 0},
718 {"LOCAL-PAC", torture_pac, 0},
719 {"LOCAL-REGISTRY", torture_registry, 0},
720 {"LOCAL-RESOLVE", torture_local_resolve, 0},
721 {"LOCAL-SDDL", torture_local_sddl, 0},
722 {"LOCAL-NDR", torture_local_ndr, 0},
725 {"LDAP-BASIC", torture_ldap_basic, 0},
726 {"LDAP-CLDAP", torture_cldap, 0},
729 {"NBT-REGISTER", torture_nbt_register, 0},
730 {"NBT-WINS", torture_nbt_wins, 0},
731 {"NBT-DGRAM", torture_nbt_dgram, 0},
732 {"NBT-BROWSE", torture_nbt_browse, 0},
733 {"NBT-WINSREPLICATION-SIMPLE", torture_nbt_winsreplication_simple, 0},
734 {"NBT-WINSREPLICATION-REPLICA", torture_nbt_winsreplication_replica, 0},
735 {"NBT-WINSREPLICATION-OWNED", torture_nbt_winsreplication_owned, 0},
738 {"NET-USERINFO", torture_userinfo, 0},
739 {"NET-USERADD", torture_useradd, 0},
740 {"NET-USERDEL", torture_userdel, 0},
741 {"NET-USERMOD", torture_usermod, 0},
742 {"NET-DOMOPEN", torture_domainopen, 0},
743 {"NET-API-LOOKUP", torture_lookup, 0},
744 {"NET-API-LOOKUPHOST", torture_lookup_host, 0},
745 {"NET-API-LOOKUPPDC", torture_lookup_pdc, 0},
746 {"NET-API-CREATEUSER", torture_createuser, 0},
747 {"NET-API-RPCCONNECT", torture_rpc_connect, 0},
748 {"NET-API-LISTSHARES", torture_listshares, 0},
749 {"NET-API-DELSHARE", torture_delshare, 0},
753 static void register_builtin_ops(void)
756 for (i = 0; builtin_torture_ops[i].name; i++) {
757 register_torture_op(builtin_torture_ops[i].name,
758 builtin_torture_ops[i].fn,
759 builtin_torture_ops[i].multi_fn);
764 static struct torture_op {
767 BOOL (*multi_fn)(struct smbcli_state *, int );
768 struct torture_op *prev, *next;
769 }* torture_ops = NULL;;
771 static struct torture_op *find_torture_op(const char *name)
773 struct torture_op *o;
774 for (o = torture_ops; o; o = o->next) {
775 if (strcmp(name, o->name) == 0)
782 _PUBLIC_ NTSTATUS register_torture_op(const char *name, BOOL (*fn)(void), BOOL (*multi_fn)(struct smbcli_state *, int ))
784 struct torture_op *op;
786 /* Check for duplicates */
787 if (find_torture_op(name) != NULL) {
788 DEBUG(0,("There already is a torture op registered with the name %s!\n", name));
789 return NT_STATUS_OBJECT_NAME_COLLISION;
792 op = talloc(talloc_autofree_context(), struct torture_op);
794 op->name = talloc_strdup(op, name);
796 op->multi_fn = multi_fn;
798 DLIST_ADD(torture_ops, op);
803 /****************************************************************************
804 run a specified test or "ALL"
805 ****************************************************************************/
806 static BOOL run_test(const char *name)
809 struct torture_op *o;
810 BOOL matched = False;
812 if (strequal(name,"ALL")) {
813 for (o = torture_ops; o; o = o->next) {
814 if (!run_test(o->name)) {
821 for (o = torture_ops; o; o = o->next) {
822 if (gen_fnmatch(name, o->name) == 0) {
826 printf("Running %s\n", o->name);
829 t = torture_create_procs(o->multi_fn,
833 printf("TEST %s FAILED!\n", o->name);
837 struct timeval tv = timeval_current();
840 printf("TEST %s FAILED!\n", o->name);
842 t = timeval_elapsed(&tv);
844 printf("%s took %g secs\n\n", o->name, t);
849 printf("Unknown torture operation '%s'\n", name);
856 static void parse_dns(const char *dns)
858 char *userdn, *basedn, *secret;
861 /* retrievieng the userdn */
862 p = strchr_m(dns, '#');
864 lp_set_cmdline("torture:ldap_userdn", "");
865 lp_set_cmdline("torture:ldap_basedn", "");
866 lp_set_cmdline("torture:ldap_secret", "");
869 userdn = strndup(dns, p - dns);
870 lp_set_cmdline("torture:ldap_userdn", userdn);
872 /* retrieve the basedn */
874 p = strchr_m(d, '#');
876 lp_set_cmdline("torture:ldap_basedn", "");
877 lp_set_cmdline("torture:ldap_secret", "");
880 basedn = strndup(d, p - d);
881 lp_set_cmdline("torture:ldap_basedn", basedn);
883 /* retrieve the secret */
886 lp_set_cmdline("torture:ldap_secret", "");
890 lp_set_cmdline("torture:ldap_secret", secret);
892 printf ("%s - %s - %s\n", userdn, basedn, secret);
896 static void usage(poptContext pc)
898 struct torture_op *o;
901 poptPrintUsage(pc, stdout, 0);
904 printf("The binding format is:\n\n");
906 printf(" TRANSPORT:host[flags]\n\n");
908 printf(" where TRANSPORT is either ncacn_np for SMB or ncacn_ip_tcp for RPC/TCP\n\n");
910 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
911 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
912 printf(" string.\n\n");
914 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
915 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
916 printf(" will be auto-determined.\n\n");
918 printf(" other recognised flags are:\n\n");
920 printf(" sign : enable ntlmssp signing\n");
921 printf(" seal : enable ntlmssp sealing\n");
922 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
923 printf(" validate: enable the NDR validator\n");
924 printf(" print: enable debugging of the packets\n");
925 printf(" bigendian: use bigendian RPC\n");
926 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
928 printf(" For example, these all connect to the samr pipe:\n\n");
930 printf(" ncacn_np:myserver\n");
931 printf(" ncacn_np:myserver[samr]\n");
932 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
933 printf(" ncacn_np:myserver[/pipe/samr]\n");
934 printf(" ncacn_np:myserver[samr,sign,print]\n");
935 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
936 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
937 printf(" ncacn_np:\n");
938 printf(" ncacn_np:[/pipe/samr]\n\n");
940 printf(" ncacn_ip_tcp:myserver\n");
941 printf(" ncacn_ip_tcp:myserver[1024]\n");
942 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
944 printf("The unc format is:\n\n");
946 printf(" //server/share\n\n");
948 printf("tests are:\n");
951 for (o = torture_ops; o; o = o->next) {
952 if (i + strlen(o->name) >= MAX_COLS) {
956 i+=printf("%s ", o->name);
960 printf("default test is ALL\n");
965 static BOOL is_binding_string(const char *binding_string)
967 TALLOC_CTX *mem_ctx = talloc_init("is_binding_string");
968 struct dcerpc_binding *binding_struct;
971 status = dcerpc_parse_binding(mem_ctx, binding_string, &binding_struct);
973 talloc_free(mem_ctx);
974 return NT_STATUS_IS_OK(status);
977 static void max_runtime_handler(int sig)
979 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
983 /****************************************************************************
985 ****************************************************************************/
986 int main(int argc,char *argv[])
995 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS,
996 OPT_DANGEROUS,OPT_SMB_PORTS};
997 init_module_fn static_init[] = STATIC_smbtorture_MODULES;
998 init_module_fn *shared_init = load_samba_modules(NULL, "torture");
1000 struct poptOption long_options[] = {
1002 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
1003 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "seed", NULL},
1004 {"num-progs", 0, POPT_ARG_INT, &torture_nprocs, 0, "num progs", NULL},
1005 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
1006 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
1007 {"use-oplocks", 'L', POPT_ARG_NONE, &use_oplocks, 0, "use oplocks", NULL},
1008 {"show-all", 0, POPT_ARG_NONE, &torture_showall, 0, "show all", NULL},
1009 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "loadfile", NULL},
1010 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
1011 {"timelimit", 't', POPT_ARG_STRING, NULL, OPT_TIMELIMIT, "timelimit", NULL},
1012 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
1013 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
1014 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS, "dangerous", NULL},
1015 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
1016 "set maximum time for smbtorture to live", "seconds"},
1018 POPT_COMMON_CONNECTION
1019 POPT_COMMON_CREDENTIALS
1024 #ifdef HAVE_SETBUFFER
1025 setbuffer(stdout, NULL, 0);
1028 register_builtin_ops();
1030 run_init_functions(static_init);
1031 run_init_functions(shared_init);
1033 talloc_free(shared_init);
1035 /* we are never interested in SIGPIPE */
1036 BlockSignals(True,SIGPIPE);
1038 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
1039 POPT_CONTEXT_KEEP_FIRST);
1041 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
1043 while((opt = poptGetNextOpt(pc)) != -1) {
1046 lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
1049 lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
1052 lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
1055 parse_dns(poptGetOptArg(pc));
1058 lp_set_cmdline("torture:dangerous", "Yes");
1061 lp_set_cmdline("smb ports", poptGetOptArg(pc));
1064 d_printf("Invalid option %s: %s\n",
1065 poptBadOption(pc, 0), poptStrerror(opt));
1072 /* this will only work if nobody else uses alarm(),
1073 which means it won't work for some tests, but we
1074 can't use the event context method we use for smbd
1075 as so many tests create their own event
1076 context. This will at least catch most cases. */
1077 signal(SIGALRM, max_runtime_handler);
1083 if (torture_seed == 0) {
1084 torture_seed = time(NULL);
1086 printf("Using seed %d\n", torture_seed);
1087 srandom(torture_seed);
1089 argv_new = discard_const_p(char *, poptGetArgs(pc));
1092 for (i=0; i<argc; i++) {
1093 if (argv_new[i] == NULL) {
1104 for(p = argv_new[1]; *p; p++) {
1109 /* see if its a RPC transport specifier */
1110 if (is_binding_string(argv_new[1])) {
1111 lp_set_cmdline("torture:binding", argv_new[1]);
1113 char *binding = NULL;
1114 char *host = NULL, *share = NULL;
1116 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
1117 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
1121 lp_set_cmdline("torture:host", host);
1122 lp_set_cmdline("torture:share", share);
1123 asprintf(&binding, "ncacn_np:%s", host);
1124 lp_set_cmdline("torture:binding", binding);
1127 if (argc_new == 0) {
1128 printf("You must specify a test to run, or 'ALL'\n");
1130 for (i=2;i<argc_new;i++) {
1131 if (!run_test(argv_new[i])) {