📄 misc.c
字号:
/* 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 3 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, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "libcli/raw/libcliraw.h"#include "libcli/raw/raw_proto.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/smbtorture.h"#include "torture/util.h"#include "libcli/smb_composite/smb_composite.h"#include "libcli/composite/composite.h"#include "param/param.h"extern struct cli_credentials *cmdline_credentials; 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 torture_context *tctx, 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) { torture_comment(tctx, "open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree)); return false; } generate_random_buffer(buf, sizeof(buf)); for (i=0;i<torture_numops;i++) { uint_t n = (uint_t)random()%10; if (i % 10 == 0) { if (torture_setting_bool(tctx, "progress", true)) { torture_comment(tctx, "%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) { torture_comment(tctx, "open failed (%s)\n", smbcli_errstr(c->tree)); correct = false; break; } if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) { torture_comment(tctx, "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)) { torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c->tree)); correct = false; } } pid2 = 0; if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) { torture_comment(tctx, "read failed (%s)\n", smbcli_errstr(c->tree)); correct = false; } if (pid2 != pid) { torture_comment(tctx, "data corruption!\n"); correct = false; } if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) { torture_comment(tctx, "close failed (%s)\n", smbcli_errstr(c->tree)); correct = false; } if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) { torture_comment(tctx, "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)))) { torture_comment(tctx, "unlock failed (%s)\n", smbcli_errstr(c->tree)); correct = false; } free(fname); } smbcli_close(c->tree, fnum2); smbcli_unlink(c->tree, lockfname); torture_comment(tctx, "%d\n", i); return correct;}bool run_torture(struct torture_context *tctx, struct smbcli_state *cli, int dummy){ return rw_torture(tctx, cli);}/* see how many RPC pipes we can open at once*/bool run_pipe_number(struct torture_context *tctx, struct smbcli_state *cli1){ const char *pipe_name = "\\WKSSVC"; int fnum; int num_pipes = 0; 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) { torture_comment(tctx, "Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree)); break; } num_pipes++; if (torture_setting_bool(tctx, "progress", true)) { torture_comment(tctx, "%d\r", num_pipes); fflush(stdout); } } torture_comment(tctx, "pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name ); 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 */bool torture_holdcon(struct torture_context *tctx){ int i; struct smbcli_state **cli; int num_dead = 0; torture_comment(tctx, "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], tctx, i)) { return false; } if (torture_setting_bool(tctx, "progress", true)) { torture_comment(tctx, "opened %d connections\r", i); fflush(stdout); } } torture_comment(tctx, "\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)) { torture_comment(tctx, "Connection %d is dead\n", i); cli[i] = NULL; num_dead++; } usleep(100); } } if (num_dead == torture_numops) { torture_comment(tctx, "All connections dead - finishing\n"); break; } torture_comment(tctx, "."); fflush(stdout); } return true;}/*test how many open files this server supports on the one socket*/bool run_maxfidtest(struct torture_context *tctx, 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) { torture_comment(tctx, "failed to connect\n"); return false; } if (smbcli_deltree(cli->tree, "\\maxfid") == -1) { torture_comment(tctx, "Failed to deltree \\maxfid - %s\n", smbcli_errstr(cli->tree)); return false; } if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) { torture_comment(tctx, "Failed to mkdir \\maxfid, error=%s\n", smbcli_errstr(cli->tree)); return false; } torture_comment(tctx, "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))) { torture_comment(tctx, "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) { torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); torture_comment(tctx, "maximum fnum is %d\n", i); break; } free(fname); if (torture_setting_bool(tctx, "progress", true)) { torture_comment(tctx, "%6d\r", i); fflush(stdout); } } torture_comment(tctx, "%6d\n", i); i--; maxfid = i; torture_comment(tctx, "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]))) { torture_comment(tctx, "Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree)); } if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) { torture_comment(tctx, "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]))) { torture_comment(tctx, "Close of fnum %d failed - %s\n", fnums[maxfid-i], smbcli_errstr(cli->tree)); } if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) { torture_comment(tctx, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); correct = false; } free(fname); if (torture_setting_bool(tctx, "progress", true)) { torture_comment(tctx, "%6d %6d\r", i, maxfid-i); fflush(stdout); } } torture_comment(tctx, "%6d\n", 0); if (smbcli_deltree(cli->tree, "\\maxfid") == -1) { torture_comment(tctx, "Failed to deltree \\maxfid - %s\n", smbcli_errstr(cli->tree)); return false; } torture_comment(tctx, "maxfid test finished\n"); if (!torture_close_connection(cli)) { correct = false; } return correct;#undef MAXFID_TEMPLATE}/* sees what IOCTLs are supported */bool torture_ioctl_test(struct torture_context *tctx, 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; mem_ctx = talloc_named_const(tctx, 0, "ioctl_test"); smbcli_unlink(cli->tree, fname); fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); if (fnum == -1) { torture_comment(tctx, "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); torture_comment(tctx, "ioctl job info: %s\n", smbcli_errstr(cli->tree)); for (device=0;device<0x100;device++) { torture_comment(tctx, "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)) { torture_comment(tctx, "ioctl device=0x%x function=0x%x OK : %d bytes\n", device, function, (int)parms.ioctl.out.blob.length); } } } return true;}static void benchrw_callback(struct smbcli_request *req);enum benchrw_stage { START, OPEN_CONNECTION, CLEANUP_TESTDIR, MK_TESTDIR, OPEN_FILE, INITIAL_WRITE, READ_WRITE_DATA, MAX_OPS_REACHED, ERROR, CLOSE_FILE, CLEANUP, FINISHED};struct benchrw_state { struct torture_context *tctx; char *dname; char *fname; uint16_t fnum; int nr; struct smbcli_tree *cli; uint8_t *buffer; int writecnt; int readcnt; int completed; int num_parallel_requests; void *req_params; enum benchrw_stage mode; struct params{ struct unclist{ const char *host; const char *share; } **unc; const char *workgroup; int retry; unsigned int writeblocks; unsigned int blocksize; unsigned int writeratio; int num_parallel_requests; } *lp_params;};/* init params using lp_parm_xxx return number of unclist entries*/static int init_benchrw_params(struct torture_context *tctx, struct params *lpar){ char **unc_list = NULL; int num_unc_names = 0, conn_index=0, empty_lines=0; const char *p; lpar->retry = torture_setting_int(tctx, "retry",3); lpar->blocksize = torture_setting_int(tctx, "blocksize",65535); lpar->writeblocks = torture_setting_int(tctx, "writeblocks",15); lpar->writeratio = torture_setting_int(tctx, "writeratio",5); lpar->num_parallel_requests = torture_setting_int( tctx, "parallel_requests", 5); lpar->workgroup = lp_workgroup(tctx->lp_ctx); p = torture_setting_string(tctx, "unclist", NULL); if (p) { char *h, *s; unc_list = file_lines_load(p, &num_unc_names, NULL); if (!unc_list || num_unc_names <= 0) { torture_comment(tctx, "Failed to load unc names list " "from '%s'\n", p); exit(1); } lpar->unc = talloc_array(tctx, struct unclist *, (num_unc_names-empty_lines)); for(conn_index = 0; conn_index < num_unc_names; conn_index++) { /* ignore empty lines */ if(strlen(unc_list[conn_index % num_unc_names])==0){ empty_lines++; continue; } if (!smbcli_parse_unc( unc_list[conn_index % num_unc_names], NULL, &h, &s)) { torture_comment( tctx, "Failed to parse UNC " "name %s\n", unc_list[conn_index % num_unc_names]); exit(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -