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");
503 This test checks that
505 1) the server supports multiple locking contexts on the one SMB
506 connection, distinguished by PID.
508 2) the server correctly fails overlapping locks made by the same PID (this
509 goes against POSIX behaviour, which is why it is tricky to implement)
511 3) the server denies unlock requests by an incorrect client PID
513 static void run_locktest2(int dummy)
515 static struct cli_state cli;
516 char *fname = "\\lockt2.lck";
517 int fnum1, fnum2, fnum3;
519 if (!open_connection(&cli)) {
523 cli_sockopt(&cli, sockops);
525 printf("starting locktest2\n");
527 cli_unlink(&cli, fname);
531 fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
533 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
537 fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
539 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
545 fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
547 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
553 if (!cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
554 printf("lock1 failed (%s)\n", cli_errstr(&cli));
558 if (cli_lock(&cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
559 printf("lock2 succeeded! This is a locking bug\n");
561 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
566 if (cli_unlock(&cli, fnum1, 0, 8)) {
567 printf("unlock1 succeeded! This is a locking bug\n");
570 if (cli_lock(&cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
571 printf("lock3 succeeded! This is a locking bug\n");
573 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
578 if (!cli_close(&cli, fnum1)) {
579 printf("close1 failed (%s)\n", cli_errstr(&cli));
583 if (!cli_close(&cli, fnum2)) {
584 printf("close2 failed (%s)\n", cli_errstr(&cli));
588 if (!cli_close(&cli, fnum3)) {
589 printf("close3 failed (%s)\n", cli_errstr(&cli));
593 close_connection(&cli);
595 printf("locktest2 finished\n");
600 This test checks that
602 1) the server supports the full offset range in lock requests
604 static void run_locktest3(int dummy)
606 static struct cli_state cli1, cli2;
607 char *fname = "\\lockt3.lck";
611 #define NEXT_OFFSET offset += (~(uint32)0) / numops
613 if (!open_connection(&cli1) || !open_connection(&cli2)) {
616 cli_sockopt(&cli1, sockops);
617 cli_sockopt(&cli2, sockops);
619 printf("starting locktest3\n");
621 cli_unlink(&cli1, fname);
623 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
625 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
628 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
630 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
634 for (offset=i=0;i<numops;i++) {
636 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
637 printf("lock1 %d failed (%s)\n",
643 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
644 printf("lock2 %d failed (%s)\n",
651 for (offset=i=0;i<numops;i++) {
654 if (cli_lock(&cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
655 printf("error: lock1 %d succeeded!\n", i);
659 if (cli_lock(&cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
660 printf("error: lock2 %d succeeded!\n", i);
664 if (cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
665 printf("error: lock3 %d succeeded!\n", i);
669 if (cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
670 printf("error: lock4 %d succeeded!\n", i);
675 for (offset=i=0;i<numops;i++) {
678 if (!cli_unlock(&cli1, fnum1, offset-1, 1)) {
679 printf("unlock1 %d failed (%s)\n",
685 if (!cli_unlock(&cli2, fnum2, offset-2, 1)) {
686 printf("unlock2 %d failed (%s)\n",
693 if (!cli_close(&cli1, fnum1)) {
694 printf("close1 failed (%s)\n", cli_errstr(&cli1));
697 if (!cli_close(&cli2, fnum2)) {
698 printf("close2 failed (%s)\n", cli_errstr(&cli2));
701 if (!cli_unlink(&cli1, fname)) {
702 printf("unlink failed (%s)\n", cli_errstr(&cli1));
706 close_connection(&cli1);
707 close_connection(&cli2);
709 printf("finished locktest3\n");
712 #define EXPECTED(ret, v) if ((ret) != (v)) printf("** ")
715 looks at overlapping locks
717 static void run_locktest4(int dummy)
719 static struct cli_state cli1, cli2;
720 char *fname = "\\lockt4.lck";
725 if (!open_connection(&cli1) || !open_connection(&cli2)) {
729 cli_sockopt(&cli1, sockops);
730 cli_sockopt(&cli2, sockops);
732 printf("starting locktest4\n");
734 cli_unlink(&cli1, fname);
736 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
737 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
739 memset(buf, 0, sizeof(buf));
741 if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
742 printf("Failed to create file\n");
746 ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
747 cli_lock(&cli1, fnum1, 2, 4, 0, WRITE_LOCK);
748 EXPECTED(ret, False);
749 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
751 ret = cli_lock(&cli1, fnum1, 10, 4, 0, READ_LOCK) &&
752 cli_lock(&cli1, fnum1, 12, 4, 0, READ_LOCK);
754 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
756 ret = cli_lock(&cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
757 cli_lock(&cli2, fnum2, 22, 4, 0, WRITE_LOCK);
758 EXPECTED(ret, False);
759 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
761 ret = cli_lock(&cli1, fnum1, 30, 4, 0, READ_LOCK) &&
762 cli_lock(&cli2, fnum2, 32, 4, 0, READ_LOCK);
764 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
766 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
767 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 42, 4, 0, WRITE_LOCK));
768 EXPECTED(ret, False);
769 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
771 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
772 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 52, 4, 0, READ_LOCK));
774 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
776 ret = cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK) &&
777 cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK);
779 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
781 ret = cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
782 cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK);
783 EXPECTED(ret, False);
784 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
786 ret = cli_lock(&cli1, fnum1, 80, 4, 0, READ_LOCK) &&
787 cli_lock(&cli1, fnum1, 80, 4, 0, WRITE_LOCK);
788 EXPECTED(ret, False);
789 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
791 ret = cli_lock(&cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
792 cli_lock(&cli1, fnum1, 90, 4, 0, READ_LOCK);
794 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
796 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
797 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 100, 4, 0, READ_LOCK));
798 EXPECTED(ret, False);
799 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
801 ret = cli_lock(&cli1, fnum1, 110, 4, 0, READ_LOCK) &&
802 cli_lock(&cli1, fnum1, 112, 4, 0, READ_LOCK) &&
803 cli_unlock(&cli1, fnum1, 110, 6);
804 EXPECTED(ret, False);
805 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
808 ret = cli_lock(&cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
809 (cli_read(&cli2, fnum2, buf, 120, 4) == 4);
810 EXPECTED(ret, False);
811 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
813 ret = cli_lock(&cli1, fnum1, 130, 4, 0, READ_LOCK) &&
814 (cli_write(&cli2, fnum2, 0, buf, 130, 4) == 4);
815 EXPECTED(ret, False);
816 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
819 ret = cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
820 cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
821 cli_unlock(&cli1, fnum1, 140, 4) &&
822 cli_unlock(&cli1, fnum1, 140, 4);
824 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
827 ret = cli_lock(&cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
828 cli_lock(&cli1, fnum1, 150, 4, 0, READ_LOCK) &&
829 cli_unlock(&cli1, fnum1, 150, 4) &&
830 (cli_read(&cli2, fnum2, buf, 150, 4) == 4) &&
831 !(cli_write(&cli2, fnum2, 0, buf, 150, 4) == 4) &&
832 cli_unlock(&cli1, fnum1, 150, 4);
834 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
836 ret = cli_lock(&cli1, fnum1, 160, 4, 0, READ_LOCK) &&
837 cli_unlock(&cli1, fnum1, 160, 4) &&
838 (cli_write(&cli2, fnum2, 0, buf, 160, 4) == 4) &&
839 (cli_read(&cli2, fnum2, buf, 160, 4) == 4);
841 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
843 ret = cli_lock(&cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
844 cli_unlock(&cli1, fnum1, 170, 4) &&
845 (cli_write(&cli2, fnum2, 0, buf, 170, 4) == 4) &&
846 (cli_read(&cli2, fnum2, buf, 170, 4) == 4);
848 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
850 ret = cli_lock(&cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
851 cli_lock(&cli1, fnum1, 190, 4, 0, READ_LOCK) &&
852 cli_unlock(&cli1, fnum1, 190, 4) &&
853 !(cli_write(&cli2, fnum2, 0, buf, 190, 4) == 4) &&
854 (cli_read(&cli2, fnum2, buf, 190, 4) == 4);
856 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
859 cli_close(&cli1, fnum1);
860 cli_close(&cli1, fnum2);
861 cli_unlink(&cli1, fname);
862 close_connection(&cli1);
863 close_connection(&cli2);
865 printf("finished locktest4\n");
870 this produces a matrix of deny mode behaviour
872 static void run_denytest1(int dummy)
874 static struct cli_state cli1, cli2;
876 int f, d1, d2, o1, o2, x=0;
877 char *fnames[] = {"denytest1.exe", "denytest1.dat", NULL};
882 {DENY_DOS, "DENY_DOS"},
883 {DENY_ALL, "DENY_ALL"},
884 {DENY_WRITE, "DENY_WRITE"},
885 {DENY_READ, "DENY_READ"},
886 {DENY_NONE, "DENY_NONE"},
887 {DENY_FCB, "DENY_FCB"},
894 {O_RDONLY, "O_RDONLY"},
895 {O_WRONLY, "O_WRONLY"},
898 if (!open_connection(&cli1) || !open_connection(&cli2)) {
901 cli_sockopt(&cli1, sockops);
902 cli_sockopt(&cli2, sockops);
904 printf("starting denytest1\n");
906 for (f=0;fnames[f];f++) {
907 cli_unlink(&cli1, fnames[f]);
909 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
910 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
911 cli_close(&cli1, fnum1);
913 for (d1=0;deny_modes[d1].name;d1++)
914 for (o1=0;open_modes[o1].name;o1++)
915 for (d2=0;deny_modes[d2].name;d2++)
916 for (o2=0;open_modes[o2].name;o2++) {
917 fnum1 = cli_open(&cli1, fnames[f],
920 fnum2 = cli_open(&cli2, fnames[f],
924 printf("%s %8s %10s %8s %10s ",
929 deny_modes[d2].name);
933 } else if (fnum2 == -1) {
936 if (cli_read(&cli2, fnum2, (void *)&x, 0, 1) == 1) {
939 if (cli_write(&cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
945 cli_close(&cli1, fnum1);
946 cli_close(&cli2, fnum2);
949 cli_unlink(&cli1, fnames[f]);
952 close_connection(&cli1);
953 close_connection(&cli2);
955 printf("finshed denytest1\n");
960 this produces a matrix of deny mode behaviour for two opens on the
963 static void run_denytest2(int dummy)
965 static struct cli_state cli1;
967 int f, d1, d2, o1, o2, x=0;
968 char *fnames[] = {"denytest2.exe", "denytest2.dat", NULL};
973 {DENY_DOS, "DENY_DOS"},
974 {DENY_ALL, "DENY_ALL"},
975 {DENY_WRITE, "DENY_WRITE"},
976 {DENY_READ, "DENY_READ"},
977 {DENY_NONE, "DENY_NONE"},
978 {DENY_FCB, "DENY_FCB"},
985 {O_RDONLY, "O_RDONLY"},
986 {O_WRONLY, "O_WRONLY"},
989 if (!open_connection(&cli1)) {
992 cli_sockopt(&cli1, sockops);
994 printf("starting denytest2\n");
996 for (f=0;fnames[f];f++) {
997 cli_unlink(&cli1, fnames[f]);
999 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1000 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1001 cli_close(&cli1, fnum1);
1003 for (d1=0;deny_modes[d1].name;d1++)
1004 for (o1=0;open_modes[o1].name;o1++)
1005 for (d2=0;deny_modes[d2].name;d2++)
1006 for (o2=0;open_modes[o2].name;o2++) {
1007 fnum1 = cli_open(&cli1, fnames[f],
1010 fnum2 = cli_open(&cli1, fnames[f],
1014 printf("%s %8s %10s %8s %10s ",
1016 open_modes[o1].name,
1017 deny_modes[d1].name,
1018 open_modes[o2].name,
1019 deny_modes[d2].name);
1023 } else if (fnum2 == -1) {
1026 if (cli_read(&cli1, fnum2, (void *)&x, 0, 1) == 1) {
1029 if (cli_write(&cli1, fnum2, 0, (void *)&x, 0, 1) == 1) {
1035 cli_close(&cli1, fnum1);
1036 cli_close(&cli1, fnum2);
1039 cli_unlink(&cli1, fnames[f]);
1042 close_connection(&cli1);
1044 printf("finshed denytest2\n");
1048 test whether fnums and tids open on one VC are available on another (a major
1051 static void run_fdpasstest(int dummy)
1053 static struct cli_state cli1, cli2;
1054 char *fname = "\\fdpass.tst";
1058 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1061 cli_sockopt(&cli1, sockops);
1062 cli_sockopt(&cli2, sockops);
1064 printf("starting fdpasstest\n");
1066 cli_unlink(&cli1, fname);
1068 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1070 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1074 if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
1075 printf("write failed (%s)\n", cli_errstr(&cli1));
1079 cli2.vuid = cli1.vuid;
1080 cli2.cnum = cli1.cnum;
1081 cli2.pid = cli1.pid;
1084 if (cli_read(&cli2, fnum1, buf, 0, 13) == 13) {
1085 printf("read succeeded! nasty security hole [%s]\n",
1090 cli_close(&cli1, fnum1);
1091 cli_unlink(&cli1, fname);
1093 close_connection(&cli1);
1094 close_connection(&cli2);
1096 printf("finished fdpasstest\n");
1101 This test checks that
1103 1) the server does not allow an unlink on a file that is open
1105 static void run_unlinktest(int dummy)
1107 static struct cli_state cli;
1108 char *fname = "\\unlink.tst";
1111 if (!open_connection(&cli)) {
1115 cli_sockopt(&cli, sockops);
1117 printf("starting unlink test\n");
1119 cli_unlink(&cli, fname);
1121 cli_setpid(&cli, 1);
1123 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1125 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
1129 if (cli_unlink(&cli, fname)) {
1130 printf("error: server allowed unlink on an open file\n");
1133 cli_close(&cli, fnum);
1134 cli_unlink(&cli, fname);
1136 close_connection(&cli);
1138 printf("unlink test finished\n");
1143 test how many open files this server supports on the one socket
1145 static void run_maxfidtest(int dummy)
1147 static struct cli_state cli;
1148 char *template = "\\maxfid.%d.%d";
1157 printf("failed to connect\n");
1161 cli_sockopt(&cli, sockops);
1165 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1166 if (cli_open(&cli, fname,
1167 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
1169 printf("open of %s failed (%s)\n",
1170 fname, cli_errstr(&cli));
1171 printf("maximum fnum is %d\n", fnum);
1177 printf("cleaning up\n");
1180 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1181 if (cli_unlink(&cli, fname)) {
1182 printf("unlink of %s failed (%s)\n",
1183 fname, cli_errstr(&cli));
1187 printf("maxfid test finished\n");
1188 close_connection(&cli);
1191 /* generate a random buffer */
1192 static void rand_buf(char *buf, int len)
1195 *buf = (char)sys_random();
1200 /* send random IPC commands */
1201 static void run_randomipc(int dummy)
1203 char *rparam = NULL;
1207 int api, param_len, i;
1208 static struct cli_state cli;
1210 printf("starting random ipc test\n");
1212 if (!open_connection(&cli)) {
1216 for (i=0;i<50000;i++) {
1217 api = sys_random() % 500;
1218 param_len = (sys_random() % 64);
1220 rand_buf(param, param_len);
1225 param, param_len, 8,
1226 NULL, 0, BUFFER_SIZE,
1231 close_connection(&cli);
1233 printf("finished random ipc test\n");
1238 static void browse_callback(const char *sname, uint32 stype,
1239 const char *comment)
1241 printf("\t%20.20s %08x %s\n", sname, stype, comment);
1247 This test checks the browse list code
1250 static void run_browsetest(int dummy)
1252 static struct cli_state cli;
1254 printf("starting browse test\n");
1256 if (!open_connection(&cli)) {
1260 printf("domain list:\n");
1261 cli_NetServerEnum(&cli, cli.server_domain,
1262 SV_TYPE_DOMAIN_ENUM,
1265 printf("machine list:\n");
1266 cli_NetServerEnum(&cli, cli.server_domain,
1270 close_connection(&cli);
1272 printf("browse test finished\n");
1277 This checks how the getatr calls works
1279 static void run_attrtest(int dummy)
1281 static struct cli_state cli;
1284 char *fname = "\\attrib.tst";
1286 printf("starting attrib test\n");
1288 if (!open_connection(&cli)) {
1292 cli_unlink(&cli, fname);
1293 fnum = cli_open(&cli, fname,
1294 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1295 cli_close(&cli, fnum);
1296 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1297 printf("getatr failed (%s)\n", cli_errstr(&cli));
1300 if (abs(t - time(NULL)) > 2) {
1301 printf("ERROR: SMBgetatr bug. time is %s",
1306 t2 = t-60*60*24; /* 1 day ago */
1308 if (!cli_setatr(&cli, fname, 0, t2)) {
1309 printf("setatr failed (%s)\n", cli_errstr(&cli));
1312 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1313 printf("getatr failed (%s)\n", cli_errstr(&cli));
1317 printf("ERROR: getatr/setatr bug. times are\n%s",
1319 printf("%s", ctime(&t2));
1322 cli_unlink(&cli, fname);
1324 close_connection(&cli);
1326 printf("attrib test finished\n");
1331 This checks a couple of trans2 calls
1333 static void run_trans2test(int dummy)
1335 static struct cli_state cli;
1338 time_t c_time, a_time, m_time, w_time, m_time2;
1339 char *fname = "\\trans2.tst";
1340 char *dname = "\\trans2";
1341 char *fname2 = "\\trans2\\trans2.tst";
1343 printf("starting trans2 test\n");
1345 if (!open_connection(&cli)) {
1349 cli_unlink(&cli, fname);
1350 fnum = cli_open(&cli, fname,
1351 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1352 if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
1354 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
1356 cli_close(&cli, fnum);
1360 cli_unlink(&cli, fname);
1361 fnum = cli_open(&cli, fname,
1362 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1363 cli_close(&cli, fnum);
1365 if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
1366 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
1368 if (c_time != m_time) {
1369 printf("create time=%s", ctime(&c_time));
1370 printf("modify time=%s", ctime(&m_time));
1371 printf("This system appears to have sticky create times\n");
1373 if (a_time % (60*60) == 0) {
1374 printf("access time=%s", ctime(&a_time));
1375 printf("This system appears to set a midnight access time\n");
1378 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1379 printf("ERROR: totally incorrect times - maybe word reversed?\n");
1384 cli_unlink(&cli, fname);
1385 fnum = cli_open(&cli, fname,
1386 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1387 cli_close(&cli, fnum);
1388 if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time,
1389 &w_time, &size, NULL, NULL)) {
1390 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1392 if (w_time < 60*60*24*2) {
1393 printf("write time=%s", ctime(&w_time));
1394 printf("This system appears to set a initial 0 write time\n");
1398 cli_unlink(&cli, fname);
1401 /* check if the server updates the directory modification time
1402 when creating a new file */
1403 if (!cli_mkdir(&cli, dname)) {
1404 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
1407 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time,
1408 &w_time, &size, NULL, NULL)) {
1409 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1412 fnum = cli_open(&cli, fname2,
1413 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1414 cli_write(&cli, fnum, 0, (char *)&fnum, 0, sizeof(fnum));
1415 cli_close(&cli, fnum);
1416 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2,
1417 &w_time, &size, NULL, NULL)) {
1418 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1420 if (m_time2 == m_time)
1421 printf("This system does not update directory modification times\n");
1423 cli_unlink(&cli, fname2);
1424 cli_rmdir(&cli, dname);
1427 close_connection(&cli);
1429 printf("trans2 test finished\n");
1434 this is a harness for some oplock tests
1436 static void run_oplock(int dummy)
1438 static struct cli_state cli1;
1439 char *fname = "\\lockt1.lck";
1442 printf("starting oplock test\n");
1444 if (!open_connection(&cli1)) {
1448 cli_unlink(&cli1, fname);
1450 cli_sockopt(&cli1, sockops);
1452 cli1.use_oplocks = True;
1454 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1456 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1460 cli1.use_oplocks = False;
1462 cli_unlink(&cli1, fname);
1463 cli_unlink(&cli1, fname);
1465 if (!cli_close(&cli1, fnum1)) {
1466 printf("close2 failed (%s)\n", cli_errstr(&cli1));
1470 if (!cli_unlink(&cli1, fname)) {
1471 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1476 close_connection(&cli1);
1478 printf("finished oplock test\n");
1482 static void list_fn(file_info *finfo, const char *name)
1488 test directory listing speed
1490 static void run_dirtest(int dummy)
1493 static struct cli_state cli;
1497 printf("starting directory test\n");
1499 if (!open_connection(&cli)) {
1503 cli_sockopt(&cli, sockops);
1506 for (i=0;i<numops;i++) {
1508 slprintf(fname, sizeof(fname), "%x", (int)random());
1509 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
1511 fprintf(stderr,"Failed to open %s\n", fname);
1514 cli_close(&cli, fnum);
1519 printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn));
1520 printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn));
1521 printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn));
1523 printf("dirtest core %g seconds\n", end_timer() - t1);
1526 for (i=0;i<numops;i++) {
1528 slprintf(fname, sizeof(fname), "%x", (int)random());
1529 cli_unlink(&cli, fname);
1532 close_connection(&cli);
1534 printf("finished dirtest\n");
1539 static double create_procs(void (*fn)(int))
1542 volatile int *child_status;
1550 child_status = (volatile int *)shm_setup(sizeof(int)*nprocs);
1551 if (!child_status) {
1552 printf("Failed to setup shared memory\n");
1556 memset((char *)child_status, 0, sizeof(int)*nprocs);
1558 for (i=0;i<nprocs;i++) {
1560 pid_t mypid = getpid();
1561 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
1563 slprintf(myname,sizeof(myname),"CLIENT%d", i);
1566 memset(¤t_cli, 0, sizeof(current_cli));
1567 if (open_connection(¤t_cli)) break;
1569 printf("pid %d failed to start\n", (int)getpid());
1575 child_status[i] = getpid();
1577 while (child_status[i]) msleep(2);
1586 for (i=0;i<nprocs;i++) {
1587 if (child_status[i]) synccount++;
1589 if (synccount == nprocs) break;
1591 } while (end_timer() < 30);
1593 if (synccount != nprocs) {
1594 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
1598 /* start the client load */
1601 for (i=0;i<nprocs;i++) {
1602 child_status[i] = 0;
1605 printf("%d clients started\n", nprocs);
1607 for (i=0;i<nprocs;i++) {
1608 waitpid(0, &status, 0);
1616 #define FLAG_MULTIPROC 1
1623 {"FDPASS", run_fdpasstest, 0},
1624 {"LOCK1", run_locktest1, 0},
1625 {"LOCK2", run_locktest2, 0},
1626 {"LOCK3", run_locktest3, 0},
1627 {"LOCK4", run_locktest4, 0},
1628 {"UNLINK", run_unlinktest, 0},
1629 {"BROWSE", run_browsetest, 0},
1630 {"ATTR", run_attrtest, 0},
1631 {"TRANS2", run_trans2test, 0},
1632 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
1633 {"TORTURE",run_torture, FLAG_MULTIPROC},
1634 {"RANDOMIPC", run_randomipc, 0},
1635 {"NBW95", run_nbw95, 0},
1636 {"NBWNT", run_nbwnt, 0},
1637 {"OPLOCK", run_oplock, 0},
1638 {"DIR", run_dirtest, 0},
1639 {"DENY1", run_denytest1, 0},
1640 {"DENY2", run_denytest2, 0},
1644 /****************************************************************************
1645 run a specified test or "ALL"
1646 ****************************************************************************/
1647 static void run_test(char *name)
1650 if (strequal(name,"ALL")) {
1651 for (i=0;torture_ops[i].name;i++) {
1652 run_test(torture_ops[i].name);
1656 for (i=0;torture_ops[i].name;i++) {
1657 if (strequal(name, torture_ops[i].name)) {
1659 printf("Running %s\n", name);
1660 if (torture_ops[i].flags & FLAG_MULTIPROC) {
1661 create_procs(torture_ops[i].fn);
1663 torture_ops[i].fn(0);
1665 printf("%s took %g secs\n\n", name, end_timer());
1671 static void usage(void)
1675 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
1677 printf("\t-U user%%pass\n");
1678 printf("\t-N numprocs\n");
1679 printf("\t-n my_netbios_name\n");
1680 printf("\t-W workgroup\n");
1681 printf("\t-o num_operations\n");
1682 printf("\t-O socket_options\n");
1683 printf("\t-m maximum protocol\n");
1686 printf("tests are:");
1687 for (i=0;torture_ops[i].name;i++) {
1688 printf(" %s", torture_ops[i].name);
1692 printf("default test is ALL\n");
1701 /****************************************************************************
1703 ****************************************************************************/
1704 int main(int argc,char *argv[])
1709 extern char *optarg;
1712 static pstring servicesf = CONFIGFILE;
1716 setbuffer(stdout, NULL, 0);
1718 charset_initialise();
1720 lp_load(servicesf,True,False,False);
1727 for(p = argv[1]; *p; p++)
1731 if (strncmp(argv[1], "//", 2)) {
1735 fstrcpy(host, &argv[1][2]);
1736 p = strchr(&host[2],'/');
1741 fstrcpy(share, p+1);
1745 if (*username == 0 && getenv("LOGNAME")) {
1746 pstrcpy(username,getenv("LOGNAME"));
1753 fstrcpy(workgroup, lp_workgroup());
1755 while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
1758 fstrcpy(workgroup,optarg);
1761 max_protocol = interpret_protocol(optarg, max_protocol);
1764 nprocs = atoi(optarg);
1767 numops = atoi(optarg);
1773 fstrcpy(myname, optarg);
1776 pstrcpy(username,optarg);
1777 p = strchr(username,'%');
1780 pstrcpy(password, p+1);
1785 printf("Unknown option %c (%d)\n", (char)opt, opt);
1792 p = getpass("Password:");
1794 pstrcpy(password, p);
1799 printf("host=%s share=%s user=%s myname=%s\n",
1800 host, share, username, myname);
1805 for (i=1;i<argc;i++) {