diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2006-06-17 02:20:39 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 14:09:11 -0500 |
commit | 845df42a19bade71bf6985d006e8e54018c53bdf (patch) | |
tree | 178f954f612466265049694564e7bf950524e0f9 /source4/torture/misc.c | |
parent | 835d8ed2f61fff798ac49156df94b86ace704b6d (diff) | |
download | samba-845df42a19bade71bf6985d006e8e54018c53bdf.tar.gz samba-845df42a19bade71bf6985d006e8e54018c53bdf.tar.xz samba-845df42a19bade71bf6985d006e8e54018c53bdf.zip |
r16333: Move more code out of the core smbtorture. It now no longer
contains protocol-specific code.
(This used to be commit 819d3b457648ffb7526a770e842badc17b6061fb)
Diffstat (limited to 'source4/torture/misc.c')
-rw-r--r-- | source4/torture/misc.c | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/source4/torture/misc.c b/source4/torture/misc.c new file mode 100644 index 0000000000..71dd1587cb --- /dev/null +++ b/source4/torture/misc.c @@ -0,0 +1,401 @@ +/* + Unix SMB/CIFS implementation. + SMB torture tester + Copyright (C) Andrew Tridgell 1997-2003 + Copyright (C) Jelmer Vernooij 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "system/time.h" +#include "system/wait.h" +#include "system/filesys.h" +#include "libcli/raw/ioctl.h" +#include "libcli/libcli.h" +#include "lib/events/events.h" +#include "libcli/resolve/resolve.h" +#include "auth/credentials/credentials.h" +#include "librpc/gen_ndr/ndr_nbt.h" +#include "torture/torture.h" +#include "torture/util.h" + +static BOOL wait_lock(struct smbcli_state *c, int fnum, uint32_t offset, uint32_t len) +{ + while (NT_STATUS_IS_ERR(smbcli_lock(c->tree, fnum, offset, len, -1, WRITE_LOCK))) { + if (!check_error(__location__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False; + } + return True; +} + + +static BOOL rw_torture(struct smbcli_state *c) +{ + const char *lockfname = "\\torture.lck"; + char *fname; + int fnum; + int fnum2; + pid_t pid2, pid = getpid(); + int i, j; + uint8_t buf[1024]; + BOOL correct = True; + + fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, + DENY_NONE); + if (fnum2 == -1) + fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE); + if (fnum2 == -1) { + printf("open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree)); + return False; + } + + + for (i=0;i<torture_numops;i++) { + uint_t n = (uint_t)random()%10; + if (i % 10 == 0) { + printf("%d\r", i); fflush(stdout); + } + asprintf(&fname, "\\torture.%u", n); + + if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) { + return False; + } + + fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL); + if (fnum == -1) { + printf("open failed (%s)\n", smbcli_errstr(c->tree)); + correct = False; + break; + } + + if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) { + printf("write failed (%s)\n", smbcli_errstr(c->tree)); + correct = False; + } + + for (j=0;j<50;j++) { + if (smbcli_write(c->tree, fnum, 0, buf, + sizeof(pid)+(j*sizeof(buf)), + sizeof(buf)) != sizeof(buf)) { + printf("write failed (%s)\n", smbcli_errstr(c->tree)); + correct = False; + } + } + + pid2 = 0; + + if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) { + printf("read failed (%s)\n", smbcli_errstr(c->tree)); + correct = False; + } + + if (pid2 != pid) { + printf("data corruption!\n"); + correct = False; + } + + if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) { + printf("close failed (%s)\n", smbcli_errstr(c->tree)); + correct = False; + } + + if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) { + printf("unlink failed (%s)\n", smbcli_errstr(c->tree)); + correct = False; + } + + if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) { + printf("unlock failed (%s)\n", smbcli_errstr(c->tree)); + correct = False; + } + free(fname); + } + + smbcli_close(c->tree, fnum2); + smbcli_unlink(c->tree, lockfname); + + printf("%d\n", i); + + return correct; +} + +static BOOL run_torture(struct smbcli_state *cli, int dummy) +{ + BOOL ret; + + ret = rw_torture(cli); + + if (!torture_close_connection(cli)) { + ret = False; + } + + return ret; +} + + +/* + see how many RPC pipes we can open at once +*/ +static BOOL run_pipe_number(struct torture_context *torture) +{ + struct smbcli_state *cli1; + const char *pipe_name = "\\WKSSVC"; + int fnum; + int num_pipes = 0; + + printf("starting pipenumber test\n"); + if (!torture_open_connection(&cli1)) { + return False; + } + + while(1) { + fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL, + NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0); + + if (fnum == -1) { + printf("Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree)); + break; + } + num_pipes++; + printf("%d\r", num_pipes); + fflush(stdout); + } + + printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name ); + torture_close_connection(cli1); + return True; +} + + + + +/* + open N connections to the server and just hold them open + used for testing performance when there are N idle users + already connected + */ + static BOOL torture_holdcon(struct torture_context *torture) +{ + int i; + struct smbcli_state **cli; + int num_dead = 0; + + printf("Opening %d connections\n", torture_numops); + + cli = malloc_array_p(struct smbcli_state *, torture_numops); + + for (i=0;i<torture_numops;i++) { + if (!torture_open_connection(&cli[i])) { + return False; + } + printf("opened %d connections\r", i); + fflush(stdout); + } + + printf("\nStarting pings\n"); + + while (1) { + for (i=0;i<torture_numops;i++) { + NTSTATUS status; + if (cli[i]) { + status = smbcli_chkpath(cli[i]->tree, "\\"); + if (!NT_STATUS_IS_OK(status)) { + printf("Connection %d is dead\n", i); + cli[i] = NULL; + num_dead++; + } + usleep(100); + } + } + + if (num_dead == torture_numops) { + printf("All connections dead - finishing\n"); + break; + } + + printf("."); + fflush(stdout); + } + + return True; +} + +/* +test how many open files this server supports on the one socket +*/ +static BOOL run_maxfidtest(struct smbcli_state *cli, int dummy) +{ +#define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d" + char *fname; + int fnums[0x11000], i; + int retries=4, maxfid; + BOOL correct = True; + + if (retries <= 0) { + printf("failed to connect\n"); + return False; + } + + if (smbcli_deltree(cli->tree, "\\maxfid") == -1) { + printf("Failed to deltree \\maxfid - %s\n", + smbcli_errstr(cli->tree)); + return False; + } + if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) { + printf("Failed to mkdir \\maxfid, error=%s\n", + smbcli_errstr(cli->tree)); + return False; + } + + printf("Testing maximum number of open files\n"); + + for (i=0; i<0x11000; i++) { + if (i % 1000 == 0) { + asprintf(&fname, "\\maxfid\\fid%d", i/1000); + if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) { + printf("Failed to mkdir %s, error=%s\n", + fname, smbcli_errstr(cli->tree)); + return False; + } + free(fname); + } + asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid()); + if ((fnums[i] = smbcli_open(cli->tree, fname, + O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) == + -1) { + printf("open of %s failed (%s)\n", + fname, smbcli_errstr(cli->tree)); + printf("maximum fnum is %d\n", i); + break; + } + free(fname); + printf("%6d\r", i); + } + printf("%6d\n", i); + i--; + + maxfid = i; + + printf("cleaning up\n"); + for (i=0;i<maxfid/2;i++) { + asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid()); + if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) { + printf("Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree)); + } + if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) { + printf("unlink of %s failed (%s)\n", + fname, smbcli_errstr(cli->tree)); + correct = False; + } + free(fname); + + asprintf(&fname, MAXFID_TEMPLATE, (maxfid-i)/1000, maxfid-i,(int)getpid()); + if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[maxfid-i]))) { + printf("Close of fnum %d failed - %s\n", fnums[maxfid-i], smbcli_errstr(cli->tree)); + } + if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) { + printf("unlink of %s failed (%s)\n", + fname, smbcli_errstr(cli->tree)); + correct = False; + } + free(fname); + + printf("%6d %6d\r", i, maxfid-i); + } + printf("%6d\n", 0); + + if (smbcli_deltree(cli->tree, "\\maxfid") == -1) { + printf("Failed to deltree \\maxfid - %s\n", + smbcli_errstr(cli->tree)); + return False; + } + + printf("maxfid test finished\n"); + if (!torture_close_connection(cli)) { + correct = False; + } + return correct; +#undef MAXFID_TEMPLATE +} + + + +/* + sees what IOCTLs are supported + */ +static BOOL torture_ioctl_test(struct torture_context *torture) +{ + struct smbcli_state *cli; + uint16_t device, function; + int fnum; + const char *fname = "\\ioctl.dat"; + NTSTATUS status; + union smb_ioctl parms; + TALLOC_CTX *mem_ctx; + + if (!torture_open_connection(&cli)) { + return False; + } + + mem_ctx = talloc_init("ioctl_test"); + + printf("starting ioctl test\n"); + + smbcli_unlink(cli->tree, fname); + + fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); + if (fnum == -1) { + printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); + return False; + } + + parms.ioctl.level = RAW_IOCTL_IOCTL; + parms.ioctl.in.file.fnum = fnum; + parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO; + status = smb_raw_ioctl(cli->tree, mem_ctx, &parms); + printf("ioctl job info: %s\n", smbcli_errstr(cli->tree)); + + for (device=0;device<0x100;device++) { + printf("testing device=0x%x\n", device); + for (function=0;function<0x100;function++) { + parms.ioctl.in.request = (device << 16) | function; + status = smb_raw_ioctl(cli->tree, mem_ctx, &parms); + + if (NT_STATUS_IS_OK(status)) { + printf("ioctl device=0x%x function=0x%x OK : %d bytes\n", + device, function, (int)parms.ioctl.out.blob.length); + } + } + } + + if (!torture_close_connection(cli)) { + return False; + } + + return True; +} + + +NTSTATUS torture_misc_init(void) +{ + register_torture_op("BENCH-HOLDCON", torture_holdcon); + register_torture_op("SCAN-PIPE_NUMBER", run_pipe_number); + register_torture_op("SCAN-IOCTL", torture_ioctl_test); + register_torture_multi_op("BENCH-TORTURE", run_torture); + register_torture_multi_op("SCAN-MAXFID", run_maxfidtest); + + return NT_STATUS_OK; +} |