rpc_server/srv_lsa.c: Bring into sync with 2.0.x.
[nivanova/samba-autobuild/.git] / source3 / utils / torture.c
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 #include <sys/ipc.h>
26 #include <sys/shm.h>
27
28 static fstring host, workgroup, share, password, username, myname;
29 static int max_protocol = PROTOCOL_NT1;
30 static char *sockops="TCP_NODELAY";
31 static int nprocs=1, numops=100;
32 static struct cli_state current_cli;
33
34 static double create_procs(void (*fn)(int));
35
36
37 static struct timeval tp1,tp2;
38
39 static void start_timer(void)
40 {
41         gettimeofday(&tp1,NULL);
42 }
43
44 static double end_timer(void)
45 {
46         gettimeofday(&tp2,NULL);
47         return((tp2.tv_sec - tp1.tv_sec) + 
48                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
49 }
50
51
52 /* return a pointer to a anonymous shared memory segment of size "size"
53    which will persist across fork() but will disappear when all processes
54    exit 
55
56    The memory is not zeroed 
57
58    This function uses system5 shared memory. It takes advantage of a property
59    that the memory is not destroyed if it is attached when the id is removed
60    */
61 static void *shm_setup(int size)
62 {
63         int shmid;
64         void *ret;
65
66         shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
67         if (shmid == -1) {
68                 printf("can't get shared memory\n");
69                 exit(1);
70         }
71         ret = (void *)shmat(shmid, 0, 0);
72         if (!ret || ret == (void *)-1) {
73                 printf("can't attach to shared memory\n");
74                 return NULL;
75         }
76         /* the following releases the ipc, but note that this process
77            and all its children will still have access to the memory, its
78            just that the shmid is no longer valid for other shm calls. This
79            means we don't leave behind lots of shm segments after we exit 
80
81            See Stevens "advanced programming in unix env" for details
82            */
83         shmctl(shmid, IPC_RMID, 0);
84         
85         return ret;
86 }
87
88
89 static BOOL open_connection(struct cli_state *c)
90 {
91         struct nmb_name called, calling;
92         struct in_addr ip;
93         extern struct in_addr ipzero;
94
95         ZERO_STRUCTP(c);
96
97         make_nmb_name(&calling, myname, 0x0);
98         make_nmb_name(&called , host, 0x20);
99
100         ip = ipzero;
101
102         if (!cli_initialise(c) || !cli_connect(c, host, &ip)) {
103                 printf("Failed to connect with %s\n", host);
104                 return False;
105         }
106
107         c->timeout = 120000; /* set a really long timeout (2 minutes) */
108
109         if (!cli_session_request(c, &calling, &called)) {
110                 printf("%s rejected the session\n",host);
111                 cli_shutdown(c);
112                 return False;
113         }
114
115         if (!cli_negprot(c)) {
116                 printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
117                 cli_shutdown(c);
118                 return False;
119         }
120
121         if (!cli_session_setup(c, username, 
122                                password, strlen(password),
123                                password, strlen(password),
124                                workgroup)) {
125                 printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
126                 cli_shutdown(c);
127                 return False;
128         }
129
130         if (!cli_send_tconX(c, share, "?????",
131                             password, strlen(password)+1)) {
132                 printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
133                 cli_shutdown(c);
134                 return False;
135         }
136
137         return True;
138 }
139
140
141
142 static void close_connection(struct cli_state *c)
143 {
144         if (!cli_tdis(c)) {
145                 printf("tdis failed (%s)\n", cli_errstr(c));
146         }
147
148         cli_shutdown(c);
149 }
150
151
152 /* check if the server produced the expected error code */
153 static BOOL check_error(struct cli_state *c, 
154                         uint8 eclass, uint32 ecode, uint32 nterr)
155 {
156         uint8 class;
157         uint32 num;
158         (void)cli_error(c, &class, &num, NULL);
159         if ((eclass != class || ecode != num) &&
160             num != (nterr&0xFFFFFF)) {
161                 printf("unexpected error code class=%d code=%d\n", 
162                          (int)class, (int)num);
163                 printf(" expected %d/%d %d\n", 
164                        (int)eclass, (int)ecode, (int)nterr);
165                 return False;
166         }
167         return True;
168 }
169
170
171 static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
172 {
173         while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) {
174                 if (!check_error(c, ERRDOS, ERRlock, 0)) return False;
175         }
176         return True;
177 }
178
179
180 static BOOL rw_torture(struct cli_state *c)
181 {
182         char *lockfname = "\\torture.lck";
183         fstring fname;
184         int fnum;
185         int fnum2;
186         pid_t pid2, pid = getpid();
187         int i, j;
188         char buf[1024];
189
190         fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
191                          DENY_NONE);
192         if (fnum2 == -1)
193                 fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
194         if (fnum2 == -1) {
195                 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
196                 return False;
197         }
198
199
200         for (i=0;i<numops;i++) {
201                 unsigned n = (unsigned)sys_random()%10;
202                 if (i % 10 == 0) {
203                         printf("%d\r", i); fflush(stdout);
204                 }
205                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
206
207                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
208                         return False;
209                 }
210
211                 fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
212                 if (fnum == -1) {
213                         printf("open failed (%s)\n", cli_errstr(c));
214                         break;
215                 }
216
217                 if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
218                         printf("write failed (%s)\n", cli_errstr(c));
219                 }
220
221                 for (j=0;j<50;j++) {
222                         if (cli_write(c, fnum, 0, (char *)buf, 
223                                       sizeof(pid)+(j*sizeof(buf)), 
224                                       sizeof(buf)) != sizeof(buf)) {
225                                 printf("write failed (%s)\n", cli_errstr(c));
226                         }
227                 }
228
229                 pid2 = 0;
230
231                 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
232                         printf("read failed (%s)\n", cli_errstr(c));
233                 }
234
235                 if (pid2 != pid) {
236                         printf("data corruption!\n");
237                 }
238
239                 if (!cli_close(c, fnum)) {
240                         printf("close failed (%s)\n", cli_errstr(c));
241                 }
242
243                 if (!cli_unlink(c, fname)) {
244                         printf("unlink failed (%s)\n", cli_errstr(c));
245                 }
246
247                 if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int))) {
248                         printf("unlock failed (%s)\n", cli_errstr(c));
249                 }
250         }
251
252         cli_close(c, fnum2);
253         cli_unlink(c, lockfname);
254
255         printf("%d\n", i);
256
257         return True;
258 }
259
260 static void run_torture(int dummy)
261 {
262         struct cli_state cli;
263
264         cli = current_cli;
265
266         cli_sockopt(&cli, sockops);
267
268         rw_torture(&cli);
269         
270         close_connection(&cli);
271 }
272
273 int line_count = 0;
274
275 /* run a test that simulates an approximate netbench client load */
276 static void run_netbench(int client)
277 {
278         struct cli_state cli;
279         int i;
280         fstring fname;
281         pstring line;
282         char cname[20];
283         FILE *f;
284         char *params[20];
285
286         cli = current_cli;
287
288         cli_sockopt(&cli, sockops);
289
290         nb_setup(&cli);
291
292         slprintf(cname,sizeof(fname), "CLIENT%d", client);
293
294         f = fopen("client.txt", "r");
295
296         if (!f) {
297                 perror("client.txt");
298                 return;
299         }
300
301         while (fgets(line, sizeof(line)-1, f)) {
302                 line_count++;
303
304                 line[strlen(line)-1] = 0;
305
306                 /* printf("[%d] %s\n", line_count, line); */
307
308                 all_string_sub(line,"CLIENT1", cname, sizeof(line));
309                 
310                 for (i=0;i<20;i++) params[i] = "";
311
312                 /* parse the command parameters */
313                 params[0] = strtok(line," ");
314                 i = 0;
315                 while (params[i]) params[++i] = strtok(NULL," ");
316
317                 params[i] = "";
318
319                 if (i < 2) continue;
320
321                 if (strcmp(params[1],"REQUEST") == 0) {
322                         if (!strcmp(params[0],"SMBopenX")) {
323                                 fstrcpy(fname, params[5]);
324                         } else if (!strcmp(params[0],"SMBclose")) {
325                                 nb_close(atoi(params[3]));
326                         } else if (!strcmp(params[0],"SMBmkdir")) {
327                                 nb_mkdir(params[3]);
328                         } else if (!strcmp(params[0],"CREATE")) {
329                                 nb_create(params[3], atoi(params[5]));
330                         } else if (!strcmp(params[0],"SMBrmdir")) {
331                                 nb_rmdir(params[3]);
332                         } else if (!strcmp(params[0],"SMBunlink")) {
333                                 fstrcpy(fname, params[3]);
334                         } else if (!strcmp(params[0],"SMBmv")) {
335                                 nb_rename(params[3], params[5]);
336                         } else if (!strcmp(params[0],"SMBgetatr")) {
337                                 fstrcpy(fname, params[3]);
338                         } else if (!strcmp(params[0],"SMBwrite")) {
339                                 nb_write(atoi(params[3]), 
340                                          atoi(params[5]), atoi(params[7]));
341                         } else if (!strcmp(params[0],"SMBwritebraw")) {
342                                 nb_write(atoi(params[3]), 
343                                          atoi(params[7]), atoi(params[5]));
344                         } else if (!strcmp(params[0],"SMBreadbraw")) {
345                                 nb_read(atoi(params[3]), 
346                                          atoi(params[7]), atoi(params[5]));
347                         } else if (!strcmp(params[0],"SMBread")) {
348                                 nb_read(atoi(params[3]), 
349                                          atoi(params[5]), atoi(params[7]));
350                         }
351                 } else {
352                         if (!strcmp(params[0],"SMBopenX")) {
353                                 if (!strncmp(params[2], "ERR", 3)) continue;
354                                 nb_open(fname, atoi(params[3]), atoi(params[5]));
355                         } else if (!strcmp(params[0],"SMBgetatr")) {
356                                 if (!strncmp(params[2], "ERR", 3)) continue;
357                                 nb_stat(fname, atoi(params[3]));
358                         } else if (!strcmp(params[0],"SMBunlink")) {
359                                 if (!strncmp(params[2], "ERR", 3)) continue;
360                                 nb_unlink(fname);
361                         }
362                 }
363         }
364         fclose(f);
365
366         slprintf(fname,sizeof(fname), "CLIENTS/CLIENT%d", client);
367         rmdir(fname);
368         rmdir("CLIENTS");
369
370         printf("+");    
371
372         close_connection(&cli);
373 }
374
375
376 /* run a test that simulates an approximate netbench w9X client load */
377 static void run_nbw95(int dummy)
378 {
379         double t;
380         t = create_procs(run_netbench);
381         /* to produce a netbench result we scale accoding to the
382            netbench measured throughput for the run that produced the
383            sniff that was used to produce client.txt. That run used 2
384            clients and ran for 660 seconds to produce a result of
385            4MBit/sec. */
386         printf("Throughput %g MB/sec (NB=%g MB/sec  %g MBit/sec)\n", 
387                132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
388 }
389
390 /* run a test that simulates an approximate netbench wNT client load */
391 static void run_nbwnt(int dummy)
392 {
393         double t;
394         t = create_procs(run_netbench);
395         printf("Throughput %g MB/sec (NB=%g MB/sec  %g MBit/sec)\n", 
396                132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
397 }
398
399
400
401 /*
402   This test checks for two things:
403
404   1) correct support for retaining locks over a close (ie. the server
405      must not use posix semantics)
406   2) support for lock timeouts
407  */
408 static void run_locktest1(int dummy)
409 {
410         static struct cli_state cli1, cli2;
411         char *fname = "\\lockt1.lck";
412         int fnum1, fnum2, fnum3;
413         time_t t1, t2;
414
415         if (!open_connection(&cli1) || !open_connection(&cli2)) {
416                 return;
417         }
418         cli_sockopt(&cli1, sockops);
419         cli_sockopt(&cli2, sockops);
420
421         printf("starting locktest1\n");
422
423         cli_unlink(&cli1, fname);
424
425         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
426         if (fnum1 == -1) {
427                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
428                 return;
429         }
430         fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
431         if (fnum2 == -1) {
432                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
433                 return;
434         }
435         fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
436         if (fnum3 == -1) {
437                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
438                 return;
439         }
440
441         if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
442                 printf("lock1 failed (%s)\n", cli_errstr(&cli1));
443                 return;
444         }
445
446
447         if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
448                 printf("lock2 succeeded! This is a locking bug\n");
449                 return;
450         } else {
451                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
452         }
453
454
455         printf("Testing lock timeouts\n");
456         t1 = time(NULL);
457         if (cli_lock(&cli2, fnum3, 0, 4, 10*1000, WRITE_LOCK)) {
458                 printf("lock3 succeeded! This is a locking bug\n");
459                 return;
460         } else {
461                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
462         }
463         t2 = time(NULL);
464
465         if (t2 - t1 < 5) {
466                 printf("error: This server appears not to support timed lock requests\n");
467         }
468
469         if (!cli_close(&cli1, fnum2)) {
470                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
471                 return;
472         }
473
474         if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
475                 printf("lock4 succeeded! This is a locking bug\n");
476                 return;
477         } else {
478                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
479         }
480
481         if (!cli_close(&cli1, fnum1)) {
482                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
483                 return;
484         }
485
486         if (!cli_close(&cli2, fnum3)) {
487                 printf("close3 failed (%s)\n", cli_errstr(&cli2));
488                 return;
489         }
490
491         if (!cli_unlink(&cli1, fname)) {
492                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
493                 return;
494         }
495
496
497         close_connection(&cli1);
498         close_connection(&cli2);
499
500         printf("Passed locktest1\n");
501 }
502
503 /*
504  checks for correct tconX support
505  */
506 static void run_tcon_test(int dummy)
507 {
508         static struct cli_state cli1;
509         char *fname = "\\tcontest.tmp";
510         int fnum1;
511         uint16 cnum;
512         char buf[4];
513
514         if (!open_connection(&cli1)) {
515                 return;
516         }
517         cli_sockopt(&cli1, sockops);
518
519         printf("starting tcontest\n");
520
521         cli_unlink(&cli1, fname);
522
523         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
524         if (fnum1 == -1)
525         {
526                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
527                 return;
528         }
529
530         cnum = cli1.cnum;
531
532         if (cli_write(&cli1, fnum1, 0, buf, 130, 4) != 4)
533         {
534                 printf("write failed (%s)", cli_errstr(&cli1));
535                 return;
536         }
537
538         if (!cli_send_tconX(&cli1, share, "?????",
539                             password, strlen(password)+1)) {
540                 printf("%s refused 2nd tree connect (%s)\n", host,
541                            cli_errstr(&cli1));
542                 cli_shutdown(&cli1);
543                 return ;
544         }
545
546         if (cli_write(&cli1, fnum1, 0, buf, 130, 4) == 4)
547         {
548                 printf("write succeeded (%s)", cli_errstr(&cli1));
549                 return;
550         }
551
552         if (cli_close(&cli1, fnum1)) {
553                 printf("close2 succeeded (%s)\n", cli_errstr(&cli1));
554                 return;
555         }
556
557         if (!cli_tdis(&cli1)) {
558                 printf("tdis failed (%s)\n", cli_errstr(&cli1));
559                 return;
560         }
561
562         cli1.cnum = cnum;
563
564         if (!cli_close(&cli1, fnum1)) {
565                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
566                 return;
567         }
568
569         close_connection(&cli1);
570
571         printf("Passed tcontest\n");
572 }
573
574
575 /*
576   This test checks that 
577
578   1) the server supports multiple locking contexts on the one SMB
579   connection, distinguished by PID.  
580
581   2) the server correctly fails overlapping locks made by the same PID (this
582      goes against POSIX behaviour, which is why it is tricky to implement)
583
584   3) the server denies unlock requests by an incorrect client PID
585 */
586 static void run_locktest2(int dummy)
587 {
588         static struct cli_state cli;
589         char *fname = "\\lockt2.lck";
590         int fnum1, fnum2, fnum3;
591
592         if (!open_connection(&cli)) {
593                 return;
594         }
595
596         cli_sockopt(&cli, sockops);
597
598         printf("starting locktest2\n");
599
600         cli_unlink(&cli, fname);
601
602         cli_setpid(&cli, 1);
603
604         fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
605         if (fnum1 == -1) {
606                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
607                 return;
608         }
609
610         fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
611         if (fnum2 == -1) {
612                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
613                 return;
614         }
615
616         cli_setpid(&cli, 2);
617
618         fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
619         if (fnum3 == -1) {
620                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
621                 return;
622         }
623
624         cli_setpid(&cli, 1);
625
626         if (!cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
627                 printf("lock1 failed (%s)\n", cli_errstr(&cli));
628                 return;
629         }
630
631         if (cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
632                 printf("WRITE lock1 succeeded! This is a locking bug\n");
633         } else {
634                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
635         }
636
637         if (cli_lock(&cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
638                 printf("WRITE lock2 succeeded! This is a locking bug\n");
639         } else {
640                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
641         }
642
643         if (cli_lock(&cli, fnum2, 0, 4, 0, READ_LOCK)) {
644                 printf("READ lock2 succeeded! This is a locking bug\n");
645         } else {
646                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
647         }
648
649         cli_setpid(&cli, 2);
650
651         if (cli_unlock(&cli, fnum1, 0, 8)) {
652                 printf("unlock1 succeeded! This is a locking bug\n");
653         }
654
655         if (cli_lock(&cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
656                 printf("lock3 succeeded! This is a locking bug\n");
657         } else {
658                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
659         }
660
661         cli_setpid(&cli, 1);
662
663         if (!cli_close(&cli, fnum1)) {
664                 printf("close1 failed (%s)\n", cli_errstr(&cli));
665                 return;
666         }
667
668         if (!cli_close(&cli, fnum2)) {
669                 printf("close2 failed (%s)\n", cli_errstr(&cli));
670                 return;
671         }
672
673         if (!cli_close(&cli, fnum3)) {
674                 printf("close3 failed (%s)\n", cli_errstr(&cli));
675                 return;
676         }
677
678         close_connection(&cli);
679
680         printf("locktest2 finished\n");
681 }
682
683
684 /*
685   This test checks that 
686
687   1) the server supports the full offset range in lock requests
688 */
689 static void run_locktest3(int dummy)
690 {
691         static struct cli_state cli1, cli2;
692         char *fname = "\\lockt3.lck";
693         int fnum1, fnum2, i;
694         uint32 offset;
695
696 #define NEXT_OFFSET offset += (~(uint32)0) / numops
697
698         if (!open_connection(&cli1) || !open_connection(&cli2)) {
699                 return;
700         }
701         cli_sockopt(&cli1, sockops);
702         cli_sockopt(&cli2, sockops);
703
704         printf("starting locktest3\n");
705
706         cli_unlink(&cli1, fname);
707
708         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
709         if (fnum1 == -1) {
710                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
711                 return;
712         }
713         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
714         if (fnum2 == -1) {
715                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
716                 return;
717         }
718
719         for (offset=i=0;i<numops;i++) {
720                 NEXT_OFFSET;
721                 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
722                         printf("lock1 %d failed (%s)\n", 
723                                i,
724                                cli_errstr(&cli1));
725                         return;
726                 }
727
728                 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
729                         printf("lock2 %d failed (%s)\n", 
730                                i,
731                                cli_errstr(&cli1));
732                         return;
733                 }
734         }
735
736         for (offset=i=0;i<numops;i++) {
737                 NEXT_OFFSET;
738
739                 if (cli_lock(&cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
740                         printf("error: lock1 %d succeeded!\n", i);
741                         return;
742                 }
743
744                 if (cli_lock(&cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
745                         printf("error: lock2 %d succeeded!\n", i);
746                         return;
747                 }
748
749                 if (cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
750                         printf("error: lock3 %d succeeded!\n", i);
751                         return;
752                 }
753
754                 if (cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
755                         printf("error: lock4 %d succeeded!\n", i);
756                         return;
757                 }
758         }
759
760         for (offset=i=0;i<numops;i++) {
761                 NEXT_OFFSET;
762
763                 if (!cli_unlock(&cli1, fnum1, offset-1, 1)) {
764                         printf("unlock1 %d failed (%s)\n", 
765                                i,
766                                cli_errstr(&cli1));
767                         return;
768                 }
769
770                 if (!cli_unlock(&cli2, fnum2, offset-2, 1)) {
771                         printf("unlock2 %d failed (%s)\n", 
772                                i,
773                                cli_errstr(&cli1));
774                         return;
775                 }
776         }
777
778         if (!cli_close(&cli1, fnum1)) {
779                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
780         }
781
782         if (!cli_close(&cli2, fnum2)) {
783                 printf("close2 failed (%s)\n", cli_errstr(&cli2));
784         }
785
786         if (!cli_unlink(&cli1, fname)) {
787                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
788                 return;
789         }
790
791         close_connection(&cli1);
792         close_connection(&cli2);
793
794         printf("finished locktest3\n");
795 }
796
797 #define EXPECTED(ret, v) if ((ret) != (v)) printf("** ")
798
799 /*
800   looks at overlapping locks
801 */
802 static void run_locktest4(int dummy)
803 {
804         static struct cli_state cli1, cli2;
805         char *fname = "\\lockt4.lck";
806         int fnum1, fnum2, f;
807         BOOL ret;
808         char buf[1000];
809
810         if (!open_connection(&cli1) || !open_connection(&cli2)) {
811                 return;
812         }
813
814         cli_sockopt(&cli1, sockops);
815         cli_sockopt(&cli2, sockops);
816
817         printf("starting locktest4\n");
818
819         cli_unlink(&cli1, fname);
820
821         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
822         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
823
824         memset(buf, 0, sizeof(buf));
825
826         if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
827                 printf("Failed to create file\n");
828                 goto fail;
829         }
830
831         ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
832               cli_lock(&cli1, fnum1, 2, 4, 0, WRITE_LOCK);
833         EXPECTED(ret, False);
834         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
835             
836         ret = cli_lock(&cli1, fnum1, 10, 4, 0, READ_LOCK) &&
837               cli_lock(&cli1, fnum1, 12, 4, 0, READ_LOCK);
838         EXPECTED(ret, True);
839         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
840
841         ret = cli_lock(&cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
842               cli_lock(&cli2, fnum2, 22, 4, 0, WRITE_LOCK);
843         EXPECTED(ret, False);
844         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
845             
846         ret = cli_lock(&cli1, fnum1, 30, 4, 0, READ_LOCK) &&
847               cli_lock(&cli2, fnum2, 32, 4, 0, READ_LOCK);
848         EXPECTED(ret, True);
849         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
850         
851         ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
852               (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 42, 4, 0, WRITE_LOCK));
853         EXPECTED(ret, False);
854         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
855             
856         ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
857               (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 52, 4, 0, READ_LOCK));
858         EXPECTED(ret, True);
859         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
860
861         ret = cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK) &&
862               cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK);
863         EXPECTED(ret, True);
864         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
865
866         ret = cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
867               cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK);
868         EXPECTED(ret, False);
869         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
870
871         ret = cli_lock(&cli1, fnum1, 80, 4, 0, READ_LOCK) &&
872               cli_lock(&cli1, fnum1, 80, 4, 0, WRITE_LOCK);
873         EXPECTED(ret, False);
874         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
875
876         ret = cli_lock(&cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
877               cli_lock(&cli1, fnum1, 90, 4, 0, READ_LOCK);
878         EXPECTED(ret, True);
879         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
880
881         ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
882               (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 100, 4, 0, READ_LOCK));
883         EXPECTED(ret, False);
884         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
885
886         ret = cli_lock(&cli1, fnum1, 110, 4, 0, READ_LOCK) &&
887               cli_lock(&cli1, fnum1, 112, 4, 0, READ_LOCK) &&
888               cli_unlock(&cli1, fnum1, 110, 6);
889         EXPECTED(ret, False);
890         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
891
892
893         ret = cli_lock(&cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
894               (cli_read(&cli2, fnum2, buf, 120, 4) == 4);
895         EXPECTED(ret, False);
896         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
897
898         ret = cli_lock(&cli1, fnum1, 130, 4, 0, READ_LOCK) &&
899               (cli_write(&cli2, fnum2, 0, buf, 130, 4) == 4);
900         EXPECTED(ret, False);
901         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
902
903
904         ret = cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
905               cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
906               cli_unlock(&cli1, fnum1, 140, 4) &&
907               cli_unlock(&cli1, fnum1, 140, 4);
908         EXPECTED(ret, True);
909         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
910
911
912         ret = cli_lock(&cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
913               cli_lock(&cli1, fnum1, 150, 4, 0, READ_LOCK) &&
914               cli_unlock(&cli1, fnum1, 150, 4) &&
915               (cli_read(&cli2, fnum2, buf, 150, 4) == 4) &&
916               !(cli_write(&cli2, fnum2, 0, buf, 150, 4) == 4) &&
917               cli_unlock(&cli1, fnum1, 150, 4);
918         EXPECTED(ret, True);
919         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
920
921         ret = cli_lock(&cli1, fnum1, 160, 4, 0, READ_LOCK) &&
922               cli_unlock(&cli1, fnum1, 160, 4) &&
923               (cli_write(&cli2, fnum2, 0, buf, 160, 4) == 4) &&         
924               (cli_read(&cli2, fnum2, buf, 160, 4) == 4);               
925         EXPECTED(ret, True);
926         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
927
928         ret = cli_lock(&cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
929               cli_unlock(&cli1, fnum1, 170, 4) &&
930               (cli_write(&cli2, fnum2, 0, buf, 170, 4) == 4) &&         
931               (cli_read(&cli2, fnum2, buf, 170, 4) == 4);               
932         EXPECTED(ret, True);
933         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
934
935         ret = cli_lock(&cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
936               cli_lock(&cli1, fnum1, 190, 4, 0, READ_LOCK) &&
937               cli_unlock(&cli1, fnum1, 190, 4) &&
938               !(cli_write(&cli2, fnum2, 0, buf, 190, 4) == 4) &&                
939               (cli_read(&cli2, fnum2, buf, 190, 4) == 4);               
940         EXPECTED(ret, True);
941         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
942
943         cli_close(&cli1, fnum1);
944         cli_close(&cli2, fnum2);
945         fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
946         f = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
947         ret = cli_lock(&cli1, fnum1, 0, 8, 0, READ_LOCK) &&
948               cli_lock(&cli1, f, 0, 1, 0, READ_LOCK) &&
949               cli_close(&cli1, fnum1) &&
950               ((fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE)) != -1) &&
951               cli_lock(&cli1, fnum1, 7, 1, 0, WRITE_LOCK);
952         cli_close(&cli1, f);
953         EXPECTED(ret, True);
954         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
955         
956
957
958  fail:
959         cli_close(&cli1, fnum1);
960         cli_close(&cli2, fnum2);
961         cli_unlink(&cli1, fname);
962         close_connection(&cli1);
963         close_connection(&cli2);
964
965         printf("finished locktest4\n");
966 }
967
968 /*
969   looks at lock upgrade/downgrade.
970 */
971 static void run_locktest5(int dummy)
972 {
973         static struct cli_state cli1, cli2;
974         char *fname = "\\lockt5.lck";
975         int fnum1, fnum2, fnum3;
976         BOOL ret;
977         char buf[1000];
978
979         if (!open_connection(&cli1) || !open_connection(&cli2)) {
980                 return;
981         }
982
983         cli_sockopt(&cli1, sockops);
984         cli_sockopt(&cli2, sockops);
985
986         printf("starting locktest5\n");
987
988         cli_unlink(&cli1, fname);
989
990         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
991         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
992         fnum3 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
993
994         memset(buf, 0, sizeof(buf));
995
996         if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
997                 printf("Failed to create file\n");
998                 goto fail;
999         }
1000
1001         /* Check for NT bug... */
1002         ret = cli_lock(&cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1003                   cli_lock(&cli1, fnum3, 0, 1, 0, READ_LOCK);
1004         cli_close(&cli1, fnum1);
1005         fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1006         ret = cli_lock(&cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1007         EXPECTED(ret, True);
1008         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
1009         cli_close(&cli1, fnum1);
1010         fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1011         cli_unlock(&cli1, fnum3, 0, 1);
1012
1013         ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1014               cli_lock(&cli1, fnum1, 1, 1, 0, READ_LOCK);
1015         EXPECTED(ret, True);
1016         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
1017
1018         ret = cli_lock(&cli2, fnum2, 0, 4, 0, READ_LOCK);
1019         EXPECTED(ret, False);
1020
1021         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
1022
1023         /* Unlock the process 2 lock. */
1024         cli_unlock(&cli2, fnum2, 0, 4);
1025
1026         ret = cli_lock(&cli1, fnum3, 0, 4, 0, READ_LOCK);
1027         EXPECTED(ret, False);
1028
1029         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
1030
1031         /* Unlock the process 1 fnum3 lock. */
1032         cli_unlock(&cli1, fnum3, 0, 4);
1033
1034         /* Stack 2 more locks here. */
1035         ret = cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK) &&
1036                   cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK);
1037
1038         EXPECTED(ret, True);
1039         printf("the same process %s stack read locks\n", ret?"can":"cannot");
1040
1041         /* Unlock the first process lock, then check this was the WRITE lock that was
1042                 removed. */
1043
1044         ret = cli_unlock(&cli1, fnum1, 0, 4) &&
1045                         cli_lock(&cli2, fnum2, 0, 4, 0, READ_LOCK);
1046
1047         EXPECTED(ret, True);
1048         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
1049
1050         /* Unlock the process 2 lock. */
1051         cli_unlock(&cli2, fnum2, 0, 4);
1052
1053         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
1054
1055         ret = cli_unlock(&cli1, fnum1, 1, 1) &&
1056                   cli_unlock(&cli1, fnum1, 0, 4) &&
1057                   cli_unlock(&cli1, fnum1, 0, 4);
1058
1059         EXPECTED(ret, True);
1060         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
1061
1062         /* Ensure the next unlock fails. */
1063         ret = cli_unlock(&cli1, fnum1, 0, 4);
1064         EXPECTED(ret, False);
1065         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
1066
1067         /* Ensure connection 2 can get a write lock. */
1068         ret = cli_lock(&cli2, fnum2, 0, 4, 0, WRITE_LOCK);
1069         EXPECTED(ret, True);
1070
1071         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
1072
1073  fail:
1074         cli_close(&cli1, fnum1);
1075         cli_close(&cli2, fnum2);
1076         cli_unlink(&cli1, fname);
1077         close_connection(&cli1);
1078         close_connection(&cli2);
1079
1080         printf("finished locktest5\n");
1081 }
1082
1083
1084 /*
1085   this produces a matrix of deny mode behaviour
1086  */
1087 static void run_denytest1(int dummy)
1088 {
1089         static struct cli_state cli1, cli2;
1090         int fnum1, fnum2;
1091         int f, d1, d2, o1, o2, x=0;
1092         char *fnames[] = {"denytest1.exe", "denytest1.dat", NULL};
1093         struct {
1094                 int v;
1095                 char *name; 
1096         } deny_modes[] = {
1097                 {DENY_DOS, "DENY_DOS"},
1098                 {DENY_ALL, "DENY_ALL"},
1099                 {DENY_WRITE, "DENY_WRITE"},
1100                 {DENY_READ, "DENY_READ"},
1101                 {DENY_NONE, "DENY_NONE"},
1102                 {DENY_FCB, "DENY_FCB"},
1103                 {-1, NULL}};
1104         struct {
1105                 int v;
1106                 char *name; 
1107         } open_modes[] = {
1108                 {O_RDWR, "O_RDWR"},
1109                 {O_RDONLY, "O_RDONLY"},
1110                 {O_WRONLY, "O_WRONLY"},
1111                 {-1, NULL}};
1112
1113         if (!open_connection(&cli1) || !open_connection(&cli2)) {
1114                 return;
1115         }
1116         cli_sockopt(&cli1, sockops);
1117         cli_sockopt(&cli2, sockops);
1118
1119         printf("starting denytest1\n");
1120
1121         for (f=0;fnames[f];f++) {
1122                 cli_unlink(&cli1, fnames[f]);
1123
1124                 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1125                 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1126                 cli_close(&cli1, fnum1);
1127
1128                 for (d1=0;deny_modes[d1].name;d1++) 
1129                 for (o1=0;open_modes[o1].name;o1++) 
1130                 for (d2=0;deny_modes[d2].name;d2++) 
1131                 for (o2=0;open_modes[o2].name;o2++) {
1132                         fnum1 = cli_open(&cli1, fnames[f], 
1133                                          open_modes[o1].v, 
1134                                          deny_modes[d1].v);
1135                         fnum2 = cli_open(&cli2, fnames[f], 
1136                                          open_modes[o2].v, 
1137                                          deny_modes[d2].v);
1138
1139                         printf("%s %8s %10s    %8s %10s     ",
1140                                fnames[f],
1141                                open_modes[o1].name,
1142                                deny_modes[d1].name,
1143                                open_modes[o2].name,
1144                                deny_modes[d2].name);
1145
1146                         if (fnum1 == -1) {
1147                                 printf("X");
1148                         } else if (fnum2 == -1) {
1149                                 printf("-");
1150                         } else {
1151                                 if (cli_read(&cli2, fnum2, (void *)&x, 0, 1) == 1) {
1152                                         printf("R");
1153                                 }
1154                                 if (cli_write(&cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
1155                                         printf("W");
1156                                 }
1157                         }
1158
1159                         printf("\n");
1160                         cli_close(&cli1, fnum1);
1161                         cli_close(&cli2, fnum2);
1162                 }
1163                 
1164                 cli_unlink(&cli1, fnames[f]);
1165         }
1166
1167         close_connection(&cli1);
1168         close_connection(&cli2);
1169         
1170         printf("finshed denytest1\n");
1171 }
1172
1173
1174 /*
1175   this produces a matrix of deny mode behaviour for two opens on the
1176   same connection
1177  */
1178 static void run_denytest2(int dummy)
1179 {
1180         static struct cli_state cli1;
1181         int fnum1, fnum2;
1182         int f, d1, d2, o1, o2, x=0;
1183         char *fnames[] = {"denytest2.exe", "denytest2.dat", NULL};
1184         struct {
1185                 int v;
1186                 char *name; 
1187         } deny_modes[] = {
1188                 {DENY_DOS, "DENY_DOS"},
1189                 {DENY_ALL, "DENY_ALL"},
1190                 {DENY_WRITE, "DENY_WRITE"},
1191                 {DENY_READ, "DENY_READ"},
1192                 {DENY_NONE, "DENY_NONE"},
1193                 {DENY_FCB, "DENY_FCB"},
1194                 {-1, NULL}};
1195         struct {
1196                 int v;
1197                 char *name; 
1198         } open_modes[] = {
1199                 {O_RDWR, "O_RDWR"},
1200                 {O_RDONLY, "O_RDONLY"},
1201                 {O_WRONLY, "O_WRONLY"},
1202                 {-1, NULL}};
1203
1204         if (!open_connection(&cli1)) {
1205                 return;
1206         }
1207         cli_sockopt(&cli1, sockops);
1208
1209         printf("starting denytest2\n");
1210
1211         for (f=0;fnames[f];f++) {
1212                 cli_unlink(&cli1, fnames[f]);
1213
1214                 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1215                 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1216                 cli_close(&cli1, fnum1);
1217
1218                 for (d1=0;deny_modes[d1].name;d1++) 
1219                 for (o1=0;open_modes[o1].name;o1++) 
1220                 for (d2=0;deny_modes[d2].name;d2++) 
1221                 for (o2=0;open_modes[o2].name;o2++) {
1222                         fnum1 = cli_open(&cli1, fnames[f], 
1223                                          open_modes[o1].v, 
1224                                          deny_modes[d1].v);
1225                         fnum2 = cli_open(&cli1, fnames[f], 
1226                                          open_modes[o2].v, 
1227                                          deny_modes[d2].v);
1228
1229                         printf("%s %8s %10s    %8s %10s     ",
1230                                fnames[f],
1231                                open_modes[o1].name,
1232                                deny_modes[d1].name,
1233                                open_modes[o2].name,
1234                                deny_modes[d2].name);
1235
1236                         if (fnum1 == -1) {
1237                                 printf("X");
1238                         } else if (fnum2 == -1) {
1239                                 printf("-");
1240                         } else {
1241                                 if (cli_read(&cli1, fnum2, (void *)&x, 0, 1) == 1) {
1242                                         printf("R");
1243                                 }
1244                                 if (cli_write(&cli1, fnum2, 0, (void *)&x, 0, 1) == 1) {
1245                                         printf("W");
1246                                 }
1247                         }
1248
1249                         printf("\n");
1250                         cli_close(&cli1, fnum1);
1251                         cli_close(&cli1, fnum2);
1252                 }
1253                 
1254                 cli_unlink(&cli1, fnames[f]);
1255         }
1256
1257         close_connection(&cli1);
1258         
1259         printf("finshed denytest2\n");
1260 }
1261
1262 /*
1263 test whether fnums and tids open on one VC are available on another (a major
1264 security hole)
1265 */
1266 static void run_fdpasstest(int dummy)
1267 {
1268         static struct cli_state cli1, cli2;
1269         char *fname = "\\fdpass.tst";
1270         int fnum1;
1271         pstring buf;
1272
1273         if (!open_connection(&cli1) || !open_connection(&cli2)) {
1274                 return;
1275         }
1276         cli_sockopt(&cli1, sockops);
1277         cli_sockopt(&cli2, sockops);
1278
1279         printf("starting fdpasstest\n");
1280
1281         cli_unlink(&cli1, fname);
1282
1283         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1284         if (fnum1 == -1) {
1285                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1286                 return;
1287         }
1288
1289         if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
1290                 printf("write failed (%s)\n", cli_errstr(&cli1));
1291                 return;
1292         }
1293
1294         cli2.vuid = cli1.vuid;
1295         cli2.cnum = cli1.cnum;
1296         cli2.pid = cli1.pid;
1297
1298
1299         if (cli_read(&cli2, fnum1, buf, 0, 13) == 13) {
1300                 printf("read succeeded! nasty security hole [%s]\n",
1301                        buf);
1302                 return;
1303         }
1304
1305         cli_close(&cli1, fnum1);
1306         cli_unlink(&cli1, fname);
1307
1308         close_connection(&cli1);
1309         close_connection(&cli2);
1310
1311         printf("finished fdpasstest\n");
1312 }
1313
1314
1315 /*
1316   This test checks that 
1317
1318   1) the server does not allow an unlink on a file that is open
1319 */
1320 static void run_unlinktest(int dummy)
1321 {
1322         static struct cli_state cli;
1323         char *fname = "\\unlink.tst";
1324         int fnum;
1325
1326         if (!open_connection(&cli)) {
1327                 return;
1328         }
1329
1330         cli_sockopt(&cli, sockops);
1331
1332         printf("starting unlink test\n");
1333
1334         cli_unlink(&cli, fname);
1335
1336         cli_setpid(&cli, 1);
1337
1338         fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1339         if (fnum == -1) {
1340                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
1341                 return;
1342         }
1343
1344         if (cli_unlink(&cli, fname)) {
1345                 printf("error: server allowed unlink on an open file\n");
1346         }
1347
1348         cli_close(&cli, fnum);
1349         cli_unlink(&cli, fname);
1350
1351         close_connection(&cli);
1352
1353         printf("unlink test finished\n");
1354 }
1355
1356
1357 /*
1358 test how many open files this server supports on the one socket
1359 */
1360 static void run_maxfidtest(int dummy)
1361 {
1362         static struct cli_state cli;
1363         char *template = "\\maxfid.%d.%d";
1364         fstring fname;
1365         int fnum;
1366         int retries=4;
1367         int n = numops;
1368
1369         cli = current_cli;
1370
1371         if (retries <= 0) {
1372                 printf("failed to connect\n");
1373                 return;
1374         }
1375
1376         cli_sockopt(&cli, sockops);
1377
1378         fnum = 0;
1379         while (1) {
1380                 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1381                 if (cli_open(&cli, fname, 
1382                              O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
1383                     -1) {
1384                         printf("open of %s failed (%s)\n", 
1385                                fname, cli_errstr(&cli));
1386                         printf("maximum fnum is %d\n", fnum);
1387                         break;
1388                 }
1389                 fnum++;
1390         }
1391
1392         printf("cleaning up\n");
1393         while (fnum > n) {
1394                 fnum--;
1395                 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1396                 if (cli_unlink(&cli, fname)) {
1397                         printf("unlink of %s failed (%s)\n", 
1398                                fname, cli_errstr(&cli));
1399                 }
1400         }
1401
1402         printf("maxfid test finished\n");
1403         close_connection(&cli);
1404 }
1405
1406 /* generate a random buffer */
1407 static void rand_buf(char *buf, int len)
1408 {
1409         while (len--) {
1410                 *buf = (char)sys_random();
1411                 buf++;
1412         }
1413 }
1414
1415 /* send random IPC commands */
1416 static void run_randomipc(int dummy)
1417 {
1418         char *rparam = NULL;
1419         char *rdata = NULL;
1420         int rdrcnt,rprcnt;
1421         pstring param;
1422         int api, param_len, i;
1423         static struct cli_state cli;
1424
1425         printf("starting random ipc test\n");
1426
1427         if (!open_connection(&cli)) {
1428                 return;
1429         }
1430
1431         for (i=0;i<50000;i++) {
1432                 api = sys_random() % 500;
1433                 param_len = (sys_random() % 64);
1434
1435                 rand_buf(param, param_len);
1436   
1437                 SSVAL(param,0,api); 
1438
1439                 cli_api(&cli, 
1440                         param, param_len, 8,  
1441                         NULL, 0, BUFFER_SIZE, 
1442                         &rparam, &rprcnt,     
1443                         &rdata, &rdrcnt);
1444         }
1445
1446         close_connection(&cli);
1447
1448         printf("finished random ipc test\n");
1449 }
1450
1451
1452
1453 static void browse_callback(const char *sname, uint32 stype, 
1454                             const char *comment)
1455 {
1456         printf("\t%20.20s %08x %s\n", sname, stype, comment);
1457 }
1458
1459
1460
1461 /*
1462   This test checks the browse list code
1463
1464 */
1465 static void run_browsetest(int dummy)
1466 {
1467         static struct cli_state cli;
1468
1469         printf("starting browse test\n");
1470
1471         if (!open_connection(&cli)) {
1472                 return;
1473         }
1474
1475         printf("domain list:\n");
1476         cli_NetServerEnum(&cli, cli.server_domain, 
1477                           SV_TYPE_DOMAIN_ENUM,
1478                           browse_callback);
1479
1480         printf("machine list:\n");
1481         cli_NetServerEnum(&cli, cli.server_domain, 
1482                           SV_TYPE_ALL,
1483                           browse_callback);
1484
1485         close_connection(&cli);
1486
1487         printf("browse test finished\n");
1488 }
1489
1490
1491 /*
1492   This checks how the getatr calls works
1493 */
1494 static void run_attrtest(int dummy)
1495 {
1496         static struct cli_state cli;
1497         int fnum;
1498         time_t t, t2;
1499         char *fname = "\\attrib.tst";
1500
1501         printf("starting attrib test\n");
1502
1503         if (!open_connection(&cli)) {
1504                 return;
1505         }
1506
1507         cli_unlink(&cli, fname);
1508         fnum = cli_open(&cli, fname, 
1509                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1510         cli_close(&cli, fnum);
1511         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1512                 printf("getatr failed (%s)\n", cli_errstr(&cli));
1513         }
1514
1515         if (abs(t - time(NULL)) > 2) {
1516                 printf("ERROR: SMBgetatr bug. time is %s",
1517                        ctime(&t));
1518                 t = time(NULL);
1519         }
1520
1521         t2 = t-60*60*24; /* 1 day ago */
1522
1523         if (!cli_setatr(&cli, fname, 0, t2)) {
1524                 printf("setatr failed (%s)\n", cli_errstr(&cli));
1525         }
1526
1527         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1528                 printf("getatr failed (%s)\n", cli_errstr(&cli));
1529         }
1530
1531         if (t != t2) {
1532                 printf("ERROR: getatr/setatr bug. times are\n%s",
1533                        ctime(&t));
1534                 printf("%s", ctime(&t2));
1535         }
1536
1537         cli_unlink(&cli, fname);
1538
1539         close_connection(&cli);
1540
1541         printf("attrib test finished\n");
1542 }
1543
1544
1545 /*
1546   This checks a couple of trans2 calls
1547 */
1548 static void run_trans2test(int dummy)
1549 {
1550         static struct cli_state cli;
1551         int fnum;
1552         size_t size;
1553         time_t c_time, a_time, m_time, w_time, m_time2;
1554         char *fname = "\\trans2.tst";
1555         char *dname = "\\trans2";
1556         char *fname2 = "\\trans2\\trans2.tst";
1557
1558         printf("starting trans2 test\n");
1559
1560         if (!open_connection(&cli)) {
1561                 return;
1562         }
1563
1564         cli_unlink(&cli, fname);
1565         fnum = cli_open(&cli, fname, 
1566                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1567         if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
1568                            NULL, NULL)) {
1569                 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
1570         }
1571         cli_close(&cli, fnum);
1572
1573         sleep(2);
1574
1575         cli_unlink(&cli, fname);
1576         fnum = cli_open(&cli, fname, 
1577                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1578         cli_close(&cli, fnum);
1579
1580         if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
1581                 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
1582         } else {
1583                 if (c_time != m_time) {
1584                         printf("create time=%s", ctime(&c_time));
1585                         printf("modify time=%s", ctime(&m_time));
1586                         printf("This system appears to have sticky create times\n");
1587                 }
1588                 if (a_time % (60*60) == 0) {
1589                         printf("access time=%s", ctime(&a_time));
1590                         printf("This system appears to set a midnight access time\n");
1591                 }
1592
1593                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1594                         printf("ERROR: totally incorrect times - maybe word reversed?\n");
1595                 }
1596         }
1597
1598
1599         cli_unlink(&cli, fname);
1600         fnum = cli_open(&cli, fname, 
1601                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1602         cli_close(&cli, fnum);
1603         if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time, 
1604                             &w_time, &size, NULL, NULL)) {
1605                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1606         } else {
1607                 if (w_time < 60*60*24*2) {
1608                         printf("write time=%s", ctime(&w_time));
1609                         printf("This system appears to set a initial 0 write time\n");
1610                 }
1611         }
1612
1613         cli_unlink(&cli, fname);
1614
1615
1616         /* check if the server updates the directory modification time
1617            when creating a new file */
1618         if (!cli_mkdir(&cli, dname)) {
1619                 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
1620         }
1621         sleep(3);
1622         if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time, 
1623                             &w_time, &size, NULL, NULL)) {
1624                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1625         }
1626
1627         fnum = cli_open(&cli, fname2, 
1628                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1629         cli_write(&cli, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
1630         cli_close(&cli, fnum);
1631         if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2, 
1632                             &w_time, &size, NULL, NULL)) {
1633                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1634         } else {
1635                 if (m_time2 == m_time)
1636                         printf("This system does not update directory modification times\n");
1637         }
1638         cli_unlink(&cli, fname2);
1639         cli_rmdir(&cli, dname);
1640
1641
1642         close_connection(&cli);
1643
1644         printf("trans2 test finished\n");
1645 }
1646
1647
1648 /*
1649   this is a harness for some oplock tests
1650  */
1651 static void run_oplock(int dummy)
1652 {
1653         static struct cli_state cli1;
1654         char *fname = "\\lockt1.lck";
1655         int fnum1;
1656
1657         printf("starting oplock test\n");
1658
1659         if (!open_connection(&cli1)) {
1660                 return;
1661         }
1662
1663         cli_unlink(&cli1, fname);
1664
1665         cli_sockopt(&cli1, sockops);
1666
1667         cli1.use_oplocks = True;
1668
1669         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1670         if (fnum1 == -1) {
1671                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1672                 return;
1673         }
1674
1675         cli1.use_oplocks = False;
1676
1677         cli_unlink(&cli1, fname);
1678         cli_unlink(&cli1, fname);
1679
1680         if (!cli_close(&cli1, fnum1)) {
1681                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
1682                 return;
1683         }
1684
1685         if (!cli_unlink(&cli1, fname)) {
1686                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1687                 return;
1688         }
1689
1690
1691         close_connection(&cli1);
1692
1693         printf("finished oplock test\n");
1694 }
1695
1696
1697 static void list_fn(file_info *finfo, const char *name)
1698 {
1699         
1700 }
1701
1702 /*
1703   test directory listing speed
1704  */
1705 static void run_dirtest(int dummy)
1706 {
1707         int i;
1708         static struct cli_state cli;
1709         int fnum;
1710         double t1;
1711
1712         printf("starting directory test\n");
1713
1714         if (!open_connection(&cli)) {
1715                 return;
1716         }
1717
1718         cli_sockopt(&cli, sockops);
1719
1720         srandom(0);
1721         for (i=0;i<numops;i++) {
1722                 fstring fname;
1723                 slprintf(fname, sizeof(fname), "%x", (int)random());
1724                 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
1725                 if (fnum == -1) {
1726                         fprintf(stderr,"Failed to open %s\n", fname);
1727                         return;
1728                 }
1729                 cli_close(&cli, fnum);
1730         }
1731
1732         t1 = end_timer();
1733
1734         printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn));
1735         printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn));
1736         printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn));
1737
1738         printf("dirtest core %g seconds\n", end_timer() - t1);
1739
1740         srandom(0);
1741         for (i=0;i<numops;i++) {
1742                 fstring fname;
1743                 slprintf(fname, sizeof(fname), "%x", (int)random());
1744                 cli_unlink(&cli, fname);
1745         }
1746
1747         close_connection(&cli);
1748
1749         printf("finished dirtest\n");
1750 }
1751
1752
1753
1754 static double create_procs(void (*fn)(int))
1755 {
1756         int i, status;
1757         volatile int *child_status;
1758         int synccount;
1759         int tries = 8;
1760
1761         start_timer();
1762
1763         synccount = 0;
1764
1765         child_status = (volatile int *)shm_setup(sizeof(int)*nprocs);
1766         if (!child_status) {
1767                 printf("Failed to setup shared memory\n");
1768                 return end_timer();
1769         }
1770
1771         memset((char *)child_status, 0, sizeof(int)*nprocs);
1772
1773         for (i=0;i<nprocs;i++) {
1774                 if (fork() == 0) {
1775                         pid_t mypid = getpid();
1776                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
1777
1778                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
1779
1780                         while (1) {
1781                                 memset(&current_cli, 0, sizeof(current_cli));
1782                                 if (open_connection(&current_cli)) break;
1783                                 if (tries-- == 0) {
1784                                         printf("pid %d failed to start\n", (int)getpid());
1785                                         _exit(1);
1786                                 }
1787                                 msleep(10);
1788                         }
1789
1790                         child_status[i] = getpid();
1791
1792                         while (child_status[i]) msleep(2);
1793
1794                         fn(i);
1795                         _exit(0);
1796                 }
1797         }
1798
1799         do {
1800                 synccount = 0;
1801                 for (i=0;i<nprocs;i++) {
1802                         if (child_status[i]) synccount++;
1803                 }
1804                 if (synccount == nprocs) break;
1805                 msleep(10);
1806         } while (end_timer() < 30);
1807
1808         if (synccount != nprocs) {
1809                 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
1810                 return end_timer();
1811         }
1812
1813         /* start the client load */
1814         start_timer();
1815
1816         for (i=0;i<nprocs;i++) {
1817                 child_status[i] = 0;
1818         }
1819
1820         printf("%d clients started\n", nprocs);
1821
1822         for (i=0;i<nprocs;i++) {
1823                 waitpid(0, &status, 0);
1824                 printf("*");
1825         }
1826         printf("\n");
1827         return end_timer();
1828 }
1829
1830
1831 #define FLAG_MULTIPROC 1
1832
1833 static struct {
1834         char *name;
1835         void (*fn)(int);
1836         unsigned flags;
1837 } torture_ops[] = {
1838         {"FDPASS", run_fdpasstest, 0},
1839         {"LOCK1",  run_locktest1,  0},
1840         {"LOCK2",  run_locktest2,  0},
1841         {"LOCK3",  run_locktest3,  0},
1842         {"LOCK4",  run_locktest4,  0},
1843         {"LOCK5",  run_locktest5,  0},
1844         {"UNLINK", run_unlinktest, 0},
1845         {"BROWSE", run_browsetest, 0},
1846         {"ATTR",   run_attrtest,   0},
1847         {"TRANS2", run_trans2test, 0},
1848         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
1849         {"TORTURE",run_torture,    FLAG_MULTIPROC},
1850         {"RANDOMIPC", run_randomipc, 0},
1851         {"NBW95",  run_nbw95, 0},
1852         {"NBWNT",  run_nbwnt, 0},
1853         {"OPLOCK",  run_oplock, 0},
1854         {"DIR",  run_dirtest, 0},
1855         {"DENY1",  run_denytest1, 0},
1856         {"DENY2",  run_denytest2, 0},
1857         {"TCON",  run_tcon_test, 0},
1858         {NULL, NULL, 0}};
1859
1860
1861 /****************************************************************************
1862 run a specified test or "ALL"
1863 ****************************************************************************/
1864 static void run_test(char *name)
1865 {
1866         int i;
1867         if (strequal(name,"ALL")) {
1868                 for (i=0;torture_ops[i].name;i++) {
1869                         run_test(torture_ops[i].name);
1870                 }
1871         }
1872         
1873         for (i=0;torture_ops[i].name;i++) {
1874                 if (strequal(name, torture_ops[i].name)) {
1875                         start_timer();
1876                         printf("Running %s\n", name);
1877                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
1878                                 create_procs(torture_ops[i].fn);
1879                         } else {
1880                                 torture_ops[i].fn(0);
1881                         }
1882                         printf("%s took %g secs\n\n", name, end_timer());
1883                 }
1884         }
1885 }
1886
1887
1888 static void usage(void)
1889 {
1890         int i;
1891
1892         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
1893
1894         printf("\t-U user%%pass\n");
1895         printf("\t-N numprocs\n");
1896         printf("\t-n my_netbios_name\n");
1897         printf("\t-W workgroup\n");
1898         printf("\t-o num_operations\n");
1899         printf("\t-O socket_options\n");
1900         printf("\t-m maximum protocol\n");
1901         printf("\n\n");
1902
1903         printf("tests are:");
1904         for (i=0;torture_ops[i].name;i++) {
1905                 printf(" %s", torture_ops[i].name);
1906         }
1907         printf("\n");
1908
1909         printf("default test is ALL\n");
1910         
1911         exit(1);
1912 }
1913
1914
1915
1916
1917
1918 /****************************************************************************
1919   main program
1920 ****************************************************************************/
1921  int main(int argc,char *argv[])
1922 {
1923         int opt, i;
1924         char *p;
1925         int gotpass = 0;
1926         extern char *optarg;
1927         extern int optind;
1928         extern FILE *dbf;
1929         static pstring servicesf = CONFIGFILE;
1930
1931         dbf = stdout;
1932
1933         setbuffer(stdout, NULL, 0);
1934
1935         charset_initialise();
1936
1937         lp_load(servicesf,True,False,False);
1938         load_interfaces();
1939
1940         if (argc < 2) {
1941                 usage();
1942         }
1943
1944         for(p = argv[1]; *p; p++)
1945           if(*p == '\\')
1946             *p = '/';
1947  
1948         if (strncmp(argv[1], "//", 2)) {
1949                 usage();
1950         }
1951
1952         fstrcpy(host, &argv[1][2]);
1953         p = strchr(&host[2],'/');
1954         if (!p) {
1955                 usage();
1956         }
1957         *p = 0;
1958         fstrcpy(share, p+1);
1959
1960         get_myname(myname);
1961
1962         if (*username == 0 && getenv("LOGNAME")) {
1963           pstrcpy(username,getenv("LOGNAME"));
1964         }
1965
1966         argc--;
1967         argv++;
1968
1969
1970         fstrcpy(workgroup, lp_workgroup());
1971
1972         while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
1973                 switch (opt) {
1974                 case 'W':
1975                         fstrcpy(workgroup,optarg);
1976                         break;
1977                 case 'm':
1978                         max_protocol = interpret_protocol(optarg, max_protocol);
1979                         break;
1980                 case 'N':
1981                         nprocs = atoi(optarg);
1982                         break;
1983                 case 'o':
1984                         numops = atoi(optarg);
1985                         break;
1986                 case 'O':
1987                         sockops = optarg;
1988                         break;
1989                 case 'n':
1990                         fstrcpy(myname, optarg);
1991                         break;
1992                 case 'U':
1993                         pstrcpy(username,optarg);
1994                         p = strchr(username,'%');
1995                         if (p) {
1996                                 *p = 0;
1997                                 pstrcpy(password, p+1);
1998                                 gotpass = 1;
1999                         }
2000                         break;
2001                 default:
2002                         printf("Unknown option %c (%d)\n", (char)opt, opt);
2003                         usage();
2004                 }
2005         }
2006
2007
2008         while (!gotpass) {
2009                 p = getpass("Password:");
2010                 if (p) {
2011                         pstrcpy(password, p);
2012                         gotpass = 1;
2013                 }
2014         }
2015
2016         printf("host=%s share=%s user=%s myname=%s\n", 
2017                host, share, username, myname);
2018
2019         if (argc == 1) {
2020                 run_test("ALL");
2021         } else {
2022                 for (i=1;i<argc;i++) {
2023                         run_test(argv[i]);
2024                 }
2025         }
2026
2027         return(0);
2028 }