2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
SMB torture tester
Copyright ( C ) Andrew Tridgell 1997 - 2003
2006-03-14 18:02:05 +03:00
Copyright ( C ) Jelmer Vernooij 2006
2003-08-13 05:53:07 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2004-11-02 05:57:18 +03:00
# include "lib/cmdline/popt_common.h"
2004-11-01 04:03:22 +03:00
# include "libcli/raw/libcliraw.h"
2004-11-02 03:24:21 +03:00
# include "system/time.h"
2004-11-02 07:51:57 +03:00
# include "system/wait.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2006-02-23 18:52:24 +03:00
# include "libcli/raw/ioctl.h"
2006-01-03 18:40:05 +03:00
# include "libcli/libcli.h"
2006-03-05 19:05:26 +03:00
# include "lib/ldb/include/ldb.h"
2006-03-06 08:16:00 +03:00
# include "lib/events/events.h"
2006-03-07 14:07:23 +03:00
# include "libcli/resolve/resolve.h"
2006-03-14 04:29:56 +03:00
# include "auth/credentials/credentials.h"
2006-03-14 18:02:05 +03:00
# include "libcli/ldap/ldap_client.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/ndr_nbt.h"
2003-08-13 05:53:07 +04:00
2006-02-04 17:08:24 +03:00
# include "torture/raw/proto.h"
# include "torture/smb2/proto.h"
# include "torture/rap/proto.h"
# include "torture/auth/proto.h"
# include "torture/local/proto.h"
# include "torture/nbench/proto.h"
# include "torture/ldap/proto.h"
# include "torture/com/proto.h"
# include "torture/nbt/proto.h"
# include "torture/libnet/proto.h"
2006-03-07 02:28:18 +03:00
# include "torture/torture.h"
2006-03-17 19:45:24 +03:00
# include "torture/util.h"
2006-03-14 00:21:44 +03:00
# include "build.h"
# include "dlinklist.h"
2006-02-04 17:08:24 +03:00
2006-03-17 19:27:22 +03:00
_PUBLIC_ int torture_nprocs = 4 ;
2006-03-17 19:11:02 +03:00
_PUBLIC_ int torture_numops = 10 ;
_PUBLIC_ int torture_entries = 1000 ;
_PUBLIC_ int torture_failures = 1 ;
_PUBLIC_ int torture_seed = 0 ;
2006-03-17 19:27:22 +03:00
_PUBLIC_ BOOL use_oplocks ;
2003-08-13 05:53:07 +04:00
static int procnum ; /* records process count number when forking */
2004-08-04 17:23:35 +04:00
static struct smbcli_state * current_cli ;
2006-03-17 19:45:24 +03:00
_PUBLIC_ BOOL use_level_II_oplocks ;
2006-03-17 19:11:02 +03:00
_PUBLIC_ BOOL torture_showall = False ;
2003-08-13 05:53:07 +04:00
2006-03-17 19:45:24 +03:00
2003-08-13 05:53:07 +04:00
2006-03-17 19:45:24 +03:00
2004-08-04 17:23:35 +04:00
static BOOL wait_lock ( struct smbcli_state * c , int fnum , uint32_t offset , uint32_t len )
2003-08-13 05:53:07 +04:00
{
2004-08-04 17:23:35 +04:00
while ( NT_STATUS_IS_ERR ( smbcli_lock ( c - > tree , fnum , offset , len , - 1 , WRITE_LOCK ) ) ) {
2004-10-17 06:52:37 +04:00
if ( ! check_error ( __location__ , c , ERRDOS , ERRlock , NT_STATUS_LOCK_NOT_GRANTED ) ) return False ;
2003-08-13 05:53:07 +04:00
}
return True ;
}
2004-08-04 17:23:35 +04:00
static BOOL rw_torture ( struct smbcli_state * c )
2003-08-13 05:53:07 +04:00
{
const char * lockfname = " \\ torture.lck " ;
char * fname ;
int fnum ;
int fnum2 ;
pid_t pid2 , pid = getpid ( ) ;
int i , j ;
2004-12-04 16:56:25 +03:00
uint8_t buf [ 1024 ] ;
2003-08-13 05:53:07 +04:00
BOOL correct = True ;
2004-08-04 17:23:35 +04:00
fnum2 = smbcli_open ( c - > tree , lockfname , O_RDWR | O_CREAT | O_EXCL ,
2003-08-13 05:53:07 +04:00
DENY_NONE ) ;
if ( fnum2 = = - 1 )
2004-08-04 17:23:35 +04:00
fnum2 = smbcli_open ( c - > tree , lockfname , O_RDWR , DENY_NONE ) ;
2003-08-13 05:53:07 +04:00
if ( fnum2 = = - 1 ) {
2004-08-04 17:23:35 +04:00
printf ( " open of %s failed (%s) \n " , lockfname , smbcli_errstr ( c - > tree ) ) ;
2003-08-13 05:53:07 +04:00
return False ;
}
for ( i = 0 ; i < torture_numops ; i + + ) {
2005-01-21 16:16:33 +03:00
uint_t n = ( uint_t ) random ( ) % 10 ;
2003-08-13 05:53:07 +04:00
if ( i % 10 = = 0 ) {
printf ( " %d \r " , i ) ; fflush ( stdout ) ;
}
asprintf ( & fname , " \\ torture.%u " , n ) ;
if ( ! wait_lock ( c , fnum2 , n * sizeof ( int ) , sizeof ( int ) ) ) {
return False ;
}
2004-08-04 17:23:35 +04:00
fnum = smbcli_open ( c - > tree , fname , O_RDWR | O_CREAT | O_TRUNC , DENY_ALL ) ;
2003-08-13 05:53:07 +04:00
if ( fnum = = - 1 ) {
2004-08-04 17:23:35 +04:00
printf ( " open failed (%s) \n " , smbcli_errstr ( c - > tree ) ) ;
2003-08-13 05:53:07 +04:00
correct = False ;
break ;
}
2004-12-04 16:56:25 +03:00
if ( smbcli_write ( c - > tree , fnum , 0 , & pid , 0 , sizeof ( pid ) ) ! = sizeof ( pid ) ) {
2004-08-04 17:23:35 +04:00
printf ( " write failed (%s) \n " , smbcli_errstr ( c - > tree ) ) ;
2003-08-13 05:53:07 +04:00
correct = False ;
}
for ( j = 0 ; j < 50 ; j + + ) {
2004-12-04 16:56:25 +03:00
if ( smbcli_write ( c - > tree , fnum , 0 , buf ,
2003-08-13 05:53:07 +04:00
sizeof ( pid ) + ( j * sizeof ( buf ) ) ,
sizeof ( buf ) ) ! = sizeof ( buf ) ) {
2004-08-04 17:23:35 +04:00
printf ( " write failed (%s) \n " , smbcli_errstr ( c - > tree ) ) ;
2003-08-13 05:53:07 +04:00
correct = False ;
}
}
pid2 = 0 ;
2004-12-04 16:56:25 +03:00
if ( smbcli_read ( c - > tree , fnum , & pid2 , 0 , sizeof ( pid ) ) ! = sizeof ( pid ) ) {
2004-08-04 17:23:35 +04:00
printf ( " read failed (%s) \n " , smbcli_errstr ( c - > tree ) ) ;
2003-08-13 05:53:07 +04:00
correct = False ;
}
if ( pid2 ! = pid ) {
printf ( " data corruption! \n " ) ;
correct = False ;
}
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_IS_ERR ( smbcli_close ( c - > tree , fnum ) ) ) {
printf ( " close failed (%s) \n " , smbcli_errstr ( c - > tree ) ) ;
2003-08-13 05:53:07 +04:00
correct = False ;
}
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_IS_ERR ( smbcli_unlink ( c - > tree , fname ) ) ) {
printf ( " unlink failed (%s) \n " , smbcli_errstr ( c - > tree ) ) ;
2003-08-13 05:53:07 +04:00
correct = False ;
}
2004-08-04 17:23:35 +04:00
if ( NT_STATUS_IS_ERR ( smbcli_unlock ( c - > tree , fnum2 , n * sizeof ( int ) , sizeof ( int ) ) ) ) {
printf ( " unlock failed (%s) \n " , smbcli_errstr ( c - > tree ) ) ;
2003-08-13 05:53:07 +04:00
correct = False ;
}
2006-03-17 19:11:02 +03:00
free ( fname ) ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 19:11:02 +03:00
smbcli_close ( c - > tree , fnum2 ) ;
smbcli_unlink ( c - > tree , lockfname ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
printf ( " %d \n " , i ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
return correct ;
}
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
static BOOL run_torture ( struct smbcli_state * cli , int dummy )
{
BOOL ret ;
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
ret = rw_torture ( cli ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
if ( ! torture_close_connection ( cli ) ) {
ret = False ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 19:11:02 +03:00
return ret ;
}
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
/*
see how many RPC pipes we can open at once
*/
static BOOL run_pipe_number ( void )
{
struct smbcli_state * cli1 ;
const char * pipe_name = " \\ WKSSVC " ;
int fnum ;
int num_pipes = 0 ;
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
printf ( " starting pipenumber test \n " ) ;
if ( ! torture_open_connection ( & cli1 ) ) {
2003-08-13 05:53:07 +04:00
return False ;
}
2006-03-17 19:11:02 +03:00
while ( 1 ) {
fnum = smbcli_nt_create_full ( cli1 - > tree , pipe_name , 0 , SEC_FILE_READ_DATA , FILE_ATTRIBUTE_NORMAL ,
NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE , NTCREATEX_DISP_OPEN_IF , 0 , 0 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
if ( fnum = = - 1 ) {
printf ( " Open of pipe %s failed with error (%s) \n " , pipe_name , smbcli_errstr ( cli1 - > tree ) ) ;
break ;
}
num_pipes + + ;
printf ( " %d \r " , num_pipes ) ;
fflush ( stdout ) ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 19:11:02 +03:00
printf ( " pipe_number test - we can open %d %s pipes. \n " , num_pipes , pipe_name ) ;
torture_close_connection ( cli1 ) ;
return True ;
}
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
/*
open N connections to the server and just hold them open
used for testing performance when there are N idle users
already connected
*/
static BOOL torture_holdcon ( void )
{
int i ;
struct smbcli_state * * cli ;
int num_dead = 0 ;
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
printf ( " Opening %d connections \n " , torture_numops ) ;
cli = malloc_array_p ( struct smbcli_state * , torture_numops ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
for ( i = 0 ; i < torture_numops ; i + + ) {
if ( ! torture_open_connection ( & cli [ i ] ) ) {
return False ;
}
printf ( " opened %d connections \r " , i ) ;
fflush ( stdout ) ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 19:11:02 +03:00
printf ( " \n Starting pings \n " ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
while ( 1 ) {
for ( i = 0 ; i < torture_numops ; i + + ) {
NTSTATUS status ;
if ( cli [ i ] ) {
status = smbcli_chkpath ( cli [ i ] - > tree , " \\ " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Connection %d is dead \n " , i ) ;
cli [ i ] = NULL ;
num_dead + + ;
}
usleep ( 100 ) ;
}
}
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
if ( num_dead = = torture_numops ) {
printf ( " All connections dead - finishing \n " ) ;
break ;
}
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
printf ( " . " ) ;
fflush ( stdout ) ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 19:11:02 +03:00
return True ;
}
2004-05-25 03:40:50 +04:00
2006-03-17 19:11:02 +03:00
/*
test how many open files this server supports on the one socket
*/
static BOOL run_maxfidtest ( struct smbcli_state * cli , int dummy )
{
# define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d"
char * fname ;
int fnums [ 0x11000 ] , i ;
int retries = 4 , maxfid ;
BOOL correct = True ;
2004-05-25 03:40:50 +04:00
2006-03-17 19:11:02 +03:00
if ( retries < = 0 ) {
printf ( " failed to connect \n " ) ;
2004-05-25 03:40:50 +04:00
return False ;
}
2006-03-17 19:11:02 +03:00
if ( smbcli_deltree ( cli - > tree , " \\ maxfid " ) = = - 1 ) {
printf ( " Failed to deltree \\ maxfid - %s \n " ,
smbcli_errstr ( cli - > tree ) ) ;
2004-05-25 03:40:50 +04:00
return False ;
}
2006-03-17 19:11:02 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_mkdir ( cli - > tree , " \\ maxfid " ) ) ) {
printf ( " Failed to mkdir \\ maxfid, error=%s \n " ,
smbcli_errstr ( cli - > tree ) ) ;
2004-05-25 03:40:50 +04:00
return False ;
}
2006-03-17 19:11:02 +03:00
printf ( " Testing maximum number of open files \n " ) ;
2004-05-25 03:40:50 +04:00
2006-03-17 19:11:02 +03:00
for ( i = 0 ; i < 0x11000 ; i + + ) {
if ( i % 1000 = = 0 ) {
asprintf ( & fname , " \\ maxfid \\ fid%d " , i / 1000 ) ;
if ( NT_STATUS_IS_ERR ( smbcli_mkdir ( cli - > tree , fname ) ) ) {
printf ( " Failed to mkdir %s, error=%s \n " ,
fname , smbcli_errstr ( cli - > tree ) ) ;
return False ;
}
free ( fname ) ;
}
asprintf ( & fname , MAXFID_TEMPLATE , i / 1000 , i , ( int ) getpid ( ) ) ;
if ( ( fnums [ i ] = smbcli_open ( cli - > tree , fname ,
O_RDWR | O_CREAT | O_TRUNC , DENY_NONE ) ) = =
- 1 ) {
printf ( " open of %s failed (%s) \n " ,
fname , smbcli_errstr ( cli - > tree ) ) ;
printf ( " maximum fnum is %d \n " , i ) ;
break ;
}
free ( fname ) ;
printf ( " %6d \r " , i ) ;
2004-05-25 03:40:50 +04:00
}
2006-03-17 19:11:02 +03:00
printf ( " %6d \n " , i ) ;
i - - ;
2004-05-25 03:40:50 +04:00
2006-03-17 19:11:02 +03:00
maxfid = i ;
2004-05-25 03:40:50 +04:00
2006-03-17 19:11:02 +03:00
printf ( " cleaning up \n " ) ;
for ( i = 0 ; i < maxfid / 2 ; i + + ) {
asprintf ( & fname , MAXFID_TEMPLATE , i / 1000 , i , ( int ) getpid ( ) ) ;
if ( NT_STATUS_IS_ERR ( smbcli_close ( cli - > tree , fnums [ i ] ) ) ) {
printf ( " Close of fnum %d failed - %s \n " , fnums [ i ] , smbcli_errstr ( cli - > tree ) ) ;
}
if ( NT_STATUS_IS_ERR ( smbcli_unlink ( cli - > tree , fname ) ) ) {
printf ( " unlink of %s failed (%s) \n " ,
fname , smbcli_errstr ( cli - > tree ) ) ;
correct = False ;
}
free ( fname ) ;
2004-05-25 03:40:50 +04:00
2006-03-17 19:11:02 +03:00
asprintf ( & fname , MAXFID_TEMPLATE , ( maxfid - i ) / 1000 , maxfid - i , ( int ) getpid ( ) ) ;
if ( NT_STATUS_IS_ERR ( smbcli_close ( cli - > tree , fnums [ maxfid - i ] ) ) ) {
printf ( " Close of fnum %d failed - %s \n " , fnums [ maxfid - i ] , smbcli_errstr ( cli - > tree ) ) ;
}
if ( NT_STATUS_IS_ERR ( smbcli_unlink ( cli - > tree , fname ) ) ) {
printf ( " unlink of %s failed (%s) \n " ,
fname , smbcli_errstr ( cli - > tree ) ) ;
correct = False ;
}
free ( fname ) ;
2004-05-25 03:40:50 +04:00
2006-03-17 19:11:02 +03:00
printf ( " %6d %6d \r " , i , maxfid - i ) ;
}
printf ( " %6d \n " , 0 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 19:11:02 +03:00
if ( smbcli_deltree ( cli - > tree , " \\ maxfid " ) = = - 1 ) {
printf ( " Failed to deltree \\ maxfid - %s \n " ,
smbcli_errstr ( cli - > tree ) ) ;
return False ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 19:11:02 +03:00
printf ( " maxfid test finished \n " ) ;
if ( ! torture_close_connection ( cli ) ) {
2003-08-13 05:53:07 +04:00
correct = False ;
}
return correct ;
2006-03-17 19:11:02 +03:00
# undef MAXFID_TEMPLATE
2003-08-13 05:53:07 +04:00
}
2006-03-17 19:11:02 +03:00
2003-08-13 05:53:07 +04:00
/*
sees what IOCTLs are supported
*/
2006-03-17 19:45:24 +03:00
static BOOL torture_ioctl_test ( void )
2003-08-13 05:53:07 +04:00
{
2004-08-04 17:23:35 +04:00
struct smbcli_state * cli ;
2004-05-25 21:24:24 +04:00
uint16_t device , function ;
2003-08-13 05:53:07 +04:00
int fnum ;
const char * fname = " \\ ioctl.dat " ;
NTSTATUS status ;
2003-12-04 05:03:06 +03:00
union smb_ioctl parms ;
2003-08-13 05:53:07 +04:00
TALLOC_CTX * mem_ctx ;
if ( ! torture_open_connection ( & cli ) ) {
return False ;
}
mem_ctx = talloc_init ( " ioctl_test " ) ;
printf ( " starting ioctl test \n " ) ;
2004-08-04 17:23:35 +04:00
smbcli_unlink ( cli - > tree , fname ) ;
2003-08-13 05:53:07 +04:00
2004-08-04 17:23:35 +04:00
fnum = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT | O_EXCL , DENY_NONE ) ;
2003-08-13 05:53:07 +04:00
if ( fnum = = - 1 ) {
2004-08-04 17:23:35 +04:00
printf ( " open of %s failed (%s) \n " , fname , smbcli_errstr ( cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
return False ;
}
2003-12-04 05:03:06 +03:00
parms . ioctl . level = RAW_IOCTL_IOCTL ;
2006-03-13 01:48:25 +03:00
parms . ioctl . in . file . fnum = fnum ;
2003-12-04 05:03:06 +03:00
parms . ioctl . in . request = IOCTL_QUERY_JOB_INFO ;
2003-08-13 05:53:07 +04:00
status = smb_raw_ioctl ( cli - > tree , mem_ctx , & parms ) ;
2004-08-04 17:23:35 +04:00
printf ( " ioctl job info: %s \n " , smbcli_errstr ( cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
for ( device = 0 ; device < 0x100 ; device + + ) {
printf ( " testing device=0x%x \n " , device ) ;
for ( function = 0 ; function < 0x100 ; function + + ) {
2003-12-04 05:03:06 +03:00
parms . ioctl . in . request = ( device < < 16 ) | function ;
2003-08-13 05:53:07 +04:00
status = smb_raw_ioctl ( cli - > tree , mem_ctx , & parms ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
printf ( " ioctl device=0x%x function=0x%x OK : %d bytes \n " ,
2005-07-17 13:20:52 +04:00
device , function , ( int ) parms . ioctl . out . blob . length ) ;
2003-08-13 05:53:07 +04:00
}
}
}
if ( ! torture_close_connection ( cli ) ) {
return False ;
}
return True ;
}
2004-10-28 17:19:39 +04:00
static void sigcont ( int sig )
2003-10-29 07:21:58 +03:00
{
}
2004-08-04 17:23:35 +04:00
double torture_create_procs ( BOOL ( * fn ) ( struct smbcli_state * , int ) , BOOL * result )
2003-08-13 05:53:07 +04:00
{
int i , status ;
volatile pid_t * child_status ;
volatile BOOL * child_status_out ;
int synccount ;
int tries = 8 ;
2004-03-09 05:13:13 +03:00
double start_time_limit = 10 + ( torture_nprocs * 1.5 ) ;
2004-03-09 12:04:06 +03:00
char * * unc_list = NULL ;
2004-06-14 03:50:55 +04:00
const char * p ;
2004-03-09 12:04:06 +03:00
int num_unc_names = 0 ;
2004-11-03 13:09:48 +03:00
struct timeval tv ;
2003-08-13 05:53:07 +04:00
2005-01-02 10:51:13 +03:00
* result = True ;
2003-08-13 05:53:07 +04:00
synccount = 0 ;
2003-10-29 07:21:58 +03:00
signal ( SIGCONT , sigcont ) ;
2004-03-09 05:13:13 +03:00
child_status = ( volatile pid_t * ) shm_setup ( sizeof ( pid_t ) * torture_nprocs ) ;
2003-08-13 05:53:07 +04:00
if ( ! child_status ) {
printf ( " Failed to setup shared memory \n " ) ;
return - 1 ;
}
2004-03-09 05:13:13 +03:00
child_status_out = ( volatile BOOL * ) shm_setup ( sizeof ( BOOL ) * torture_nprocs ) ;
2003-08-13 05:53:07 +04:00
if ( ! child_status_out ) {
printf ( " Failed to setup result status shared memory \n " ) ;
return - 1 ;
}
2004-03-09 12:04:06 +03:00
p = lp_parm_string ( - 1 , " torture " , " unclist " ) ;
if ( p ) {
2005-07-10 05:10:09 +04:00
unc_list = file_lines_load ( p , & num_unc_names , NULL ) ;
2004-03-09 12:04:06 +03:00
if ( ! unc_list | | num_unc_names < = 0 ) {
2004-09-10 06:16:41 +04:00
printf ( " Failed to load unc names list from '%s' \n " , p ) ;
2004-03-09 12:04:06 +03:00
exit ( 1 ) ;
}
}
2004-03-09 05:13:13 +03:00
for ( i = 0 ; i < torture_nprocs ; i + + ) {
2003-08-13 05:53:07 +04:00
child_status [ i ] = 0 ;
child_status_out [ i ] = True ;
}
2004-11-03 13:09:48 +03:00
tv = timeval_current ( ) ;
2003-08-13 05:53:07 +04:00
2004-03-09 05:13:13 +03:00
for ( i = 0 ; i < torture_nprocs ; i + + ) {
2003-08-13 05:53:07 +04:00
procnum = i ;
if ( fork ( ) = = 0 ) {
char * myname ;
2006-03-15 13:24:56 +03:00
char * hostname = NULL , * sharename ;
2004-03-09 12:04:06 +03:00
2003-08-13 05:53:07 +04:00
pid_t mypid = getpid ( ) ;
2005-01-21 16:16:33 +03:00
srandom ( ( ( int ) mypid ) ^ ( ( int ) time ( NULL ) ) ) ;
2003-08-13 05:53:07 +04:00
asprintf ( & myname , " CLIENT%d " , i ) ;
lp_set_cmdline ( " netbios name " , myname ) ;
free ( myname ) ;
2004-03-09 12:04:06 +03:00
if ( unc_list ) {
2005-01-15 14:58:52 +03:00
if ( ! smbcli_parse_unc ( unc_list [ i % num_unc_names ] ,
NULL , & hostname , & sharename ) ) {
2004-03-09 12:04:06 +03:00
printf ( " Failed to parse UNC name %s \n " ,
unc_list [ i % num_unc_names ] ) ;
exit ( 1 ) ;
}
}
2003-08-13 05:53:07 +04:00
while ( 1 ) {
2004-03-09 12:04:06 +03:00
if ( hostname ) {
2005-08-24 17:15:01 +04:00
if ( torture_open_connection_share ( NULL ,
& current_cli ,
2004-03-09 12:04:06 +03:00
hostname ,
2005-08-24 17:15:01 +04:00
sharename ,
NULL ) ) {
2004-03-09 12:04:06 +03:00
break ;
}
} else if ( torture_open_connection ( & current_cli ) ) {
break ;
}
2003-08-13 05:53:07 +04:00
if ( tries - - = = 0 ) {
printf ( " pid %d failed to start \n " , ( int ) getpid ( ) ) ;
_exit ( 1 ) ;
}
2003-09-29 10:04:23 +04:00
msleep ( 100 ) ;
2003-08-13 05:53:07 +04:00
}
child_status [ i ] = getpid ( ) ;
2003-10-29 07:21:58 +03:00
pause ( ) ;
2003-09-29 10:04:23 +04:00
if ( child_status [ i ] ) {
printf ( " Child %d failed to start! \n " , i ) ;
child_status_out [ i ] = 1 ;
_exit ( 1 ) ;
}
2003-08-13 05:53:07 +04:00
2004-03-09 05:13:13 +03:00
child_status_out [ i ] = fn ( current_cli , i ) ;
2003-08-13 05:53:07 +04:00
_exit ( 0 ) ;
}
}
do {
synccount = 0 ;
2004-03-09 05:13:13 +03:00
for ( i = 0 ; i < torture_nprocs ; i + + ) {
2003-08-13 05:53:07 +04:00
if ( child_status [ i ] ) synccount + + ;
}
2004-03-09 05:13:13 +03:00
if ( synccount = = torture_nprocs ) break ;
2003-09-29 10:04:23 +04:00
msleep ( 100 ) ;
2004-11-03 13:09:48 +03:00
} while ( timeval_elapsed ( & tv ) < start_time_limit ) ;
2003-08-13 05:53:07 +04:00
2004-03-09 05:13:13 +03:00
if ( synccount ! = torture_nprocs ) {
printf ( " FAILED TO START %d CLIENTS (started %d) \n " , torture_nprocs , synccount ) ;
2003-08-13 05:53:07 +04:00
* result = False ;
2004-11-03 13:09:48 +03:00
return timeval_elapsed ( & tv ) ;
2003-08-13 05:53:07 +04:00
}
2004-03-09 05:13:13 +03:00
printf ( " Starting %d clients \n " , torture_nprocs ) ;
2003-09-29 10:04:23 +04:00
2003-08-13 05:53:07 +04:00
/* start the client load */
2004-11-03 13:09:48 +03:00
tv = timeval_current ( ) ;
2004-03-09 05:13:13 +03:00
for ( i = 0 ; i < torture_nprocs ; i + + ) {
2003-08-13 05:53:07 +04:00
child_status [ i ] = 0 ;
}
2004-03-09 05:13:13 +03:00
printf ( " %d clients started \n " , torture_nprocs ) ;
2003-08-13 05:53:07 +04:00
2004-11-25 01:26:19 +03:00
kill ( 0 , SIGCONT ) ;
2004-03-09 05:13:13 +03:00
for ( i = 0 ; i < torture_nprocs ; i + + ) {
2003-09-29 10:04:23 +04:00
int ret ;
2005-09-23 04:38:22 +04:00
while ( ( ret = waitpid ( 0 , & status , 0 ) ) = = - 1 & & errno = = EINTR ) /* noop */ ;
2003-09-29 10:04:23 +04:00
if ( ret = = - 1 | | WEXITSTATUS ( status ) ! = 0 ) {
* result = False ;
}
2003-08-13 05:53:07 +04:00
}
printf ( " \n " ) ;
2004-03-09 05:13:13 +03:00
for ( i = 0 ; i < torture_nprocs ; i + + ) {
2003-08-13 05:53:07 +04:00
if ( ! child_status_out [ i ] ) {
* result = False ;
}
}
2004-11-03 13:09:48 +03:00
return timeval_elapsed ( & tv ) ;
2003-08-13 05:53:07 +04:00
}
# define FLAG_MULTIPROC 1
static struct {
const char * name ;
2004-10-28 17:40:50 +04:00
BOOL ( * fn ) ( void ) ;
BOOL ( * multi_fn ) ( struct smbcli_state * , int ) ;
2006-03-14 00:21:44 +03:00
} builtin_torture_ops [ ] = {
2004-08-03 08:44:27 +04:00
/* benchmarking tests */
{ " BENCH-HOLDCON " , torture_holdcon , 0 } ,
{ " BENCH-NBENCH " , torture_nbench , 0 } ,
2004-10-28 17:40:50 +04:00
{ " BENCH-TORTURE " , NULL , run_torture } ,
2005-01-31 12:54:39 +03:00
{ " BENCH-NBT " , torture_bench_nbt , 0 } ,
2005-02-15 07:55:56 +03:00
{ " BENCH-WINS " , torture_bench_wins , 0 } ,
2005-05-18 08:17:24 +04:00
{ " BENCH-CLDAP " , torture_bench_cldap , 0 } ,
2004-08-03 08:44:27 +04:00
/* RAW smb tests */
2003-08-13 05:53:07 +04:00
{ " RAW-QFSINFO " , torture_raw_qfsinfo , 0 } ,
{ " RAW-QFILEINFO " , torture_raw_qfileinfo , 0 } ,
{ " RAW-SFILEINFO " , torture_raw_sfileinfo , 0 } ,
{ " RAW-SFILEINFO-BUG " , torture_raw_sfileinfo_bug , 0 } ,
{ " RAW-SEARCH " , torture_raw_search , 0 } ,
{ " RAW-CLOSE " , torture_raw_close , 0 } ,
{ " RAW-OPEN " , torture_raw_open , 0 } ,
{ " RAW-MKDIR " , torture_raw_mkdir , 0 } ,
{ " RAW-OPLOCK " , torture_raw_oplock , 0 } ,
{ " RAW-NOTIFY " , torture_raw_notify , 0 } ,
{ " RAW-MUX " , torture_raw_mux , 0 } ,
{ " RAW-IOCTL " , torture_raw_ioctl , 0 } ,
{ " RAW-CHKPATH " , torture_raw_chkpath , 0 } ,
{ " RAW-UNLINK " , torture_raw_unlink , 0 } ,
{ " RAW-READ " , torture_raw_read , 0 } ,
{ " RAW-WRITE " , torture_raw_write , 0 } ,
{ " RAW-LOCK " , torture_raw_lock , 0 } ,
{ " RAW-CONTEXT " , torture_raw_context , 0 } ,
{ " RAW-RENAME " , torture_raw_rename , 0 } ,
{ " RAW-SEEK " , torture_raw_seek , 0 } ,
2004-11-15 09:55:27 +03:00
{ " RAW-EAS " , torture_raw_eas , 0 } ,
2005-07-01 15:50:30 +04:00
{ " RAW-EAMAX " , torture_max_eas , 0 } ,
2004-11-15 09:55:27 +03:00
{ " RAW-STREAMS " , torture_raw_streams , 0 } ,
2004-11-18 04:02:27 +03:00
{ " RAW-ACLS " , torture_raw_acls , 0 } ,
2004-07-12 20:35:48 +04:00
{ " RAW-RAP " , torture_raw_rap , 0 } ,
2005-01-12 10:03:29 +03:00
{ " RAW-COMPOSITE " , torture_raw_composite , 0 } ,
2004-08-03 08:44:27 +04:00
2005-11-11 07:46:48 +03:00
/* SMB2 tests */
{ " SMB2-CONNECT " , torture_smb2_connect , 0 } ,
2005-11-12 05:37:51 +03:00
{ " SMB2-SCAN " , torture_smb2_scan , 0 } ,
2005-11-12 10:48:56 +03:00
{ " SMB2-SCANGETINFO " , torture_smb2_getinfo_scan , 0 } ,
2005-11-18 12:25:25 +03:00
{ " SMB2-SCANSETINFO " , torture_smb2_setinfo_scan , 0 } ,
2005-11-19 09:39:12 +03:00
{ " SMB2-SCANFIND " , torture_smb2_find_scan , 0 } ,
2005-11-15 07:38:59 +03:00
{ " SMB2-GETINFO " , torture_smb2_getinfo , 0 } ,
2005-11-18 09:31:33 +03:00
{ " SMB2-SETINFO " , torture_smb2_setinfo , 0 } ,
2005-11-22 16:14:04 +03:00
{ " SMB2-FIND " , torture_smb2_find , 0 } ,
2005-11-11 07:46:48 +03:00
2004-08-03 08:44:27 +04:00
/* protocol scanners */
2004-10-28 17:40:50 +04:00
{ " SCAN-MAXFID " , NULL , run_maxfidtest } ,
2004-08-03 08:44:27 +04:00
{ " SCAN-PIPE_NUMBER " , run_pipe_number , 0 } ,
{ " SCAN-IOCTL " , torture_ioctl_test , 0 } ,
2005-01-25 04:21:59 +03:00
{ " SCAN-RAP " , torture_rap_scan , 0 } ,
2004-08-03 08:44:27 +04:00
2004-09-01 08:39:06 +04:00
/* local (no server) testers */
{ " LOCAL-NTLMSSP " , torture_ntlmssp_self_check , 0 } ,
{ " LOCAL-ICONV " , torture_local_iconv , 0 } ,
2004-09-28 09:42:02 +04:00
{ " LOCAL-TALLOC " , torture_local_talloc , 0 } ,
2004-10-17 14:04:49 +04:00
{ " LOCAL-MESSAGING " , torture_local_messaging , 0 } ,
2005-06-05 10:53:07 +04:00
{ " LOCAL-IRPC " , torture_local_irpc , 0 } ,
2004-10-24 17:00:51 +04:00
{ " LOCAL-BINDING " , torture_local_binding_string , 0 } ,
2005-09-26 21:42:12 +04:00
{ " LOCAL-STRLIST " , torture_local_util_strlist , 0 } ,
2005-09-29 01:54:29 +04:00
{ " LOCAL-FILE " , torture_local_util_file , 0 } ,
2004-10-22 10:46:04 +04:00
{ " LOCAL-IDTREE " , torture_local_idtree , 0 } ,
2005-01-19 06:20:20 +03:00
{ " LOCAL-SOCKET " , torture_local_socket , 0 } ,
2005-07-04 06:36:16 +04:00
{ " LOCAL-PAC " , torture_pac , 0 } ,
2005-09-29 02:16:30 +04:00
{ " LOCAL-REGISTRY " , torture_registry , 0 } ,
2005-09-13 16:44:33 +04:00
{ " LOCAL-RESOLVE " , torture_local_resolve , 0 } ,
2005-12-02 06:19:23 +03:00
{ " LOCAL-SDDL " , torture_local_sddl , 0 } ,
2005-12-29 23:35:56 +03:00
{ " LOCAL-NDR " , torture_local_ndr , 0 } ,
2004-08-03 08:44:27 +04:00
2004-08-12 12:00:45 +04:00
/* ldap testers */
{ " LDAP-BASIC " , torture_ldap_basic , 0 } ,
2005-05-10 06:03:47 +04:00
{ " LDAP-CLDAP " , torture_cldap , 0 } ,
2004-08-12 12:00:45 +04:00
2005-02-01 09:16:12 +03:00
/* nbt tests */
{ " NBT-REGISTER " , torture_nbt_register , 0 } ,
2005-02-10 06:22:47 +03:00
{ " NBT-WINS " , torture_nbt_wins , 0 } ,
2005-04-06 15:17:08 +04:00
{ " NBT-DGRAM " , torture_nbt_dgram , 0 } ,
2006-01-27 16:10:24 +03:00
{ " NBT-BROWSE " , torture_nbt_browse , 0 } ,
2006-02-22 15:10:29 +03:00
{ " NBT-WINSREPLICATION-SIMPLE " , torture_nbt_winsreplication_simple , 0 } ,
{ " NBT-WINSREPLICATION-REPLICA " , torture_nbt_winsreplication_replica , 0 } ,
{ " NBT-WINSREPLICATION-OWNED " , torture_nbt_winsreplication_owned , 0 } ,
2005-03-04 03:24:21 +03:00
2003-08-13 05:53:07 +04:00
{ NULL , NULL , 0 } } ;
2006-03-14 00:21:44 +03:00
static void register_builtin_ops ( void )
{
int i ;
for ( i = 0 ; builtin_torture_ops [ i ] . name ; i + + ) {
register_torture_op ( builtin_torture_ops [ i ] . name ,
builtin_torture_ops [ i ] . fn ,
builtin_torture_ops [ i ] . multi_fn ) ;
}
}
2006-03-17 19:27:22 +03:00
struct torture_op * torture_ops = NULL ;
2006-03-14 00:21:44 +03:00
2006-03-17 19:11:02 +03:00
_PUBLIC_ NTSTATUS register_torture_op ( const char * name , BOOL ( * fn ) ( void ) , BOOL ( * multi_fn ) ( struct smbcli_state * , int ) )
2006-03-14 00:21:44 +03:00
{
2006-03-17 20:20:24 +03:00
struct torture_op * op , * p ;
2006-03-14 00:21:44 +03:00
op = talloc ( talloc_autofree_context ( ) , struct torture_op ) ;
op - > name = talloc_strdup ( op , name ) ;
op - > fn = fn ;
op - > multi_fn = multi_fn ;
2006-03-17 20:20:24 +03:00
for ( p = torture_ops ; p ; p = p - > next ) {
if ( strcmp ( p - > name , op - > name ) = = 0 ) {
/* Check for duplicates */
DEBUG ( 0 , ( " There already is a torture op registered with the name %s! \n " , name ) ) ;
talloc_free ( op ) ;
return NT_STATUS_OBJECT_NAME_COLLISION ;
}
if ( strcmp ( p - > name , op - > name ) < 0 & &
( ! p - > next | | strcmp ( p - > next - > name , op - > name ) > 0 ) ) {
DLIST_ADD_AFTER ( torture_ops , op , p ) ;
return NT_STATUS_OK ;
}
}
2006-03-14 00:21:44 +03:00
DLIST_ADD ( torture_ops , op ) ;
return NT_STATUS_OK ;
}
2003-08-13 05:53:07 +04:00
2006-03-17 19:27:22 +03:00
int torture_init ( void )
2003-08-13 05:53:07 +04:00
{
2006-03-17 19:27:22 +03:00
init_module_fn static_init [ ] = STATIC_torture_MODULES ;
2006-03-14 00:21:44 +03:00
init_module_fn * shared_init = load_samba_modules ( NULL , " torture " ) ;
register_builtin_ops ( ) ;
run_init_functions ( static_init ) ;
run_init_functions ( shared_init ) ;
talloc_free ( shared_init ) ;
2006-03-17 19:27:22 +03:00
return 0 ;
2003-08-13 05:53:07 +04:00
}