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(¤t_cli, 0, sizeof(current_cli)); 1567 if (open_connection(¤t_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