1996-05-04 11:50:46 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-04 11:50:46 +04:00
status reporting
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
1996-05-04 11:50:46 +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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 11:50:46 +04:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-08-15 19:11:34 +04:00
Revision History :
12 aug 96 : Erik . Devriendt @ te6 . siemens . be
added support for shared memory implementation of share mode locking
1998-07-24 05:08:31 +04:00
21 - Jul - 1998 : rsharpe @ ns . aus . com ( Richard Sharpe )
Added - L ( locks only ) - S ( shares only ) flags and code
1996-05-04 11:50:46 +04:00
*/
/*
* This program reports current SMB connections
*/
# include "includes.h"
2003-11-13 01:35:50 +03:00
# define SMB_MAXPIDS 2048
2004-12-17 11:51:23 +03:00
static uid_t Ucrit_uid = 0 ; /* added by OH */
2007-05-07 19:31:12 +04:00
static struct server_id Ucrit_pid [ SMB_MAXPIDS ] ; /* Ugly !!! */ /* added by OH */
2003-11-13 01:35:50 +03:00
static int Ucrit_MaxPid = 0 ; /* added by OH */
static unsigned int Ucrit_IsActive = 0 ; /* added by OH */
2007-10-19 22:38:36 +04:00
static bool verbose , brief ;
static bool shares_only ; /* Added by RJS */
static bool locks_only ; /* Added by RJS */
static bool processes_only ;
static bool show_brl ;
static bool numeric_only ;
1998-07-24 05:08:31 +04:00
2004-11-12 02:30:32 +03:00
const char * username = NULL ;
2007-10-19 04:40:25 +04:00
extern bool status_profile_dump ( bool be_verbose ) ;
extern bool status_profile_rates ( bool be_verbose ) ;
2006-07-11 22:01:26 +04:00
1998-08-10 05:25:32 +04:00
/* added by OH */
2004-12-17 11:51:23 +03:00
static void Ucrit_addUid ( uid_t uid )
1998-08-10 05:25:32 +04:00
{
2004-12-17 11:51:23 +03:00
Ucrit_uid = uid ;
Ucrit_IsActive = 1 ;
1998-08-10 05:25:32 +04:00
}
2004-12-17 11:51:23 +03:00
static unsigned int Ucrit_checkUid ( uid_t uid )
1998-08-10 05:25:32 +04:00
{
2003-11-13 01:35:50 +03:00
if ( ! Ucrit_IsActive )
return 1 ;
2004-12-17 11:51:23 +03:00
if ( uid = = Ucrit_uid )
2003-11-13 01:35:50 +03:00
return 1 ;
1998-08-10 05:25:32 +04:00
return 0 ;
}
2007-05-07 19:31:12 +04:00
static unsigned int Ucrit_checkPid ( struct server_id pid )
1998-08-10 05:25:32 +04:00
{
int i ;
2003-11-13 01:35:50 +03:00
if ( ! Ucrit_IsActive )
return 1 ;
for ( i = 0 ; i < Ucrit_MaxPid ; i + + ) {
2007-05-07 19:31:12 +04:00
if ( cluster_id_equal ( & pid , & Ucrit_pid [ i ] ) )
2003-11-13 01:35:50 +03:00
return 1 ;
}
1998-08-10 05:25:32 +04:00
return 0 ;
}
2007-10-19 04:40:25 +04:00
static bool Ucrit_addPid ( struct server_id pid )
2003-11-13 01:35:50 +03:00
{
if ( ! Ucrit_IsActive )
return True ;
if ( Ucrit_MaxPid > = SMB_MAXPIDS ) {
d_printf ( " ERROR: More than %d pids for user %s! \n " ,
2004-12-17 11:51:23 +03:00
SMB_MAXPIDS , uidtoname ( Ucrit_uid ) ) ;
2003-11-13 01:35:50 +03:00
return False ;
}
Ucrit_pid [ Ucrit_MaxPid + + ] = pid ;
return True ;
}
1998-08-10 05:25:32 +04:00
2006-07-21 18:13:30 +04:00
static void print_share_mode ( const struct share_mode_entry * e ,
const char * sharepath ,
const char * fname ,
void * dummy )
1997-10-20 12:46:00 +04:00
{
static int count ;
2006-02-01 00:54:24 +03:00
if ( ! is_valid_share_mode_entry ( e ) ) {
return ;
}
2007-07-18 17:52:20 +04:00
if ( ! process_exists ( e - > pid ) ) {
return ;
}
1997-10-20 12:46:00 +04:00
if ( count = = 0 ) {
2001-09-08 06:59:23 +04:00
d_printf ( " Locked files: \n " ) ;
2006-06-21 06:31:12 +04:00
d_printf ( " Pid Uid DenyMode Access R/W Oplock SharePath Name Time \n " ) ;
d_printf ( " -------------------------------------------------------------------------------------------------- \n " ) ;
1997-10-20 12:46:00 +04:00
}
count + + ;
2007-05-07 19:31:12 +04:00
if ( Ucrit_checkPid ( e - > pid ) ) {
2006-01-23 17:26:48 +03:00
d_printf ( " %-11s " , procid_str_static ( & e - > pid ) ) ;
2006-06-21 06:31:12 +04:00
d_printf ( " %-9u " , ( unsigned int ) e - > uid ) ;
2005-07-08 08:51:27 +04:00
switch ( map_share_mode_to_deny_mode ( e - > share_access ,
e - > private_options ) ) {
case DENY_NONE : d_printf ( " DENY_NONE " ) ; break ;
case DENY_ALL : d_printf ( " DENY_ALL " ) ; break ;
case DENY_DOS : d_printf ( " DENY_DOS " ) ; break ;
case DENY_READ : d_printf ( " DENY_READ " ) ; break ;
case DENY_WRITE : printf ( " DENY_WRITE " ) ; break ;
case DENY_FCB : d_printf ( " DENY_FCB " ) ; break ;
default : {
d_printf ( " unknown-please report ! "
" e->share_access = 0x%x, "
" e->private_options = 0x%x \n " ,
( unsigned int ) e - > share_access ,
( unsigned int ) e - > private_options ) ;
break ;
}
}
d_printf ( " 0x%-8x " , ( unsigned int ) e - > access_mask ) ;
2005-09-14 00:13:33 +04:00
if ( ( e - > access_mask & ( FILE_READ_DATA | FILE_WRITE_DATA ) ) = =
( FILE_READ_DATA | FILE_WRITE_DATA ) ) {
2005-07-08 08:51:27 +04:00
d_printf ( " RDWR " ) ;
} else if ( e - > access_mask & FILE_WRITE_DATA ) {
d_printf ( " WRONLY " ) ;
} else {
d_printf ( " RDONLY " ) ;
}
if ( ( e - > op_type & ( EXCLUSIVE_OPLOCK | BATCH_OPLOCK ) ) = =
( EXCLUSIVE_OPLOCK | BATCH_OPLOCK ) ) {
d_printf ( " EXCLUSIVE+BATCH " ) ;
} else if ( e - > op_type & EXCLUSIVE_OPLOCK ) {
d_printf ( " EXCLUSIVE " ) ;
} else if ( e - > op_type & BATCH_OPLOCK ) {
d_printf ( " BATCH " ) ;
} else if ( e - > op_type & LEVEL_II_OPLOCK ) {
d_printf ( " LEVEL_II " ) ;
} else {
d_printf ( " NONE " ) ;
}
2007-03-06 02:40:03 +03:00
d_printf ( " %s %s %s " , sharepath , fname , time_to_asc ( ( time_t ) e - > time . tv_sec ) ) ;
1998-05-30 06:25:11 +04:00
}
1997-10-20 12:46:00 +04:00
}
1997-05-20 04:32:51 +04:00
2007-05-29 13:30:34 +04:00
static void print_brl ( struct file_id id ,
2007-05-07 13:35:35 +04:00
struct server_id pid ,
2006-04-10 19:33:04 +04:00
enum brl_type lock_type ,
enum brl_flavour lock_flav ,
br_off start ,
2007-05-29 17:26:44 +04:00
br_off size ,
void * private_data )
2000-01-16 14:14:44 +03:00
{
static int count ;
2007-05-29 13:30:34 +04:00
int i ;
static const struct {
enum brl_type lock_type ;
const char * desc ;
} lock_types [ ] = {
{ READ_LOCK , " R " } ,
{ WRITE_LOCK , " W " } ,
{ PENDING_READ_LOCK , " PR " } ,
{ PENDING_WRITE_LOCK , " PW " } ,
{ UNLOCK_LOCK , " U " }
} ;
const char * desc = " X " ;
2007-08-01 15:18:56 +04:00
const char * sharepath = " " ;
const char * fname = " " ;
struct share_mode_lock * share_mode ;
2000-01-16 14:14:44 +03:00
if ( count = = 0 ) {
2001-09-08 06:59:23 +04:00
d_printf ( " Byte range locks: \n " ) ;
2007-08-01 15:18:56 +04:00
d_printf ( " Pid dev:inode R/W start size SharePath Name \n " ) ;
d_printf ( " -------------------------------------------------------------------------------- \n " ) ;
2000-01-16 14:14:44 +03:00
}
count + + ;
2007-08-01 15:18:56 +04:00
share_mode = fetch_share_mode_unlocked ( NULL , id , " __unspecified__ " , " __unspecified__ " ) ;
if ( share_mode ) {
sharepath = share_mode - > servicepath ;
fname = share_mode - > filename ;
}
2007-05-29 13:30:34 +04:00
for ( i = 0 ; i < ARRAY_SIZE ( lock_types ) ; i + + ) {
if ( lock_type = = lock_types [ i ] . lock_type ) {
desc = lock_types [ i ] . desc ;
}
}
2007-08-01 15:18:56 +04:00
d_printf ( " %-10s %-15s %-4s %-9.0f %-9.0f %-24s %-24s \n " ,
2007-09-10 14:56:07 +04:00
procid_str_static ( & pid ) , file_id_string_tos ( & id ) ,
2007-05-29 13:30:34 +04:00
desc ,
2007-08-01 15:18:56 +04:00
( double ) start , ( double ) size ,
sharepath , fname ) ;
2007-08-02 13:22:47 +04:00
TALLOC_FREE ( share_mode ) ;
2000-01-16 14:14:44 +03:00
}
2007-05-28 15:38:42 +04:00
static int traverse_fn1 ( struct db_record * rec ,
2007-05-08 17:44:36 +04:00
const struct connections_key * key ,
const struct connections_data * crec ,
void * state )
1999-12-21 07:54:30 +03:00
{
2007-05-08 17:44:36 +04:00
if ( crec - > cnum = = - 1 )
2001-05-15 22:12:02 +04:00
return 0 ;
1999-12-21 07:54:30 +03:00
2007-05-08 17:44:36 +04:00
if ( ! process_exists ( crec - > pid ) | | ! Ucrit_checkUid ( crec - > uid ) ) {
1999-12-21 07:54:30 +03:00
return 0 ;
}
2005-09-30 21:13:37 +04:00
d_printf ( " %-10s %s %-12s %s " ,
2007-05-29 22:41:16 +04:00
crec - > servicename , procid_str_static ( & crec - > pid ) ,
crec - > machine ,
time_to_asc ( crec - > start ) ) ;
2001-08-22 23:11:55 +04:00
return 0 ;
}
2007-05-29 22:41:16 +04:00
static int traverse_sessionid ( struct db_record * db , void * state )
2001-08-22 23:11:55 +04:00
{
struct sessionid sessionid ;
2004-12-17 11:51:23 +03:00
fstring uid_str , gid_str ;
2001-08-22 23:11:55 +04:00
2007-05-29 22:41:16 +04:00
if ( db - > value . dsize ! = sizeof ( sessionid ) )
2001-08-22 23:11:55 +04:00
return 0 ;
2007-05-29 22:41:16 +04:00
memcpy ( & sessionid , db - > value . dptr , sizeof ( sessionid ) ) ;
2001-08-22 23:11:55 +04:00
2007-05-07 19:31:12 +04:00
if ( ! process_exists ( sessionid . pid ) | | ! Ucrit_checkUid ( sessionid . uid ) ) {
2001-08-22 23:11:55 +04:00
return 0 ;
1999-12-21 07:54:30 +03:00
}
2003-11-13 01:35:50 +03:00
Ucrit_addPid ( sessionid . pid ) ;
2004-12-17 11:51:23 +03:00
fstr_sprintf ( uid_str , " %d " , sessionid . uid ) ;
fstr_sprintf ( gid_str , " %d " , sessionid . gid ) ;
2007-05-29 22:41:16 +04:00
d_printf ( " %-7s %-12s %-12s %-12s (%s) \n " ,
2007-05-07 19:31:12 +04:00
procid_str_static ( & sessionid . pid ) ,
2004-12-17 11:51:23 +03:00
numeric_only ? uid_str : uidtoname ( sessionid . uid ) ,
numeric_only ? gid_str : gidtoname ( sessionid . gid ) ,
sessionid . remote_machine , sessionid . hostname ) ;
2001-08-22 23:11:55 +04:00
1999-12-21 07:54:30 +03:00
return 0 ;
}
1997-05-20 04:32:51 +04:00
1996-06-04 10:42:03 +04:00
int main ( int argc , char * argv [ ] )
1996-05-04 11:50:46 +04:00
{
1999-12-21 07:54:30 +03:00
int c ;
2006-07-11 22:01:26 +04:00
int profile_only = 0 ;
2007-10-19 04:40:25 +04:00
bool show_processes , show_locks , show_shares ;
2002-03-12 00:37:01 +03:00
poptContext pc ;
struct poptOption long_options [ ] = {
2002-10-28 22:50:06 +03:00
POPT_AUTOHELP
2007-10-19 22:38:36 +04:00
{ " processes " , ' p ' , POPT_ARG_NONE , NULL , ' p ' , " Show processes only " } ,
{ " verbose " , ' v ' , POPT_ARG_NONE , NULL , ' v ' , " Be verbose " } ,
{ " locks " , ' L ' , POPT_ARG_NONE , NULL , ' L ' , " Show locks only " } ,
{ " shares " , ' S ' , POPT_ARG_NONE , NULL , ' S ' , " Show shares only " } ,
2004-11-12 02:30:32 +03:00
{ " user " , ' u ' , POPT_ARG_STRING , & username , ' u ' , " Switch to user " } ,
2007-10-19 22:38:36 +04:00
{ " brief " , ' b ' , POPT_ARG_NONE , NULL , ' b ' , " Be brief " } ,
2006-07-11 22:01:26 +04:00
{ " profile " , ' P ' , POPT_ARG_NONE , NULL , ' P ' , " Do profiling " } ,
{ " profile-rates " , ' R ' , POPT_ARG_NONE , NULL , ' R ' , " Show call rates " } ,
2007-10-19 22:38:36 +04:00
{ " byterange " , ' B ' , POPT_ARG_NONE , NULL , ' B ' , " Include byte range locks " } ,
{ " numeric " , ' n ' , POPT_ARG_NONE , NULL , ' n ' , " Numeric uid/gid " } ,
2003-04-14 07:30:20 +04:00
POPT_COMMON_SAMBA
POPT_TABLEEND
2002-03-12 00:37:01 +03:00
} ;
2007-08-31 13:54:30 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
int ret = 0 ;
2002-03-12 00:37:01 +03:00
2006-05-11 02:33:10 +04:00
sec_init ( ) ;
2005-12-29 01:48:54 +03:00
load_case_tables ( ) ;
1999-12-21 07:54:30 +03:00
setup_logging ( argv [ 0 ] , True ) ;
2001-09-10 15:08:57 +04:00
dbf = x_stderr ;
1999-12-21 07:54:30 +03:00
if ( getuid ( ) ! = geteuid ( ) ) {
2001-09-08 06:59:23 +04:00
d_printf ( " smbstatus should not be run setuid \n " ) ;
2007-08-31 13:54:30 +04:00
ret = 1 ;
goto done ;
1998-07-24 05:08:31 +04:00
}
2002-03-12 00:37:01 +03:00
pc = poptGetContext ( NULL , argc , ( const char * * ) argv , long_options ,
POPT_CONTEXT_KEEP_FIRST ) ;
1999-12-21 07:54:30 +03:00
2003-04-16 18:31:10 +04:00
while ( ( c = poptGetNextOpt ( pc ) ) ! = - 1 ) {
1999-12-21 07:54:30 +03:00
switch ( c ) {
2007-10-19 22:38:36 +04:00
case ' p ' :
processes_only = true ;
break ;
case ' v ' :
verbose = true ;
break ;
case ' L ' :
locks_only = true ;
break ;
case ' S ' :
shares_only = true ;
break ;
case ' b ' :
brief = true ;
break ;
case ' u ' :
2004-12-17 11:51:23 +03:00
Ucrit_addUid ( nametouid ( poptGetOptArg ( pc ) ) ) ;
1999-12-21 07:54:30 +03:00
break ;
2006-07-11 22:01:26 +04:00
case ' P ' :
case ' R ' :
profile_only = c ;
2007-10-19 22:38:36 +04:00
break ;
case ' B ' :
show_brl = true ;
break ;
case ' n ' :
numeric_only = true ;
break ;
1999-12-13 16:27:58 +03:00
}
1999-12-21 07:54:30 +03:00
}
2001-06-13 09:36:28 +04:00
2004-11-12 02:30:32 +03:00
/* setup the flags based on the possible combincations */
show_processes = ! ( shares_only | | locks_only | | profile_only ) | | processes_only ;
show_locks = ! ( shares_only | | processes_only | | profile_only ) | | locks_only ;
show_shares = ! ( processes_only | | locks_only | | profile_only ) | | shares_only ;
if ( username )
2004-12-17 11:51:23 +03:00
Ucrit_addUid ( nametouid ( username ) ) ;
2004-11-12 02:30:32 +03:00
1999-12-21 07:54:30 +03:00
if ( verbose ) {
2001-11-19 05:49:53 +03:00
d_printf ( " using configfile = %s \n " , dyn_CONFIGFILE ) ;
1999-12-21 07:54:30 +03:00
}
2002-10-28 22:50:06 +03:00
2006-01-29 01:53:04 +03:00
if ( ! lp_load ( dyn_CONFIGFILE , False , False , False , True ) ) {
2002-10-28 22:50:06 +03:00
fprintf ( stderr , " Can't load %s - run testparm to debug it \n " , dyn_CONFIGFILE ) ;
2007-08-31 13:54:30 +04:00
ret = - 1 ;
goto done ;
2002-10-28 22:50:06 +03:00
}
2006-07-11 22:01:26 +04:00
2007-06-10 21:02:09 +04:00
/*
* This implicitly initializes the global ctdbd connection , usable by
* the db_open ( ) calls further down .
*/
messaging_init ( NULL , procid_self ( ) , event_context_init ( NULL ) ) ;
2006-07-11 22:01:26 +04:00
switch ( profile_only ) {
case ' P ' :
/* Dump profile data */
return status_profile_dump ( verbose ) ;
case ' R ' :
/* Continuously display rate-converted data */
return status_profile_rates ( verbose ) ;
default :
break ;
1999-12-21 07:54:30 +03:00
}
2006-07-11 22:01:26 +04:00
2004-11-12 02:30:32 +03:00
if ( show_processes ) {
2007-05-29 22:41:16 +04:00
struct db_context * db ;
db = db_open ( NULL , lock_path ( " sessionid.tdb " ) , 0 ,
TDB_DEFAULT , O_RDWR , 0644 ) ;
if ( ! db ) {
2004-11-12 02:30:32 +03:00
d_printf ( " sessionid.tdb not initialised \n " ) ;
} else {
d_printf ( " \n Samba version %s \n " , SAMBA_VERSION_STRING ) ;
d_printf ( " PID Username Group Machine \n " ) ;
d_printf ( " ------------------------------------------------------------------- \n " ) ;
2007-05-29 22:41:16 +04:00
db - > traverse_read ( db , traverse_sessionid , NULL ) ;
2007-08-02 13:22:47 +04:00
TALLOC_FREE ( db ) ;
2004-11-12 02:30:32 +03:00
}
2007-08-31 13:54:30 +04:00
if ( processes_only ) {
goto done ;
}
2001-09-11 02:31:59 +04:00
}
2001-08-22 23:11:55 +04:00
2004-11-12 02:30:32 +03:00
if ( show_shares ) {
2007-05-08 17:44:36 +04:00
if ( verbose ) {
d_printf ( " Opened %s \n " , lock_path ( " connections.tdb " ) ) ;
}
2004-11-12 02:30:32 +03:00
2007-08-31 13:54:30 +04:00
if ( brief ) {
goto done ;
}
2004-11-12 02:30:32 +03:00
2007-05-08 17:44:36 +04:00
d_printf ( " \n Service pid machine Connected at \n " ) ;
d_printf ( " ------------------------------------------------------- \n " ) ;
2004-11-12 02:30:32 +03:00
2007-05-08 17:44:36 +04:00
connections_forall ( traverse_fn1 , NULL ) ;
2004-11-12 02:30:32 +03:00
2007-05-08 17:44:36 +04:00
d_printf ( " \n " ) ;
1999-12-21 07:54:30 +03:00
2007-08-31 13:54:30 +04:00
if ( shares_only ) {
goto done ;
}
2001-09-11 02:31:59 +04:00
}
1999-12-21 07:54:30 +03:00
2004-11-12 02:30:32 +03:00
if ( show_locks ) {
2007-08-31 13:54:30 +04:00
int result ;
2007-10-21 19:05:34 +04:00
struct db_context * db ;
db = db_open ( NULL , lock_path ( " locking.tdb " ) , 0 ,
TDB_DEFAULT , O_RDONLY , 0 ) ;
if ( ! db ) {
d_printf ( " %s not initialised \n " ,
lock_path ( " locking.tdb " ) ) ;
d_printf ( " This is normal if an SMB client has never "
" connected to your server. \n " ) ;
exit ( 0 ) ;
} else {
TALLOC_FREE ( db ) ;
}
1999-12-22 04:36:27 +03:00
1999-12-21 07:54:30 +03:00
if ( ! locking_init ( 1 ) ) {
2001-09-08 06:59:23 +04:00
d_printf ( " Can't initialise locking module - exiting \n " ) ;
2007-08-31 13:54:30 +04:00
ret = 1 ;
goto done ;
1999-12-21 07:54:30 +03:00
}
2007-08-31 13:54:30 +04:00
result = share_mode_forall ( print_share_mode , NULL ) ;
1999-12-22 04:36:27 +03:00
2007-08-31 13:54:30 +04:00
if ( result = = 0 ) {
2001-09-08 06:59:23 +04:00
d_printf ( " No locked files \n " ) ;
2007-08-31 13:54:30 +04:00
} else if ( result = = - 1 ) {
2001-09-08 06:59:23 +04:00
d_printf ( " locked file list truncated \n " ) ;
1999-12-22 04:36:27 +03:00
}
1999-12-21 07:54:30 +03:00
2001-09-08 06:59:23 +04:00
d_printf ( " \n " ) ;
2000-01-16 14:14:44 +03:00
if ( show_brl ) {
2007-05-29 17:26:44 +04:00
brl_forall ( print_brl , NULL ) ;
2000-01-16 14:14:44 +03:00
}
1999-12-21 07:54:30 +03:00
locking_end ( ) ;
}
1997-05-20 04:32:51 +04:00
2007-08-31 13:54:30 +04:00
done :
TALLOC_FREE ( frame ) ;
return ret ;
1996-05-04 11:50:46 +04:00
}