2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1997-1998
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.
26 static fstring host, workgroup, share, password, username, myname;
27 static int max_protocol = PROTOCOL_NT1;
28 static char *sockops="TCP_NODELAY";
29 static int nprocs=1, numops=100;
30 static struct cli_state current_cli;
32 static double create_procs(void (*fn)(int));
35 static struct timeval tp1,tp2;
37 static void start_timer(void)
39 gettimeofday(&tp1,NULL);
42 static double end_timer(void)
44 gettimeofday(&tp2,NULL);
45 return((tp2.tv_sec - tp1.tv_sec) +
46 (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
50 /* return a pointer to a anonymous shared memory segment of size "size"
51 which will persist across fork() but will disappear when all processes
54 The memory is not zeroed
56 This function uses system5 shared memory. It takes advantage of a property
57 that the memory is not destroyed if it is attached when the id is removed
59 static void *shm_setup(int size)
64 shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
66 printf("can't get shared memory\n");
69 ret = (void *)shmat(shmid, 0, 0);
70 if (!ret || ret == (void *)-1) {
71 printf("can't attach to shared memory\n");
74 /* the following releases the ipc, but note that this process
75 and all its children will still have access to the memory, its
76 just that the shmid is no longer valid for other shm calls. This
77 means we don't leave behind lots of shm segments after we exit
79 See Stevens "advanced programming in unix env" for details
81 shmctl(shmid, IPC_RMID, 0);
87 static BOOL open_connection(struct cli_state *c)
89 struct nmb_name called, calling;
91 extern struct in_addr ipzero;
95 make_nmb_name(&calling, myname, 0x0);
96 make_nmb_name(&called , host, 0x20);
100 if (!cli_initialise(c) || !cli_connect(c, host, &ip)) {
101 printf("Failed to connect with %s\n", host);
105 c->timeout = 120000; /* set a really long timeout (2 minutes) */
107 if (!cli_session_request(c, &calling, &called)) {
108 printf("%s rejected the session\n",host);
113 if (!cli_negprot(c)) {
114 printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
119 if (!cli_session_setup(c, username,
120 password, strlen(password),
121 password, strlen(password),
123 printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
128 if (!cli_send_tconX(c, share, "?????",
129 password, strlen(password)+1)) {
130 printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
140 static void close_connection(struct cli_state *c)
143 printf("tdis failed (%s)\n", cli_errstr(c));
150 /* check if the server produced the expected error code */
151 static BOOL check_error(struct cli_state *c,
152 uint8 eclass, uint32 ecode, uint32 nterr)
156 (void)cli_error(c, &class, &num, NULL);
157 if ((eclass != class || ecode != num) &&
158 num != (nterr&0xFFFFFF)) {
159 printf("unexpected error code class=%d code=%d\n",
160 (int)class, (int)num);
161 printf(" expected %d/%d %d\n",
162 (int)eclass, (int)ecode, (int)nterr);
169 static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
171 while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) {
172 if (!check_error(c, ERRDOS, ERRlock, 0)) return False;
178 static BOOL rw_torture(struct cli_state *c)
180 char *lockfname = "\\torture.lck";
184 pid_t pid2, pid = getpid();
188 fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
191 fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
193 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
198 for (i=0;i<numops;i++) {
199 unsigned n = (unsigned)sys_random()%10;
201 printf("%d\r", i); fflush(stdout);
203 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
205 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
209 fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
211 printf("open failed (%s)\n", cli_errstr(c));
215 if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
216 printf("write failed (%s)\n", cli_errstr(c));
220 if (cli_write(c, fnum, 0, (char *)buf,
221 sizeof(pid)+(j*sizeof(buf)),
222 sizeof(buf)) != sizeof(buf)) {
223 printf("write failed (%s)\n", cli_errstr(c));
229 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
230 printf("read failed (%s)\n", cli_errstr(c));
234 printf("data corruption!\n");
237 if (!cli_close(c, fnum)) {
238 printf("close failed (%s)\n", cli_errstr(c));
241 if (!cli_unlink(c, fname)) {
242 printf("unlink failed (%s)\n", cli_errstr(c));
245 if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int))) {
246 printf("unlock failed (%s)\n", cli_errstr(c));
251 cli_unlink(c, lockfname);
258 static void run_torture(int dummy)
260 struct cli_state cli;
264 cli_sockopt(&cli, sockops);
268 close_connection(&cli);
273 /* run a test that simulates an approximate netbench client load */
274 static void run_netbench(int client)
276 struct cli_state cli;
286 cli_sockopt(&cli, sockops);
290 slprintf(cname,sizeof(fname), "CLIENT%d", client);
292 f = fopen("client.txt", "r");
295 perror("client.txt");
299 while (fgets(line, sizeof(line)-1, f)) {
302 line[strlen(line)-1] = 0;
304 /* printf("[%d] %s\n", line_count, line); */
306 all_string_sub(line,"CLIENT1", cname, sizeof(line));
308 for (i=0;i<20;i++) params[i] = "";
310 /* parse the command parameters */
311 params[0] = strtok(line," ");
313 while (params[i]) params[++i] = strtok(NULL," ");
319 if (strcmp(params[1],"REQUEST") == 0) {
320 if (!strcmp(params[0],"SMBopenX")) {
321 fstrcpy(fname, params[5]);
322 } else if (!strcmp(params[0],"SMBclose")) {
323 nb_close(atoi(params[3]));
324 } else if (!strcmp(params[0],"SMBmkdir")) {
326 } else if (!strcmp(params[0],"CREATE")) {
327 nb_create(params[3], atoi(params[5]));
328 } else if (!strcmp(params[0],"SMBrmdir")) {
330 } else if (!strcmp(params[0],"SMBunlink")) {
331 fstrcpy(fname, params[3]);
332 } else if (!strcmp(params[0],"SMBmv")) {
333 nb_rename(params[3], params[5]);
334 } else if (!strcmp(params[0],"SMBgetatr")) {
335 fstrcpy(fname, params[3]);
336 } else if (!strcmp(params[0],"SMBwrite")) {
337 nb_write(atoi(params[3]),
338 atoi(params[5]), atoi(params[7]));
339 } else if (!strcmp(params[0],"SMBwritebraw")) {
340 nb_write(atoi(params[3]),
341 atoi(params[7]), atoi(params[5]));
342 } else if (!strcmp(params[0],"SMBreadbraw")) {
343 nb_read(atoi(params[3]),
344 atoi(params[7]), atoi(params[5]));
345 } else if (!strcmp(params[0],"SMBread")) {
346 nb_read(atoi(params[3]),
347 atoi(params[5]), atoi(params[7]));
350 if (!strcmp(params[0],"SMBopenX")) {
351 if (!strncmp(params[2], "ERR", 3)) continue;
352 nb_open(fname, atoi(params[3]), atoi(params[5]));
353 } else if (!strcmp(params[0],"SMBgetatr")) {
354 if (!strncmp(params[2], "ERR", 3)) continue;
355 nb_stat(fname, atoi(params[3]));
356 } else if (!strcmp(params[0],"SMBunlink")) {
357 if (!strncmp(params[2], "ERR", 3)) continue;
364 slprintf(fname,sizeof(fname), "CLIENTS/CLIENT%d", client);
370 close_connection(&cli);
374 /* run a test that simulates an approximate netbench w9X client load */
375 static void run_nbw95(int dummy)
378 t = create_procs(run_netbench);
379 /* to produce a netbench result we scale accoding to the
380 netbench measured throughput for the run that produced the
381 sniff that was used to produce client.txt. That run used 2
382 clients and ran for 660 seconds to produce a result of
384 printf("Throughput %g MB/sec (NB=%g MB/sec %g MBit/sec)\n",
385 132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
388 /* run a test that simulates an approximate netbench wNT client load */
389 static void run_nbwnt(int dummy)
392 t = create_procs(run_netbench);
393 printf("Throughput %g MB/sec (NB=%g MB/sec %g MBit/sec)\n",
394 132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
400 This test checks for two things:
402 1) correct support for retaining locks over a close (ie. the server
403 must not use posix semantics)
404 2) support for lock timeouts
406 static void run_locktest1(int dummy)
408 static struct cli_state cli1, cli2;
409 char *fname = "\\lockt1.lck";
410 int fnum1, fnum2, fnum3;
413 if (!open_connection(&cli1) || !open_connection(&cli2)) {
416 cli_sockopt(&cli1, sockops);
417 cli_sockopt(&cli2, sockops);
419 printf("starting locktest1\n");
421 cli_unlink(&cli1, fname);
423 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
425 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
428 fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
430 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
433 fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
435 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
439 if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
440 printf("lock1 failed (%s)\n", cli_errstr(&cli1));
445 if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
446 printf("lock2 succeeded! This is a locking bug\n");
449 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
453 printf("Testing lock timeouts\n");
455 if (cli_lock(&cli2, fnum3, 0, 4, 10*1000, WRITE_LOCK)) {
456 printf("lock3 succeeded! This is a locking bug\n");
459 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
464 printf("error: This server appears not to support timed lock requests\n");
467 if (!cli_close(&cli1, fnum2)) {
468 printf("close1 failed (%s)\n", cli_errstr(&cli1));
472 if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
473 printf("lock4 succeeded! This is a locking bug\n");
476 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
479 if (!cli_close(&cli1, fnum1)) {
480 printf("close2 failed (%s)\n", cli_errstr(&cli1));
484 if (!cli_close(&cli2, fnum3)) {
485 printf("close3 failed (%s)\n", cli_errstr(&cli2));
489 if (!cli_unlink(&cli1, fname)) {
490 printf("unlink failed (%s)\n", cli_errstr(&cli1));
495 close_connection(&cli1);
496 close_connection(&cli2);
498 printf("Passed locktest1\n");
502 checks for correct tconX support
504 static void run_tcon_test(int dummy)
506 static struct cli_state cli1;
507 char *fname = "\\tcontest.tmp";
512 if (!open_connection(&cli1)) {
515 cli_sockopt(&cli1, sockops);
517 printf("starting tcontest\n");
519 cli_unlink(&cli1, fname);
521 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
524 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
530 if (cli_write(&cli1, fnum1, 0, buf, 130, 4) != 4)
532 printf("write failed (%s)", cli_errstr(&cli1));
536 if (!cli_send_tconX(&cli1, share, "?????",
537 password, strlen(password)+1)) {
538 printf("%s refused 2nd tree connect (%s)\n", host,
544 if (cli_write(&cli1, fnum1, 0, buf, 130, 4) == 4)
546 printf("write succeeded (%s)", cli_errstr(&cli1));
550 if (cli_close(&cli1, fnum1)) {
551 printf("close2 succeeded (%s)\n", cli_errstr(&cli1));
555 if (!cli_tdis(&cli1)) {
556 printf("tdis failed (%s)\n", cli_errstr(&cli1));
562 if (!cli_close(&cli1, fnum1)) {
563 printf("close2 failed (%s)\n", cli_errstr(&cli1));
567 close_connection(&cli1);
569 printf("Passed tcontest\n");
574 This test checks that
576 1) the server supports multiple locking contexts on the one SMB
577 connection, distinguished by PID.
579 2) the server correctly fails overlapping locks made by the same PID (this
580 goes against POSIX behaviour, which is why it is tricky to implement)
582 3) the server denies unlock requests by an incorrect client PID
584 static void run_locktest2(int dummy)
586 static struct cli_state cli;
587 char *fname = "\\lockt2.lck";
588 int fnum1, fnum2, fnum3;
590 if (!open_connection(&cli)) {
594 cli_sockopt(&cli, sockops);
596 printf("starting locktest2\n");
598 cli_unlink(&cli, fname);
602 fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
604 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
608 fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
610 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
616 fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
618 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
624 if (!cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
625 printf("lock1 failed (%s)\n", cli_errstr(&cli));
629 if (cli_lock(&cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
630 printf("lock2 succeeded! This is a locking bug\n");
632 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
637 if (cli_unlock(&cli, fnum1, 0, 8)) {
638 printf("unlock1 succeeded! This is a locking bug\n");
641 if (cli_lock(&cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
642 printf("lock3 succeeded! This is a locking bug\n");
644 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
649 if (!cli_close(&cli, fnum1)) {
650 printf("close1 failed (%s)\n", cli_errstr(&cli));
654 if (!cli_close(&cli, fnum2)) {
655 printf("close2 failed (%s)\n", cli_errstr(&cli));
659 if (!cli_close(&cli, fnum3)) {
660 printf("close3 failed (%s)\n", cli_errstr(&cli));
664 close_connection(&cli);
666 printf("locktest2 finished\n");
671 This test checks that
673 1) the server supports the full offset range in lock requests
675 static void run_locktest3(int dummy)
677 static struct cli_state cli1, cli2;
678 char *fname = "\\lockt3.lck";
682 #define NEXT_OFFSET offset += (~(uint32)0) / numops
684 if (!open_connection(&cli1) || !open_connection(&cli2)) {
687 cli_sockopt(&cli1, sockops);
688 cli_sockopt(&cli2, sockops);
690 printf("starting locktest3\n");
692 cli_unlink(&cli1, fname);
694 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
696 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
699 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
701 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
705 for (offset=i=0;i<numops;i++) {
707 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
708 printf("lock1 %d failed (%s)\n",
714 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
715 printf("lock2 %d failed (%s)\n",
722 for (offset=i=0;i<numops;i++) {
725 if (cli_lock(&cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
726 printf("error: lock1 %d succeeded!\n", i);
730 if (cli_lock(&cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
731 printf("error: lock2 %d succeeded!\n", i);
735 if (cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
736 printf("error: lock3 %d succeeded!\n", i);
740 if (cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
741 printf("error: lock4 %d succeeded!\n", i);
746 for (offset=i=0;i<numops;i++) {
749 if (!cli_unlock(&cli1, fnum1, offset-1, 1)) {
750 printf("unlock1 %d failed (%s)\n",
756 if (!cli_unlock(&cli2, fnum2, offset-2, 1)) {
757 printf("unlock2 %d failed (%s)\n",
764 if (!cli_close(&cli1, fnum1)) {
765 printf("close1 failed (%s)\n", cli_errstr(&cli1));
768 if (!cli_close(&cli2, fnum2)) {
769 printf("close2 failed (%s)\n", cli_errstr(&cli2));
772 if (!cli_unlink(&cli1, fname)) {
773 printf("unlink failed (%s)\n", cli_errstr(&cli1));
777 close_connection(&cli1);
778 close_connection(&cli2);
780 printf("finished locktest3\n");
783 #define EXPECTED(ret, v) if ((ret) != (v)) printf("** ")
786 looks at overlapping locks
788 static void run_locktest4(int dummy)
790 static struct cli_state cli1, cli2;
791 char *fname = "\\lockt4.lck";
796 if (!open_connection(&cli1) || !open_connection(&cli2)) {
800 cli_sockopt(&cli1, sockops);
801 cli_sockopt(&cli2, sockops);
803 printf("starting locktest4\n");
805 cli_unlink(&cli1, fname);
807 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
808 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
810 memset(buf, 0, sizeof(buf));
812 if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
813 printf("Failed to create file\n");
817 ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
818 cli_lock(&cli1, fnum1, 2, 4, 0, WRITE_LOCK);
819 EXPECTED(ret, False);
820 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
822 ret = cli_lock(&cli1, fnum1, 10, 4, 0, READ_LOCK) &&
823 cli_lock(&cli1, fnum1, 12, 4, 0, READ_LOCK);
825 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
827 ret = cli_lock(&cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
828 cli_lock(&cli2, fnum2, 22, 4, 0, WRITE_LOCK);
829 EXPECTED(ret, False);
830 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
832 ret = cli_lock(&cli1, fnum1, 30, 4, 0, READ_LOCK) &&
833 cli_lock(&cli2, fnum2, 32, 4, 0, READ_LOCK);
835 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
837 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
838 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 42, 4, 0, WRITE_LOCK));
839 EXPECTED(ret, False);
840 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
842 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
843 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 52, 4, 0, READ_LOCK));
845 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
847 ret = cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK) &&
848 cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK);
850 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
852 ret = cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
853 cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK);
854 EXPECTED(ret, False);
855 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
857 ret = cli_lock(&cli1, fnum1, 80, 4, 0, READ_LOCK) &&
858 cli_lock(&cli1, fnum1, 80, 4, 0, WRITE_LOCK);
859 EXPECTED(ret, False);
860 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
862 ret = cli_lock(&cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
863 cli_lock(&cli1, fnum1, 90, 4, 0, READ_LOCK);
865 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
867 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
868 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 100, 4, 0, READ_LOCK));
869 EXPECTED(ret, False);
870 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
872 ret = cli_lock(&cli1, fnum1, 110, 4, 0, READ_LOCK) &&
873 cli_lock(&cli1, fnum1, 112, 4, 0, READ_LOCK) &&
874 cli_unlock(&cli1, fnum1, 110, 6);
875 EXPECTED(ret, False);
876 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
879 ret = cli_lock(&cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
880 (cli_read(&cli2, fnum2, buf, 120, 4) == 4);
881 EXPECTED(ret, False);
882 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
884 ret = cli_lock(&cli1, fnum1, 130, 4, 0, READ_LOCK) &&
885 (cli_write(&cli2, fnum2, 0, buf, 130, 4) == 4);
886 EXPECTED(ret, False);
887 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
890 ret = cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
891 cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
892 cli_unlock(&cli1, fnum1, 140, 4) &&
893 cli_unlock(&cli1, fnum1, 140, 4);
895 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
898 ret = cli_lock(&cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
899 cli_lock(&cli1, fnum1, 150, 4, 0, READ_LOCK) &&
900 cli_unlock(&cli1, fnum1, 150, 4) &&
901 (cli_read(&cli2, fnum2, buf, 150, 4) == 4) &&
902 !(cli_write(&cli2, fnum2, 0, buf, 150, 4) == 4) &&
903 cli_unlock(&cli1, fnum1, 150, 4);
905 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
907 ret = cli_lock(&cli1, fnum1, 160, 4, 0, READ_LOCK) &&
908 cli_unlock(&cli1, fnum1, 160, 4) &&
909 (cli_write(&cli2, fnum2, 0, buf, 160, 4) == 4) &&
910 (cli_read(&cli2, fnum2, buf, 160, 4) == 4);
912 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
914 ret = cli_lock(&cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
915 cli_unlock(&cli1, fnum1, 170, 4) &&
916 (cli_write(&cli2, fnum2, 0, buf, 170, 4) == 4) &&
917 (cli_read(&cli2, fnum2, buf, 170, 4) == 4);
919 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
921 ret = cli_lock(&cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
922 cli_lock(&cli1, fnum1, 190, 4, 0, READ_LOCK) &&
923 cli_unlock(&cli1, fnum1, 190, 4) &&
924 !(cli_write(&cli2, fnum2, 0, buf, 190, 4) == 4) &&
925 (cli_read(&cli2, fnum2, buf, 190, 4) == 4);
927 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
930 cli_close(&cli1, fnum1);
931 cli_close(&cli1, fnum2);
932 cli_unlink(&cli1, fname);
933 close_connection(&cli1);
934 close_connection(&cli2);
936 printf("finished locktest4\n");
941 this produces a matrix of deny mode behaviour
943 static void run_denytest1(int dummy)
945 static struct cli_state cli1, cli2;
947 int f, d1, d2, o1, o2, x=0;
948 char *fnames[] = {"denytest1.exe", "denytest1.dat", NULL};
953 {DENY_DOS, "DENY_DOS"},
954 {DENY_ALL, "DENY_ALL"},
955 {DENY_WRITE, "DENY_WRITE"},
956 {DENY_READ, "DENY_READ"},
957 {DENY_NONE, "DENY_NONE"},
958 {DENY_FCB, "DENY_FCB"},
965 {O_RDONLY, "O_RDONLY"},
966 {O_WRONLY, "O_WRONLY"},
969 if (!open_connection(&cli1) || !open_connection(&cli2)) {
972 cli_sockopt(&cli1, sockops);
973 cli_sockopt(&cli2, sockops);
975 printf("starting denytest1\n");
977 for (f=0;fnames[f];f++) {
978 cli_unlink(&cli1, fnames[f]);
980 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
981 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
982 cli_close(&cli1, fnum1);
984 for (d1=0;deny_modes[d1].name;d1++)
985 for (o1=0;open_modes[o1].name;o1++)
986 for (d2=0;deny_modes[d2].name;d2++)
987 for (o2=0;open_modes[o2].name;o2++) {
988 fnum1 = cli_open(&cli1, fnames[f],
991 fnum2 = cli_open(&cli2, fnames[f],
995 printf("%s %8s %10s %8s %10s ",
1000 deny_modes[d2].name);
1004 } else if (fnum2 == -1) {
1007 if (cli_read(&cli2, fnum2, (void *)&x, 0, 1) == 1) {
1010 if (cli_write(&cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
1016 cli_close(&cli1, fnum1);
1017 cli_close(&cli2, fnum2);
1020 cli_unlink(&cli1, fnames[f]);
1023 close_connection(&cli1);
1024 close_connection(&cli2);
1026 printf("finshed denytest1\n");
1031 this produces a matrix of deny mode behaviour for two opens on the
1034 static void run_denytest2(int dummy)
1036 static struct cli_state cli1;
1038 int f, d1, d2, o1, o2, x=0;
1039 char *fnames[] = {"denytest2.exe", "denytest2.dat", NULL};
1044 {DENY_DOS, "DENY_DOS"},
1045 {DENY_ALL, "DENY_ALL"},
1046 {DENY_WRITE, "DENY_WRITE"},
1047 {DENY_READ, "DENY_READ"},
1048 {DENY_NONE, "DENY_NONE"},
1049 {DENY_FCB, "DENY_FCB"},
1056 {O_RDONLY, "O_RDONLY"},
1057 {O_WRONLY, "O_WRONLY"},
1060 if (!open_connection(&cli1)) {
1063 cli_sockopt(&cli1, sockops);
1065 printf("starting denytest2\n");
1067 for (f=0;fnames[f];f++) {
1068 cli_unlink(&cli1, fnames[f]);
1070 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1071 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1072 cli_close(&cli1, fnum1);
1074 for (d1=0;deny_modes[d1].name;d1++)
1075 for (o1=0;open_modes[o1].name;o1++)
1076 for (d2=0;deny_modes[d2].name;d2++)
1077 for (o2=0;open_modes[o2].name;o2++) {
1078 fnum1 = cli_open(&cli1, fnames[f],
1081 fnum2 = cli_open(&cli1, fnames[f],
1085 printf("%s %8s %10s %8s %10s ",
1087 open_modes[o1].name,
1088 deny_modes[d1].name,
1089 open_modes[o2].name,
1090 deny_modes[d2].name);
1094 } else if (fnum2 == -1) {
1097 if (cli_read(&cli1, fnum2, (void *)&x, 0, 1) == 1) {
1100 if (cli_write(&cli1, fnum2, 0, (void *)&x, 0, 1) == 1) {
1106 cli_close(&cli1, fnum1);
1107 cli_close(&cli1, fnum2);
1110 cli_unlink(&cli1, fnames[f]);
1113 close_connection(&cli1);
1115 printf("finshed denytest2\n");
1119 test whether fnums and tids open on one VC are available on another (a major
1122 static void run_fdpasstest(int dummy)
1124 static struct cli_state cli1, cli2;
1125 char *fname = "\\fdpass.tst";
1129 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1132 cli_sockopt(&cli1, sockops);
1133 cli_sockopt(&cli2, sockops);
1135 printf("starting fdpasstest\n");
1137 cli_unlink(&cli1, fname);
1139 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1141 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1145 if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
1146 printf("write failed (%s)\n", cli_errstr(&cli1));
1150 cli2.vuid = cli1.vuid;
1151 cli2.cnum = cli1.cnum;
1152 cli2.pid = cli1.pid;
1155 if (cli_read(&cli2, fnum1, buf, 0, 13) == 13) {
1156 printf("read succeeded! nasty security hole [%s]\n",
1161 cli_close(&cli1, fnum1);
1162 cli_unlink(&cli1, fname);
1164 close_connection(&cli1);
1165 close_connection(&cli2);
1167 printf("finished fdpasstest\n");
1172 This test checks that
1174 1) the server does not allow an unlink on a file that is open
1176 static void run_unlinktest(int dummy)
1178 static struct cli_state cli;
1179 char *fname = "\\unlink.tst";
1182 if (!open_connection(&cli)) {
1186 cli_sockopt(&cli, sockops);
1188 printf("starting unlink test\n");
1190 cli_unlink(&cli, fname);
1192 cli_setpid(&cli, 1);
1194 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1196 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
1200 if (cli_unlink(&cli, fname)) {
1201 printf("error: server allowed unlink on an open file\n");
1204 cli_close(&cli, fnum);
1205 cli_unlink(&cli, fname);
1207 close_connection(&cli);
1209 printf("unlink test finished\n");
1214 test how many open files this server supports on the one socket
1216 static void run_maxfidtest(int dummy)
1218 static struct cli_state cli;
1219 char *template = "\\maxfid.%d.%d";
1228 printf("failed to connect\n");
1232 cli_sockopt(&cli, sockops);
1236 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1237 if (cli_open(&cli, fname,
1238 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
1240 printf("open of %s failed (%s)\n",
1241 fname, cli_errstr(&cli));
1242 printf("maximum fnum is %d\n", fnum);
1248 printf("cleaning up\n");
1251 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1252 if (cli_unlink(&cli, fname)) {
1253 printf("unlink of %s failed (%s)\n",
1254 fname, cli_errstr(&cli));
1258 printf("maxfid test finished\n");
1259 close_connection(&cli);
1262 /* generate a random buffer */
1263 static void rand_buf(char *buf, int len)
1266 *buf = (char)sys_random();
1271 /* send random IPC commands */
1272 static void run_randomipc(int dummy)
1274 char *rparam = NULL;
1278 int api, param_len, i;
1279 static struct cli_state cli;
1281 printf("starting random ipc test\n");
1283 if (!open_connection(&cli)) {
1287 for (i=0;i<50000;i++) {
1288 api = sys_random() % 500;
1289 param_len = (sys_random() % 64);
1291 rand_buf(param, param_len);
1296 param, param_len, 8,
1297 NULL, 0, BUFFER_SIZE,
1302 close_connection(&cli);
1304 printf("finished random ipc test\n");
1309 static void browse_callback(const char *sname, uint32 stype,
1310 const char *comment)
1312 printf("\t%20.20s %08x %s\n", sname, stype, comment);
1318 This test checks the browse list code
1321 static void run_browsetest(int dummy)
1323 static struct cli_state cli;
1325 printf("starting browse test\n");
1327 if (!open_connection(&cli)) {
1331 printf("domain list:\n");
1332 cli_NetServerEnum(&cli, cli.server_domain,
1333 SV_TYPE_DOMAIN_ENUM,
1336 printf("machine list:\n");
1337 cli_NetServerEnum(&cli, cli.server_domain,
1341 close_connection(&cli);
1343 printf("browse test finished\n");
1348 This checks how the getatr calls works
1350 static void run_attrtest(int dummy)
1352 static struct cli_state cli;
1355 char *fname = "\\attrib.tst";
1357 printf("starting attrib test\n");
1359 if (!open_connection(&cli)) {
1363 cli_unlink(&cli, fname);
1364 fnum = cli_open(&cli, fname,
1365 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1366 cli_close(&cli, fnum);
1367 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1368 printf("getatr failed (%s)\n", cli_errstr(&cli));
1371 if (abs(t - time(NULL)) > 2) {
1372 printf("ERROR: SMBgetatr bug. time is %s",
1377 t2 = t-60*60*24; /* 1 day ago */
1379 if (!cli_setatr(&cli, fname, 0, t2)) {
1380 printf("setatr failed (%s)\n", cli_errstr(&cli));
1383 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1384 printf("getatr failed (%s)\n", cli_errstr(&cli));
1388 printf("ERROR: getatr/setatr bug. times are\n%s",
1390 printf("%s", ctime(&t2));
1393 cli_unlink(&cli, fname);
1395 close_connection(&cli);
1397 printf("attrib test finished\n");
1402 This checks a couple of trans2 calls
1404 static void run_trans2test(int dummy)
1406 static struct cli_state cli;
1409 time_t c_time, a_time, m_time, w_time, m_time2;
1410 char *fname = "\\trans2.tst";
1411 char *dname = "\\trans2";
1412 char *fname2 = "\\trans2\\trans2.tst";
1414 printf("starting trans2 test\n");
1416 if (!open_connection(&cli)) {
1420 cli_unlink(&cli, fname);
1421 fnum = cli_open(&cli, fname,
1422 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1423 if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
1425 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
1427 cli_close(&cli, fnum);
1431 cli_unlink(&cli, fname);
1432 fnum = cli_open(&cli, fname,
1433 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1434 cli_close(&cli, fnum);
1436 if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
1437 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
1439 if (c_time != m_time) {
1440 printf("create time=%s", ctime(&c_time));
1441 printf("modify time=%s", ctime(&m_time));
1442 printf("This system appears to have sticky create times\n");
1444 if (a_time % (60*60) == 0) {
1445 printf("access time=%s", ctime(&a_time));
1446 printf("This system appears to set a midnight access time\n");
1449 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1450 printf("ERROR: totally incorrect times - maybe word reversed?\n");
1455 cli_unlink(&cli, fname);
1456 fnum = cli_open(&cli, fname,
1457 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1458 cli_close(&cli, fnum);
1459 if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time,
1460 &w_time, &size, NULL, NULL)) {
1461 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1463 if (w_time < 60*60*24*2) {
1464 printf("write time=%s", ctime(&w_time));
1465 printf("This system appears to set a initial 0 write time\n");
1469 cli_unlink(&cli, fname);
1472 /* check if the server updates the directory modification time
1473 when creating a new file */
1474 if (!cli_mkdir(&cli, dname)) {
1475 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
1478 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time,
1479 &w_time, &size, NULL, NULL)) {
1480 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1483 fnum = cli_open(&cli, fname2,
1484 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1485 cli_write(&cli, fnum, 0, (char *)&fnum, 0, sizeof(fnum));
1486 cli_close(&cli, fnum);
1487 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2,
1488 &w_time, &size, NULL, NULL)) {
1489 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1491 if (m_time2 == m_time)
1492 printf("This system does not update directory modification times\n");
1494 cli_unlink(&cli, fname2);
1495 cli_rmdir(&cli, dname);
1498 close_connection(&cli);
1500 printf("trans2 test finished\n");
1505 this is a harness for some oplock tests
1507 static void run_oplock(int dummy)
1509 static struct cli_state cli1;
1510 char *fname = "\\lockt1.lck";
1513 printf("starting oplock test\n");
1515 if (!open_connection(&cli1)) {
1519 cli_unlink(&cli1, fname);
1521 cli_sockopt(&cli1, sockops);
1523 cli1.use_oplocks = True;
1525 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1527 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1531 cli1.use_oplocks = False;
1533 cli_unlink(&cli1, fname);
1534 cli_unlink(&cli1, fname);
1536 if (!cli_close(&cli1, fnum1)) {
1537 printf("close2 failed (%s)\n", cli_errstr(&cli1));
1541 if (!cli_unlink(&cli1, fname)) {
1542 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1547 close_connection(&cli1);
1549 printf("finished oplock test\n");
1553 static void list_fn(file_info *finfo, const char *name)
1559 test directory listing speed
1561 static void run_dirtest(int dummy)
1564 static struct cli_state cli;
1568 printf("starting directory test\n");
1570 if (!open_connection(&cli)) {
1574 cli_sockopt(&cli, sockops);
1577 for (i=0;i<numops;i++) {
1579 slprintf(fname, sizeof(fname), "%x", (int)random());
1580 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
1582 fprintf(stderr,"Failed to open %s\n", fname);
1585 cli_close(&cli, fnum);
1590 printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn));
1591 printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn));
1592 printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn));
1594 printf("dirtest core %g seconds\n", end_timer() - t1);
1597 for (i=0;i<numops;i++) {
1599 slprintf(fname, sizeof(fname), "%x", (int)random());
1600 cli_unlink(&cli, fname);
1603 close_connection(&cli);
1605 printf("finished dirtest\n");
1610 static double create_procs(void (*fn)(int))
1613 volatile int *child_status;
1621 child_status = (volatile int *)shm_setup(sizeof(int)*nprocs);
1622 if (!child_status) {
1623 printf("Failed to setup shared memory\n");
1627 memset((char *)child_status, 0, sizeof(int)*nprocs);
1629 for (i=0;i<nprocs;i++) {
1631 pid_t mypid = getpid();
1632 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
1634 slprintf(myname,sizeof(myname),"CLIENT%d", i);
1637 memset(¤t_cli, 0, sizeof(current_cli));
1638 if (open_connection(¤t_cli)) break;
1640 printf("pid %d failed to start\n", (int)getpid());
1646 child_status[i] = getpid();
1648 while (child_status[i]) msleep(2);
1657 for (i=0;i<nprocs;i++) {
1658 if (child_status[i]) synccount++;
1660 if (synccount == nprocs) break;
1662 } while (end_timer() < 30);
1664 if (synccount != nprocs) {
1665 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
1669 /* start the client load */
1672 for (i=0;i<nprocs;i++) {
1673 child_status[i] = 0;
1676 printf("%d clients started\n", nprocs);
1678 for (i=0;i<nprocs;i++) {
1679 waitpid(0, &status, 0);
1687 #define FLAG_MULTIPROC 1
1694 {"FDPASS", run_fdpasstest, 0},
1695 {"LOCK1", run_locktest1, 0},
1696 {"LOCK2", run_locktest2, 0},
1697 {"LOCK3", run_locktest3, 0},
1698 {"LOCK4", run_locktest4, 0},
1699 {"UNLINK", run_unlinktest, 0},
1700 {"BROWSE", run_browsetest, 0},
1701 {"ATTR", run_attrtest, 0},
1702 {"TRANS2", run_trans2test, 0},
1703 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
1704 {"TORTURE",run_torture, FLAG_MULTIPROC},
1705 {"RANDOMIPC", run_randomipc, 0},
1706 {"NBW95", run_nbw95, 0},
1707 {"NBWNT", run_nbwnt, 0},
1708 {"OPLOCK", run_oplock, 0},
1709 {"DIR", run_dirtest, 0},
1710 {"DENY1", run_denytest1, 0},
1711 {"DENY2", run_denytest2, 0},
1712 {"TCON", run_tcon_test, 0},
1716 /****************************************************************************
1717 run a specified test or "ALL"
1718 ****************************************************************************/
1719 static void run_test(char *name)
1722 if (strequal(name,"ALL")) {
1723 for (i=0;torture_ops[i].name;i++) {
1724 run_test(torture_ops[i].name);
1728 for (i=0;torture_ops[i].name;i++) {
1729 if (strequal(name, torture_ops[i].name)) {
1731 printf("Running %s\n", name);
1732 if (torture_ops[i].flags & FLAG_MULTIPROC) {
1733 create_procs(torture_ops[i].fn);
1735 torture_ops[i].fn(0);
1737 printf("%s took %g secs\n\n", name, end_timer());
1743 static void usage(void)
1747 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
1749 printf("\t-U user%%pass\n");
1750 printf("\t-N numprocs\n");
1751 printf("\t-n my_netbios_name\n");
1752 printf("\t-W workgroup\n");
1753 printf("\t-o num_operations\n");
1754 printf("\t-O socket_options\n");
1755 printf("\t-m maximum protocol\n");
1758 printf("tests are:");
1759 for (i=0;torture_ops[i].name;i++) {
1760 printf(" %s", torture_ops[i].name);
1764 printf("default test is ALL\n");
1773 /****************************************************************************
1775 ****************************************************************************/
1776 int main(int argc,char *argv[])
1781 extern char *optarg;
1784 static pstring servicesf = CONFIGFILE;
1788 setbuffer(stdout, NULL, 0);
1790 charset_initialise();
1792 lp_load(servicesf,True,False,False);
1799 for(p = argv[1]; *p; p++)
1803 if (strncmp(argv[1], "//", 2)) {
1807 fstrcpy(host, &argv[1][2]);
1808 p = strchr(&host[2],'/');
1813 fstrcpy(share, p+1);
1817 if (*username == 0 && getenv("LOGNAME")) {
1818 pstrcpy(username,getenv("LOGNAME"));
1825 fstrcpy(workgroup, lp_workgroup());
1827 while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
1830 fstrcpy(workgroup,optarg);
1833 max_protocol = interpret_protocol(optarg, max_protocol);
1836 nprocs = atoi(optarg);
1839 numops = atoi(optarg);
1845 fstrcpy(myname, optarg);
1848 pstrcpy(username,optarg);
1849 p = strchr(username,'%');
1852 pstrcpy(password, p+1);
1857 printf("Unknown option %c (%d)\n", (char)opt, opt);
1864 p = getpass("Password:");
1866 pstrcpy(password, p);
1871 printf("host=%s share=%s user=%s myname=%s\n",
1872 host, share, username, myname);
1877 for (i=1;i<argc;i++) {