• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba/source/utils/
1/*
2   Unix SMB/Netbios implementation.
3   Version 1.9.
4   SMB torture tester
5   Copyright (C) Andrew Tridgell 1997-1998
6
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.
11
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.
16
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.
20*/
21
22#define NO_SYSLOG
23
24#include "includes.h"
25
26static fstring host, workgroup, share, password, username, myname;
27static int max_protocol = PROTOCOL_NT1;
28static char *sockops="TCP_NODELAY";
29static int nprocs=1, numops=100;
30static struct cli_state current_cli;
31
32static double create_procs(void (*fn)(int));
33
34
35static struct timeval tp1,tp2;
36
37static void start_timer(void)
38{
39	gettimeofday(&tp1,NULL);
40}
41
42static double end_timer(void)
43{
44	gettimeofday(&tp2,NULL);
45	return((tp2.tv_sec - tp1.tv_sec) +
46	       (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
47}
48
49
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
52   exit
53
54   The memory is not zeroed
55
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
58   */
59static void *shm_setup(int size)
60{
61	int shmid;
62	void *ret;
63
64	shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
65	if (shmid == -1) {
66		printf("can't get shared memory\n");
67		exit(1);
68	}
69	ret = (void *)shmat(shmid, 0, 0);
70	if (!ret || ret == (void *)-1) {
71		printf("can't attach to shared memory\n");
72		return NULL;
73	}
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
78
79	   See Stevens "advanced programming in unix env" for details
80	   */
81	shmctl(shmid, IPC_RMID, 0);
82
83	return ret;
84}
85
86
87static BOOL open_connection(struct cli_state *c)
88{
89	struct nmb_name called, calling;
90	struct in_addr ip;
91	extern struct in_addr ipzero;
92
93	ZERO_STRUCTP(c);
94
95	make_nmb_name(&calling, myname, 0x0);
96	make_nmb_name(&called , host, 0x20);
97
98	ip = ipzero;
99
100	if (!cli_initialise(c) || !cli_connect(c, host, &ip)) {
101		printf("Failed to connect with %s\n", host);
102		return False;
103	}
104
105	c->timeout = 120000; /* set a really long timeout (2 minutes) */
106
107	if (!cli_session_request(c, &calling, &called)) {
108		printf("%s rejected the session\n",host);
109		cli_shutdown(c);
110		return False;
111	}
112
113	if (!cli_negprot(c)) {
114		printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
115		cli_shutdown(c);
116		return False;
117	}
118
119	if (!cli_session_setup(c, username,
120			       password, strlen(password),
121			       password, strlen(password),
122			       workgroup)) {
123		printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
124		cli_shutdown(c);
125		return False;
126	}
127
128	if (!cli_send_tconX(c, share, "?????",
129			    password, strlen(password)+1)) {
130		printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
131		cli_shutdown(c);
132		return False;
133	}
134
135	return True;
136}
137
138
139
140static void close_connection(struct cli_state *c)
141{
142	if (!cli_tdis(c)) {
143		printf("tdis failed (%s)\n", cli_errstr(c));
144	}
145
146	cli_shutdown(c);
147}
148
149
150/* check if the server produced the expected error code */
151static BOOL check_error(struct cli_state *c,
152			uint8 eclass, uint32 ecode, uint32 nterr)
153{
154	uint8 class;
155	uint32 num;
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);
163		return False;
164	}
165	return True;
166}
167
168
169static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
170{
171	while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) {
172		if (!check_error(c, ERRDOS, ERRlock, 0)) return False;
173	}
174	return True;
175}
176
177
178static BOOL rw_torture(struct cli_state *c)
179{
180	char *lockfname = "\\torture.lck";
181	fstring fname;
182	int fnum;
183	int fnum2;
184	pid_t pid2, pid = getpid();
185	int i, j;
186	char buf[1024];
187
188	fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
189			 DENY_NONE);
190	if (fnum2 == -1)
191		fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
192	if (fnum2 == -1) {
193		printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
194		return False;
195	}
196
197
198	for (i=0;i<numops;i++) {
199		unsigned n = (unsigned)sys_random()%10;
200		if (i % 10 == 0) {
201			printf("%d\r", i); fflush(stdout);
202		}
203		slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
204
205		if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
206			return False;
207		}
208
209		fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
210		if (fnum == -1) {
211			printf("open failed (%s)\n", cli_errstr(c));
212			break;
213		}
214
215		if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
216			printf("write failed (%s)\n", cli_errstr(c));
217		}
218
219		for (j=0;j<50;j++) {
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));
224			}
225		}
226
227		pid2 = 0;
228
229		if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
230			printf("read failed (%s)\n", cli_errstr(c));
231		}
232
233		if (pid2 != pid) {
234			printf("data corruption!\n");
235		}
236
237		if (!cli_close(c, fnum)) {
238			printf("close failed (%s)\n", cli_errstr(c));
239		}
240
241		if (!cli_unlink(c, fname)) {
242			printf("unlink failed (%s)\n", cli_errstr(c));
243		}
244
245		if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int))) {
246			printf("unlock failed (%s)\n", cli_errstr(c));
247		}
248	}
249
250	cli_close(c, fnum2);
251	cli_unlink(c, lockfname);
252
253	printf("%d\n", i);
254
255	return True;
256}
257
258static void run_torture(int dummy)
259{
260	struct cli_state cli;
261
262	cli = current_cli;
263
264	cli_sockopt(&cli, sockops);
265
266	rw_torture(&cli);
267
268	close_connection(&cli);
269}
270
271int line_count = 0;
272
273/* run a test that simulates an approximate netbench client load */
274static void run_netbench(int client)
275{
276	struct cli_state cli;
277	int i;
278	fstring fname;
279	pstring line;
280	char cname[20];
281	FILE *f;
282	char *params[20];
283
284	cli = current_cli;
285
286	cli_sockopt(&cli, sockops);
287
288	nb_setup(&cli);
289
290	slprintf(cname,sizeof(fname), "CLIENT%d", client);
291
292	f = fopen("client.txt", "r");
293
294	if (!f) {
295		perror("client.txt");
296		return;
297	}
298
299	while (fgets(line, sizeof(line)-1, f)) {
300		line_count++;
301
302		line[strlen(line)-1] = 0;
303
304		/* printf("[%d] %s\n", line_count, line); */
305
306		all_string_sub(line,"CLIENT1", cname, sizeof(line));
307
308		for (i=0;i<20;i++) params[i] = "";
309
310		/* parse the command parameters */
311		params[0] = strtok(line," ");
312		i = 0;
313		while (params[i]) params[++i] = strtok(NULL," ");
314
315		params[i] = "";
316
317		if (i < 2) continue;
318
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")) {
325				nb_mkdir(params[3]);
326			} else if (!strcmp(params[0],"CREATE")) {
327				nb_create(params[3], atoi(params[5]));
328			} else if (!strcmp(params[0],"SMBrmdir")) {
329				nb_rmdir(params[3]);
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]));
348			}
349		} else {
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;
358				nb_unlink(fname);
359			}
360		}
361	}
362	fclose(f);
363
364	slprintf(fname,sizeof(fname), "CLIENTS/CLIENT%d", client);
365	rmdir(fname);
366	rmdir("CLIENTS");
367
368	printf("+");
369
370	close_connection(&cli);
371}
372
373
374/* run a test that simulates an approximate netbench w9X client load */
375static void run_nbw95(int dummy)
376{
377	double t;
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
383           4MBit/sec. */
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);
386}
387
388/* run a test that simulates an approximate netbench wNT client load */
389static void run_nbwnt(int dummy)
390{
391	double t;
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);
395}
396
397
398
399/*
400  This test checks for two things:
401
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
405 */
406static void run_locktest1(int dummy)
407{
408	static struct cli_state cli1, cli2;
409	char *fname = "\\lockt1.lck";
410	int fnum1, fnum2, fnum3;
411	time_t t1, t2;
412
413	if (!open_connection(&cli1) || !open_connection(&cli2)) {
414		return;
415	}
416	cli_sockopt(&cli1, sockops);
417	cli_sockopt(&cli2, sockops);
418
419	printf("starting locktest1\n");
420
421	cli_unlink(&cli1, fname);
422
423	fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
424	if (fnum1 == -1) {
425		printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
426		return;
427	}
428	fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
429	if (fnum2 == -1) {
430		printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
431		return;
432	}
433	fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
434	if (fnum3 == -1) {
435		printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
436		return;
437	}
438
439	if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
440		printf("lock1 failed (%s)\n", cli_errstr(&cli1));
441		return;
442	}
443
444
445	if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
446		printf("lock2 succeeded! This is a locking bug\n");
447		return;
448	} else {
449		if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
450	}
451
452
453	printf("Testing lock timeouts\n");
454	t1 = time(NULL);
455	if (cli_lock(&cli2, fnum3, 0, 4, 10*1000, WRITE_LOCK)) {
456		printf("lock3 succeeded! This is a locking bug\n");
457		return;
458	} else {
459		if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
460	}
461	t2 = time(NULL);
462
463	if (t2 - t1 < 5) {
464		printf("error: This server appears not to support timed lock requests\n");
465	}
466
467	if (!cli_close(&cli1, fnum2)) {
468		printf("close1 failed (%s)\n", cli_errstr(&cli1));
469		return;
470	}
471
472	if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
473		printf("lock4 succeeded! This is a locking bug\n");
474		return;
475	} else {
476		if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
477	}
478
479	if (!cli_close(&cli1, fnum1)) {
480		printf("close2 failed (%s)\n", cli_errstr(&cli1));
481		return;
482	}
483
484	if (!cli_close(&cli2, fnum3)) {
485		printf("close3 failed (%s)\n", cli_errstr(&cli2));
486		return;
487	}
488
489	if (!cli_unlink(&cli1, fname)) {
490		printf("unlink failed (%s)\n", cli_errstr(&cli1));
491		return;
492	}
493
494
495	close_connection(&cli1);
496	close_connection(&cli2);
497
498	printf("Passed locktest1\n");
499}
500
501
502/*
503  This test checks that
504
505  1) the server supports multiple locking contexts on the one SMB
506  connection, distinguished by PID.
507
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)
510
511  3) the server denies unlock requests by an incorrect client PID
512*/
513static void run_locktest2(int dummy)
514{
515	static struct cli_state cli;
516	char *fname = "\\lockt2.lck";
517	int fnum1, fnum2, fnum3;
518
519	if (!open_connection(&cli)) {
520		return;
521	}
522
523	cli_sockopt(&cli, sockops);
524
525	printf("starting locktest2\n");
526
527	cli_unlink(&cli, fname);
528
529	cli_setpid(&cli, 1);
530
531	fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
532	if (fnum1 == -1) {
533		printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
534		return;
535	}
536
537	fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
538	if (fnum2 == -1) {
539		printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
540		return;
541	}
542
543	cli_setpid(&cli, 2);
544
545	fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
546	if (fnum3 == -1) {
547		printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
548		return;
549	}
550
551	cli_setpid(&cli, 1);
552
553	if (!cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
554		printf("lock1 failed (%s)\n", cli_errstr(&cli));
555		return;
556	}
557
558	if (cli_lock(&cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
559		printf("lock2 succeeded! This is a locking bug\n");
560	} else {
561		if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
562	}
563
564	cli_setpid(&cli, 2);
565
566	if (cli_unlock(&cli, fnum1, 0, 8)) {
567		printf("unlock1 succeeded! This is a locking bug\n");
568	}
569
570	if (cli_lock(&cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
571		printf("lock3 succeeded! This is a locking bug\n");
572	} else {
573		if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
574	}
575
576	cli_setpid(&cli, 1);
577
578	if (!cli_close(&cli, fnum1)) {
579		printf("close1 failed (%s)\n", cli_errstr(&cli));
580		return;
581	}
582
583	if (!cli_close(&cli, fnum2)) {
584		printf("close2 failed (%s)\n", cli_errstr(&cli));
585		return;
586	}
587
588	if (!cli_close(&cli, fnum3)) {
589		printf("close3 failed (%s)\n", cli_errstr(&cli));
590		return;
591	}
592
593	close_connection(&cli);
594
595	printf("locktest2 finished\n");
596}
597
598
599/*
600  This test checks that
601
602  1) the server supports the full offset range in lock requests
603*/
604static void run_locktest3(int dummy)
605{
606	static struct cli_state cli1, cli2;
607	char *fname = "\\lockt3.lck";
608	int fnum1, fnum2, i;
609	uint32 offset;
610
611#define NEXT_OFFSET offset += (~(uint32)0) / numops
612
613	if (!open_connection(&cli1) || !open_connection(&cli2)) {
614		return;
615	}
616	cli_sockopt(&cli1, sockops);
617	cli_sockopt(&cli2, sockops);
618
619	printf("starting locktest3\n");
620
621	cli_unlink(&cli1, fname);
622
623	fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
624	if (fnum1 == -1) {
625		printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
626		return;
627	}
628	fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
629	if (fnum2 == -1) {
630		printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
631		return;
632	}
633
634	for (offset=i=0;i<numops;i++) {
635		NEXT_OFFSET;
636		if (!cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
637			printf("lock1 %d failed (%s)\n",
638			       i,
639			       cli_errstr(&cli1));
640			return;
641		}
642
643		if (!cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
644			printf("lock2 %d failed (%s)\n",
645			       i,
646			       cli_errstr(&cli1));
647			return;
648		}
649	}
650
651	for (offset=i=0;i<numops;i++) {
652		NEXT_OFFSET;
653
654		if (cli_lock(&cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
655			printf("error: lock1 %d succeeded!\n", i);
656			return;
657		}
658
659		if (cli_lock(&cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
660			printf("error: lock2 %d succeeded!\n", i);
661			return;
662		}
663
664		if (cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
665			printf("error: lock3 %d succeeded!\n", i);
666			return;
667		}
668
669		if (cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
670			printf("error: lock4 %d succeeded!\n", i);
671			return;
672		}
673	}
674
675	for (offset=i=0;i<numops;i++) {
676		NEXT_OFFSET;
677
678		if (!cli_unlock(&cli1, fnum1, offset-1, 1)) {
679			printf("unlock1 %d failed (%s)\n",
680			       i,
681			       cli_errstr(&cli1));
682			return;
683		}
684
685		if (!cli_unlock(&cli2, fnum2, offset-2, 1)) {
686			printf("unlock2 %d failed (%s)\n",
687			       i,
688			       cli_errstr(&cli1));
689			return;
690		}
691	}
692
693	if (!cli_close(&cli1, fnum1)) {
694		printf("close1 failed (%s)\n", cli_errstr(&cli1));
695	}
696
697	if (!cli_close(&cli2, fnum2)) {
698		printf("close2 failed (%s)\n", cli_errstr(&cli2));
699	}
700
701	if (!cli_unlink(&cli1, fname)) {
702		printf("unlink failed (%s)\n", cli_errstr(&cli1));
703		return;
704	}
705
706	close_connection(&cli1);
707	close_connection(&cli2);
708
709	printf("finished locktest3\n");
710}
711
712#define EXPECTED(ret, v) if ((ret) != (v)) printf("** ")
713
714/*
715  looks at overlapping locks
716*/
717static void run_locktest4(int dummy)
718{
719	static struct cli_state cli1, cli2;
720	char *fname = "\\lockt4.lck";
721	int fnum1, fnum2;
722	BOOL ret;
723	char buf[1000];
724
725	if (!open_connection(&cli1) || !open_connection(&cli2)) {
726		return;
727	}
728
729	cli_sockopt(&cli1, sockops);
730	cli_sockopt(&cli2, sockops);
731
732	printf("starting locktest4\n");
733
734	cli_unlink(&cli1, fname);
735
736	fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
737	fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
738
739	memset(buf, 0, sizeof(buf));
740
741	if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
742		printf("Failed to create file\n");
743		goto fail;
744	}
745
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");
750
751	ret = cli_lock(&cli1, fnum1, 10, 4, 0, READ_LOCK) &&
752	      cli_lock(&cli1, fnum1, 12, 4, 0, READ_LOCK);
753	EXPECTED(ret, True);
754	printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
755
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");
760
761	ret = cli_lock(&cli1, fnum1, 30, 4, 0, READ_LOCK) &&
762	      cli_lock(&cli2, fnum2, 32, 4, 0, READ_LOCK);
763	EXPECTED(ret, True);
764	printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
765
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");
770
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));
773	EXPECTED(ret, True);
774	printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
775
776	ret = cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK) &&
777	      cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK);
778	EXPECTED(ret, True);
779	printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
780
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");
785
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");
790
791	ret = cli_lock(&cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
792	      cli_lock(&cli1, fnum1, 90, 4, 0, READ_LOCK);
793	EXPECTED(ret, True);
794	printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
795
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");
800
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");
806
807
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");
812
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");
817
818
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);
823	EXPECTED(ret, True);
824	printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
825
826
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);
833	EXPECTED(ret, True);
834	printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
835
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);
840	EXPECTED(ret, True);
841	printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
842
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);
847	EXPECTED(ret, True);
848	printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
849
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);
855	EXPECTED(ret, True);
856	printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
857
858 fail:
859	cli_close(&cli1, fnum1);
860	cli_close(&cli1, fnum2);
861	cli_unlink(&cli1, fname);
862	close_connection(&cli1);
863	close_connection(&cli2);
864
865	printf("finished locktest4\n");
866}
867
868
869/*
870  this produces a matrix of deny mode behaviour
871 */
872static void run_denytest1(int dummy)
873{
874	static struct cli_state cli1, cli2;
875	int fnum1, fnum2;
876	int f, d1, d2, o1, o2, x=0;
877	char *fnames[] = {"denytest1.exe", "denytest1.dat", NULL};
878	struct {
879		int v;
880		char *name;
881	} deny_modes[] = {
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"},
888		{-1, NULL}};
889	struct {
890		int v;
891		char *name;
892	} open_modes[] = {
893		{O_RDWR, "O_RDWR"},
894		{O_RDONLY, "O_RDONLY"},
895		{O_WRONLY, "O_WRONLY"},
896		{-1, NULL}};
897
898	if (!open_connection(&cli1) || !open_connection(&cli2)) {
899		return;
900	}
901	cli_sockopt(&cli1, sockops);
902	cli_sockopt(&cli2, sockops);
903
904	printf("starting denytest1\n");
905
906	for (f=0;fnames[f];f++) {
907		cli_unlink(&cli1, fnames[f]);
908
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);
912
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],
918					 open_modes[o1].v,
919					 deny_modes[d1].v);
920			fnum2 = cli_open(&cli2, fnames[f],
921					 open_modes[o2].v,
922					 deny_modes[d2].v);
923
924			printf("%s %8s %10s    %8s %10s     ",
925			       fnames[f],
926			       open_modes[o1].name,
927			       deny_modes[d1].name,
928			       open_modes[o2].name,
929			       deny_modes[d2].name);
930
931			if (fnum1 == -1) {
932				printf("X");
933			} else if (fnum2 == -1) {
934				printf("-");
935			} else {
936				if (cli_read(&cli2, fnum2, (void *)&x, 0, 1) == 1) {
937					printf("R");
938				}
939				if (cli_write(&cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
940					printf("W");
941				}
942			}
943
944			printf("\n");
945			cli_close(&cli1, fnum1);
946			cli_close(&cli2, fnum2);
947		}
948
949		cli_unlink(&cli1, fnames[f]);
950	}
951
952	close_connection(&cli1);
953	close_connection(&cli2);
954
955	printf("finshed denytest1\n");
956}
957
958
959/*
960  this produces a matrix of deny mode behaviour for two opens on the
961  same connection
962 */
963static void run_denytest2(int dummy)
964{
965	static struct cli_state cli1;
966	int fnum1, fnum2;
967	int f, d1, d2, o1, o2, x=0;
968	char *fnames[] = {"denytest2.exe", "denytest2.dat", NULL};
969	struct {
970		int v;
971		char *name;
972	} deny_modes[] = {
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"},
979		{-1, NULL}};
980	struct {
981		int v;
982		char *name;
983	} open_modes[] = {
984		{O_RDWR, "O_RDWR"},
985		{O_RDONLY, "O_RDONLY"},
986		{O_WRONLY, "O_WRONLY"},
987		{-1, NULL}};
988
989	if (!open_connection(&cli1)) {
990		return;
991	}
992	cli_sockopt(&cli1, sockops);
993
994	printf("starting denytest2\n");
995
996	for (f=0;fnames[f];f++) {
997		cli_unlink(&cli1, fnames[f]);
998
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);
1002
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],
1008					 open_modes[o1].v,
1009					 deny_modes[d1].v);
1010			fnum2 = cli_open(&cli1, fnames[f],
1011					 open_modes[o2].v,
1012					 deny_modes[d2].v);
1013
1014			printf("%s %8s %10s    %8s %10s     ",
1015			       fnames[f],
1016			       open_modes[o1].name,
1017			       deny_modes[d1].name,
1018			       open_modes[o2].name,
1019			       deny_modes[d2].name);
1020
1021			if (fnum1 == -1) {
1022				printf("X");
1023			} else if (fnum2 == -1) {
1024				printf("-");
1025			} else {
1026				if (cli_read(&cli1, fnum2, (void *)&x, 0, 1) == 1) {
1027					printf("R");
1028				}
1029				if (cli_write(&cli1, fnum2, 0, (void *)&x, 0, 1) == 1) {
1030					printf("W");
1031				}
1032			}
1033
1034			printf("\n");
1035			cli_close(&cli1, fnum1);
1036			cli_close(&cli1, fnum2);
1037		}
1038
1039		cli_unlink(&cli1, fnames[f]);
1040	}
1041
1042	close_connection(&cli1);
1043
1044	printf("finshed denytest2\n");
1045}
1046
1047/*
1048test whether fnums and tids open on one VC are available on another (a major
1049security hole)
1050*/
1051static void run_fdpasstest(int dummy)
1052{
1053	static struct cli_state cli1, cli2;
1054	char *fname = "\\fdpass.tst";
1055	int fnum1;
1056	pstring buf;
1057
1058	if (!open_connection(&cli1) || !open_connection(&cli2)) {
1059		return;
1060	}
1061	cli_sockopt(&cli1, sockops);
1062	cli_sockopt(&cli2, sockops);
1063
1064	printf("starting fdpasstest\n");
1065
1066	cli_unlink(&cli1, fname);
1067
1068	fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1069	if (fnum1 == -1) {
1070		printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1071		return;
1072	}
1073
1074	if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
1075		printf("write failed (%s)\n", cli_errstr(&cli1));
1076		return;
1077	}
1078
1079	cli2.vuid = cli1.vuid;
1080	cli2.cnum = cli1.cnum;
1081	cli2.pid = cli1.pid;
1082
1083
1084	if (cli_read(&cli2, fnum1, buf, 0, 13) == 13) {
1085		printf("read succeeded! nasty security hole [%s]\n",
1086		       buf);
1087		return;
1088	}
1089
1090	cli_close(&cli1, fnum1);
1091	cli_unlink(&cli1, fname);
1092
1093	close_connection(&cli1);
1094	close_connection(&cli2);
1095
1096	printf("finished fdpasstest\n");
1097}
1098
1099
1100/*
1101  This test checks that
1102
1103  1) the server does not allow an unlink on a file that is open
1104*/
1105static void run_unlinktest(int dummy)
1106{
1107	static struct cli_state cli;
1108	char *fname = "\\unlink.tst";
1109	int fnum;
1110
1111	if (!open_connection(&cli)) {
1112		return;
1113	}
1114
1115	cli_sockopt(&cli, sockops);
1116
1117	printf("starting unlink test\n");
1118
1119	cli_unlink(&cli, fname);
1120
1121	cli_setpid(&cli, 1);
1122
1123	fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1124	if (fnum == -1) {
1125		printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
1126		return;
1127	}
1128
1129	if (cli_unlink(&cli, fname)) {
1130		printf("error: server allowed unlink on an open file\n");
1131	}
1132
1133	cli_close(&cli, fnum);
1134	cli_unlink(&cli, fname);
1135
1136	close_connection(&cli);
1137
1138	printf("unlink test finished\n");
1139}
1140
1141
1142/*
1143test how many open files this server supports on the one socket
1144*/
1145static void run_maxfidtest(int dummy)
1146{
1147	static struct cli_state cli;
1148	char *template = "\\maxfid.%d.%d";
1149	fstring fname;
1150	int fnum;
1151	int retries=4;
1152	int n = numops;
1153
1154	cli = current_cli;
1155
1156	if (retries <= 0) {
1157		printf("failed to connect\n");
1158		return;
1159	}
1160
1161	cli_sockopt(&cli, sockops);
1162
1163	fnum = 0;
1164	while (1) {
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) ==
1168		    -1) {
1169			printf("open of %s failed (%s)\n",
1170			       fname, cli_errstr(&cli));
1171			printf("maximum fnum is %d\n", fnum);
1172			break;
1173		}
1174		fnum++;
1175	}
1176
1177	printf("cleaning up\n");
1178	while (fnum > n) {
1179		fnum--;
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));
1184		}
1185	}
1186
1187	printf("maxfid test finished\n");
1188	close_connection(&cli);
1189}
1190
1191/* generate a random buffer */
1192static void rand_buf(char *buf, int len)
1193{
1194	while (len--) {
1195		*buf = (char)sys_random();
1196		buf++;
1197	}
1198}
1199
1200/* send random IPC commands */
1201static void run_randomipc(int dummy)
1202{
1203	char *rparam = NULL;
1204	char *rdata = NULL;
1205	int rdrcnt,rprcnt;
1206	pstring param;
1207	int api, param_len, i;
1208	static struct cli_state cli;
1209
1210	printf("starting random ipc test\n");
1211
1212	if (!open_connection(&cli)) {
1213		return;
1214	}
1215
1216	for (i=0;i<50000;i++) {
1217		api = sys_random() % 500;
1218		param_len = (sys_random() % 64);
1219
1220		rand_buf(param, param_len);
1221
1222		SSVAL(param,0,api);
1223
1224		cli_api(&cli,
1225			param, param_len, 8,
1226			NULL, 0, BUFFER_SIZE,
1227			&rparam, &rprcnt,
1228			&rdata, &rdrcnt);
1229	}
1230
1231	close_connection(&cli);
1232
1233	printf("finished random ipc test\n");
1234}
1235
1236
1237
1238static void browse_callback(const char *sname, uint32 stype,
1239			    const char *comment)
1240{
1241	printf("\t%20.20s %08x %s\n", sname, stype, comment);
1242}
1243
1244
1245
1246/*
1247  This test checks the browse list code
1248
1249*/
1250static void run_browsetest(int dummy)
1251{
1252	static struct cli_state cli;
1253
1254	printf("starting browse test\n");
1255
1256	if (!open_connection(&cli)) {
1257		return;
1258	}
1259
1260	printf("domain list:\n");
1261	cli_NetServerEnum(&cli, cli.server_domain,
1262			  SV_TYPE_DOMAIN_ENUM,
1263			  browse_callback);
1264
1265	printf("machine list:\n");
1266	cli_NetServerEnum(&cli, cli.server_domain,
1267			  SV_TYPE_ALL,
1268			  browse_callback);
1269
1270	close_connection(&cli);
1271
1272	printf("browse test finished\n");
1273}
1274
1275
1276/*
1277  This checks how the getatr calls works
1278*/
1279static void run_attrtest(int dummy)
1280{
1281	static struct cli_state cli;
1282	int fnum;
1283	time_t t, t2;
1284	char *fname = "\\attrib.tst";
1285
1286	printf("starting attrib test\n");
1287
1288	if (!open_connection(&cli)) {
1289		return;
1290	}
1291
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));
1298	}
1299
1300	if (abs(t - time(NULL)) > 2) {
1301		printf("ERROR: SMBgetatr bug. time is %s",
1302		       ctime(&t));
1303		t = time(NULL);
1304	}
1305
1306	t2 = t-60*60*24; /* 1 day ago */
1307
1308	if (!cli_setatr(&cli, fname, 0, t2)) {
1309		printf("setatr failed (%s)\n", cli_errstr(&cli));
1310	}
1311
1312	if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1313		printf("getatr failed (%s)\n", cli_errstr(&cli));
1314	}
1315
1316	if (t != t2) {
1317		printf("ERROR: getatr/setatr bug. times are\n%s",
1318		       ctime(&t));
1319		printf("%s", ctime(&t2));
1320	}
1321
1322	cli_unlink(&cli, fname);
1323
1324	close_connection(&cli);
1325
1326	printf("attrib test finished\n");
1327}
1328
1329
1330/*
1331  This checks a couple of trans2 calls
1332*/
1333static void run_trans2test(int dummy)
1334{
1335	static struct cli_state cli;
1336	int fnum;
1337	size_t size;
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";
1342
1343	printf("starting trans2 test\n");
1344
1345	if (!open_connection(&cli)) {
1346		return;
1347	}
1348
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,
1353			   NULL, NULL)) {
1354		printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
1355	}
1356	cli_close(&cli, fnum);
1357
1358	sleep(2);
1359
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);
1364
1365	if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
1366		printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
1367	} else {
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");
1372		}
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");
1376		}
1377
1378		if (abs(m_time - time(NULL)) > 60*60*24*7) {
1379			printf("ERROR: totally incorrect times - maybe word reversed?\n");
1380		}
1381	}
1382
1383
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));
1391	} else {
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");
1395		}
1396	}
1397
1398	cli_unlink(&cli, fname);
1399
1400
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));
1405	}
1406	sleep(3);
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));
1410	}
1411
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));
1419	} else {
1420		if (m_time2 == m_time)
1421			printf("This system does not update directory modification times\n");
1422	}
1423	cli_unlink(&cli, fname2);
1424	cli_rmdir(&cli, dname);
1425
1426
1427	close_connection(&cli);
1428
1429	printf("trans2 test finished\n");
1430}
1431
1432
1433/*
1434  this is a harness for some oplock tests
1435 */
1436static void run_oplock(int dummy)
1437{
1438	static struct cli_state cli1;
1439	char *fname = "\\lockt1.lck";
1440	int fnum1;
1441
1442	printf("starting oplock test\n");
1443
1444	if (!open_connection(&cli1)) {
1445		return;
1446	}
1447
1448	cli_unlink(&cli1, fname);
1449
1450	cli_sockopt(&cli1, sockops);
1451
1452	cli1.use_oplocks = True;
1453
1454	fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1455	if (fnum1 == -1) {
1456		printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1457		return;
1458	}
1459
1460	cli1.use_oplocks = False;
1461
1462	cli_unlink(&cli1, fname);
1463	cli_unlink(&cli1, fname);
1464
1465	if (!cli_close(&cli1, fnum1)) {
1466		printf("close2 failed (%s)\n", cli_errstr(&cli1));
1467		return;
1468	}
1469
1470	if (!cli_unlink(&cli1, fname)) {
1471		printf("unlink failed (%s)\n", cli_errstr(&cli1));
1472		return;
1473	}
1474
1475
1476	close_connection(&cli1);
1477
1478	printf("finished oplock test\n");
1479}
1480
1481
1482static void list_fn(file_info *finfo, const char *name)
1483{
1484
1485}
1486
1487/*
1488  test directory listing speed
1489 */
1490static void run_dirtest(int dummy)
1491{
1492	int i;
1493	static struct cli_state cli;
1494	int fnum;
1495	double t1;
1496
1497	printf("starting directory test\n");
1498
1499	if (!open_connection(&cli)) {
1500		return;
1501	}
1502
1503	cli_sockopt(&cli, sockops);
1504
1505	srandom(0);
1506	for (i=0;i<numops;i++) {
1507		fstring fname;
1508		slprintf(fname, sizeof(fname), "%x", (int)random());
1509		fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
1510		if (fnum == -1) {
1511			fprintf(stderr,"Failed to open %s\n", fname);
1512			return;
1513		}
1514		cli_close(&cli, fnum);
1515	}
1516
1517	t1 = end_timer();
1518
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));
1522
1523	printf("dirtest core %g seconds\n", end_timer() - t1);
1524
1525	srandom(0);
1526	for (i=0;i<numops;i++) {
1527		fstring fname;
1528		slprintf(fname, sizeof(fname), "%x", (int)random());
1529		cli_unlink(&cli, fname);
1530	}
1531
1532	close_connection(&cli);
1533
1534	printf("finished dirtest\n");
1535}
1536
1537
1538
1539static double create_procs(void (*fn)(int))
1540{
1541	int i, status;
1542	volatile int *child_status;
1543	int synccount;
1544	int tries = 8;
1545
1546	start_timer();
1547
1548	synccount = 0;
1549
1550	child_status = (volatile int *)shm_setup(sizeof(int)*nprocs);
1551	if (!child_status) {
1552		printf("Failed to setup shared memory\n");
1553		return end_timer();
1554	}
1555
1556	memset((char *)child_status, 0, sizeof(int)*nprocs);
1557
1558	for (i=0;i<nprocs;i++) {
1559		if (fork() == 0) {
1560			pid_t mypid = getpid();
1561			sys_srandom(((int)mypid) ^ ((int)time(NULL)));
1562
1563			slprintf(myname,sizeof(myname),"CLIENT%d", i);
1564
1565			while (1) {
1566				memset(&current_cli, 0, sizeof(current_cli));
1567				if (open_connection(&current_cli)) break;
1568				if (tries-- == 0) {
1569					printf("pid %d failed to start\n", (int)getpid());
1570					_exit(1);
1571				}
1572				msleep(10);
1573			}
1574
1575			child_status[i] = getpid();
1576
1577			while (child_status[i]) msleep(2);
1578
1579			fn(i);
1580			_exit(0);
1581		}
1582	}
1583
1584	do {
1585		synccount = 0;
1586		for (i=0;i<nprocs;i++) {
1587			if (child_status[i]) synccount++;
1588		}
1589		if (synccount == nprocs) break;
1590		msleep(10);
1591	} while (end_timer() < 30);
1592
1593	if (synccount != nprocs) {
1594		printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
1595		return end_timer();
1596	}
1597
1598	/* start the client load */
1599	start_timer();
1600
1601	for (i=0;i<nprocs;i++) {
1602		child_status[i] = 0;
1603	}
1604
1605	printf("%d clients started\n", nprocs);
1606
1607	for (i=0;i<nprocs;i++) {
1608		waitpid(0, &status, 0);
1609		printf("*");
1610	}
1611	printf("\n");
1612	return end_timer();
1613}
1614
1615
1616#define FLAG_MULTIPROC 1
1617
1618static struct {
1619	char *name;
1620	void (*fn)(int);
1621	unsigned flags;
1622} torture_ops[] = {
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},
1641	{NULL, NULL, 0}};
1642
1643
1644/****************************************************************************
1645run a specified test or "ALL"
1646****************************************************************************/
1647static void run_test(char *name)
1648{
1649	int i;
1650	if (strequal(name,"ALL")) {
1651		for (i=0;torture_ops[i].name;i++) {
1652			run_test(torture_ops[i].name);
1653		}
1654	}
1655
1656	for (i=0;torture_ops[i].name;i++) {
1657		if (strequal(name, torture_ops[i].name)) {
1658			start_timer();
1659			printf("Running %s\n", name);
1660			if (torture_ops[i].flags & FLAG_MULTIPROC) {
1661				create_procs(torture_ops[i].fn);
1662			} else {
1663				torture_ops[i].fn(0);
1664			}
1665			printf("%s took %g secs\n\n", name, end_timer());
1666		}
1667	}
1668}
1669
1670
1671static void usage(void)
1672{
1673	int i;
1674
1675	printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
1676
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");
1684	printf("\n\n");
1685
1686	printf("tests are:");
1687	for (i=0;torture_ops[i].name;i++) {
1688		printf(" %s", torture_ops[i].name);
1689	}
1690	printf("\n");
1691
1692	printf("default test is ALL\n");
1693
1694	exit(1);
1695}
1696
1697
1698
1699
1700
1701/****************************************************************************
1702  main program
1703****************************************************************************/
1704 int main(int argc,char *argv[])
1705{
1706	int opt, i;
1707	char *p;
1708	int gotpass = 0;
1709	extern char *optarg;
1710	extern int optind;
1711	extern FILE *dbf;
1712	static pstring servicesf = CONFIGFILE;
1713
1714	dbf = stdout;
1715
1716	setbuffer(stdout, NULL, 0);
1717
1718	charset_initialise();
1719
1720	lp_load(servicesf,True,False,False);
1721	load_interfaces();
1722
1723	if (argc < 2) {
1724		usage();
1725	}
1726
1727        for(p = argv[1]; *p; p++)
1728          if(*p == '\\')
1729            *p = '/';
1730
1731	if (strncmp(argv[1], "//", 2)) {
1732		usage();
1733	}
1734
1735	fstrcpy(host, &argv[1][2]);
1736	p = strchr(&host[2],'/');
1737	if (!p) {
1738		usage();
1739	}
1740	*p = 0;
1741	fstrcpy(share, p+1);
1742
1743	get_myname(myname);
1744
1745	if (*username == 0 && getenv("LOGNAME")) {
1746	  pstrcpy(username,getenv("LOGNAME"));
1747	}
1748
1749	argc--;
1750	argv++;
1751
1752
1753	fstrcpy(workgroup, lp_workgroup());
1754
1755	while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
1756		switch (opt) {
1757		case 'W':
1758			fstrcpy(workgroup,optarg);
1759			break;
1760		case 'm':
1761			max_protocol = interpret_protocol(optarg, max_protocol);
1762			break;
1763		case 'N':
1764			nprocs = atoi(optarg);
1765			break;
1766		case 'o':
1767			numops = atoi(optarg);
1768			break;
1769		case 'O':
1770			sockops = optarg;
1771			break;
1772		case 'n':
1773			fstrcpy(myname, optarg);
1774			break;
1775		case 'U':
1776			pstrcpy(username,optarg);
1777			p = strchr(username,'%');
1778			if (p) {
1779				*p = 0;
1780				pstrcpy(password, p+1);
1781				gotpass = 1;
1782			}
1783			break;
1784		default:
1785			printf("Unknown option %c (%d)\n", (char)opt, opt);
1786			usage();
1787		}
1788	}
1789
1790
1791	while (!gotpass) {
1792		p = getpass("Password:");
1793		if (p) {
1794			pstrcpy(password, p);
1795			gotpass = 1;
1796		}
1797	}
1798
1799	printf("host=%s share=%s user=%s myname=%s\n",
1800	       host, share, username, myname);
1801
1802	if (argc == 1) {
1803		run_test("ALL");
1804	} else {
1805		for (i=1;i<argc;i++) {
1806			run_test(argv[i]);
1807		}
1808	}
1809
1810	return(0);
1811}
1812