1/* 2 Unix SMB/CIFS implementation. 3 status reporting 4 Copyright (C) Andrew Tridgell 1994-1998 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 20 Revision History: 21 22 12 aug 96: Erik.Devriendt@te6.siemens.be 23 added support for shared memory implementation of share mode locking 24 25 21-Jul-1998: rsharpe@ns.aus.com (Richard Sharpe) 26 Added -L (locks only) -S (shares only) flags and code 27 28*/ 29 30/* 31 * This program reports current SMB connections 32 */ 33 34#include "includes.h" 35 36#define SMB_MAXPIDS 2048 37static uid_t Ucrit_uid = 0; /* added by OH */ 38static pid_t Ucrit_pid[SMB_MAXPIDS]; /* Ugly !!! */ /* added by OH */ 39static int Ucrit_MaxPid=0; /* added by OH */ 40static unsigned int Ucrit_IsActive = 0; /* added by OH */ 41 42static int verbose, brief; 43static int shares_only = 0; /* Added by RJS */ 44static int locks_only = 0; /* Added by RJS */ 45static BOOL processes_only=False; 46static int show_brl; 47static BOOL numeric_only = False; 48 49const char *username = NULL; 50 51extern BOOL status_profile_dump(BOOL be_verbose); 52extern BOOL status_profile_rates(BOOL be_verbose); 53 54/* added by OH */ 55static void Ucrit_addUid(uid_t uid) 56{ 57 Ucrit_uid = uid; 58 Ucrit_IsActive = 1; 59} 60 61static unsigned int Ucrit_checkUid(uid_t uid) 62{ 63 if ( !Ucrit_IsActive ) 64 return 1; 65 66 if ( uid == Ucrit_uid ) 67 return 1; 68 69 return 0; 70} 71 72static unsigned int Ucrit_checkPid(pid_t pid) 73{ 74 int i; 75 76 if ( !Ucrit_IsActive ) 77 return 1; 78 79 for (i=0;i<Ucrit_MaxPid;i++) { 80 if( pid == Ucrit_pid[i] ) 81 return 1; 82 } 83 84 return 0; 85} 86 87static BOOL Ucrit_addPid( pid_t pid ) 88{ 89 if ( !Ucrit_IsActive ) 90 return True; 91 92 if ( Ucrit_MaxPid >= SMB_MAXPIDS ) { 93 d_printf("ERROR: More than %d pids for user %s!\n", 94 SMB_MAXPIDS, uidtoname(Ucrit_uid)); 95 96 return False; 97 } 98 99 Ucrit_pid[Ucrit_MaxPid++] = pid; 100 101 return True; 102} 103 104static void print_share_mode(const struct share_mode_entry *e, 105 const char *sharepath, 106 const char *fname, 107 void *dummy) 108{ 109 static int count; 110 111 if (!is_valid_share_mode_entry(e)) { 112 return; 113 } 114 115 if (count==0) { 116 d_printf("Locked files:\n"); 117 d_printf("Pid Uid DenyMode Access R/W Oplock SharePath Name Time\n"); 118 d_printf("--------------------------------------------------------------------------------------------------\n"); 119 } 120 count++; 121 122 if (Ucrit_checkPid(procid_to_pid(&e->pid))) { 123 d_printf("%-11s ",procid_str_static(&e->pid)); 124 d_printf("%-9u ", (unsigned int)e->uid); 125 switch (map_share_mode_to_deny_mode(e->share_access, 126 e->private_options)) { 127 case DENY_NONE: d_printf("DENY_NONE "); break; 128 case DENY_ALL: d_printf("DENY_ALL "); break; 129 case DENY_DOS: d_printf("DENY_DOS "); break; 130 case DENY_READ: d_printf("DENY_READ "); break; 131 case DENY_WRITE:printf("DENY_WRITE "); break; 132 case DENY_FCB: d_printf("DENY_FCB "); break; 133 default: { 134 d_printf("unknown-please report ! " 135 "e->share_access = 0x%x, " 136 "e->private_options = 0x%x\n", 137 (unsigned int)e->share_access, 138 (unsigned int)e->private_options ); 139 break; 140 } 141 } 142 d_printf("0x%-8x ",(unsigned int)e->access_mask); 143 if ((e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))== 144 (FILE_READ_DATA|FILE_WRITE_DATA)) { 145 d_printf("RDWR "); 146 } else if (e->access_mask & FILE_WRITE_DATA) { 147 d_printf("WRONLY "); 148 } else { 149 d_printf("RDONLY "); 150 } 151 152 if((e->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == 153 (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) { 154 d_printf("EXCLUSIVE+BATCH "); 155 } else if (e->op_type & EXCLUSIVE_OPLOCK) { 156 d_printf("EXCLUSIVE "); 157 } else if (e->op_type & BATCH_OPLOCK) { 158 d_printf("BATCH "); 159 } else if (e->op_type & LEVEL_II_OPLOCK) { 160 d_printf("LEVEL_II "); 161 } else { 162 d_printf("NONE "); 163 } 164 165 d_printf(" %s %s %s",sharepath, fname, time_to_asc((time_t)e->time.tv_sec)); 166 } 167} 168 169static void print_brl(SMB_DEV_T dev, 170 SMB_INO_T ino, 171 struct process_id pid, 172 enum brl_type lock_type, 173 enum brl_flavour lock_flav, 174 br_off start, 175 br_off size) 176{ 177 static int count; 178 if (count==0) { 179 d_printf("Byte range locks:\n"); 180 d_printf(" Pid dev:inode R/W start size\n"); 181 d_printf("------------------------------------------------\n"); 182 } 183 count++; 184 185 d_printf("%8s %05x:%05x %s %9.0f %9.0f\n", 186 procid_str_static(&pid), (int)dev, (int)ino, 187 lock_type==READ_LOCK?"R":"W", 188 (double)start, (double)size); 189} 190 191static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) 192{ 193 struct connections_data crec; 194 195 if (dbuf.dsize != sizeof(crec)) 196 return 0; 197 198 memcpy(&crec, dbuf.dptr, sizeof(crec)); 199 200 if (crec.cnum == -1) 201 return 0; 202 203 if (!process_exists(crec.pid) || !Ucrit_checkUid(crec.uid)) { 204 return 0; 205 } 206 207 d_printf("%-10s %s %-12s %s", 208 crec.servicename,procid_str_static(&crec.pid), 209 crec.machine, 210 time_to_asc(crec.start)); 211 212 return 0; 213} 214 215static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) 216{ 217 struct sessionid sessionid; 218 fstring uid_str, gid_str; 219 220 if (dbuf.dsize != sizeof(sessionid)) 221 return 0; 222 223 memcpy(&sessionid, dbuf.dptr, sizeof(sessionid)); 224 225 if (!process_exists_by_pid(sessionid.pid) || !Ucrit_checkUid(sessionid.uid)) { 226 return 0; 227 } 228 229 Ucrit_addPid( sessionid.pid ); 230 231 fstr_sprintf(uid_str, "%d", sessionid.uid); 232 fstr_sprintf(gid_str, "%d", sessionid.gid); 233 234 d_printf("%5d %-12s %-12s %-12s (%s)\n", 235 (int)sessionid.pid, 236 numeric_only ? uid_str : uidtoname(sessionid.uid), 237 numeric_only ? gid_str : gidtoname(sessionid.gid), 238 sessionid.remote_machine, sessionid.hostname); 239 240 return 0; 241} 242 243 244 245 246 int main(int argc, char *argv[]) 247{ 248 int c; 249 int profile_only = 0; 250 TDB_CONTEXT *tdb; 251 BOOL show_processes, show_locks, show_shares; 252 poptContext pc; 253 struct poptOption long_options[] = { 254 POPT_AUTOHELP 255 {"processes", 'p', POPT_ARG_NONE, &processes_only, 'p', "Show processes only" }, 256 {"verbose", 'v', POPT_ARG_NONE, &verbose, 'v', "Be verbose" }, 257 {"locks", 'L', POPT_ARG_NONE, &locks_only, 'L', "Show locks only" }, 258 {"shares", 'S', POPT_ARG_NONE, &shares_only, 'S', "Show shares only" }, 259 {"user", 'u', POPT_ARG_STRING, &username, 'u', "Switch to user" }, 260 {"brief", 'b', POPT_ARG_NONE, &brief, 'b', "Be brief" }, 261 {"profile", 'P', POPT_ARG_NONE, NULL, 'P', "Do profiling" }, 262 {"profile-rates", 'R', POPT_ARG_NONE, NULL, 'R', "Show call rates" }, 263 {"byterange", 'B', POPT_ARG_NONE, &show_brl, 'B', "Include byte range locks"}, 264 {"numeric", 'n', POPT_ARG_NONE, &numeric_only, 'n', "Numeric uid/gid"}, 265 POPT_COMMON_SAMBA 266 POPT_TABLEEND 267 }; 268 269 sec_init(); 270 load_case_tables(); 271 272 setup_logging(argv[0],True); 273 274 dbf = x_stderr; 275 276 if (getuid() != geteuid()) { 277 d_printf("smbstatus should not be run setuid\n"); 278 return(1); 279 } 280 281 pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 282 POPT_CONTEXT_KEEP_FIRST); 283 284 while ((c = poptGetNextOpt(pc)) != -1) { 285 switch (c) { 286 case 'u': 287 Ucrit_addUid(nametouid(poptGetOptArg(pc))); 288 break; 289 case 'P': 290 case 'R': 291 profile_only = c; 292 } 293 } 294 295 /* setup the flags based on the possible combincations */ 296 297 show_processes = !(shares_only || locks_only || profile_only) || processes_only; 298 show_locks = !(shares_only || processes_only || profile_only) || locks_only; 299 show_shares = !(processes_only || locks_only || profile_only) || shares_only; 300 301 if ( username ) 302 Ucrit_addUid( nametouid(username) ); 303 304 if (verbose) { 305 d_printf("using configfile = %s\n", dyn_CONFIGFILE); 306 } 307 308 if (!lp_load(dyn_CONFIGFILE,False,False,False,True)) { 309 fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); 310 return (-1); 311 } 312 313 switch (profile_only) { 314 case 'P': 315 /* Dump profile data */ 316 return status_profile_dump(verbose); 317 case 'R': 318 /* Continuously display rate-converted data */ 319 return status_profile_rates(verbose); 320 default: 321 break; 322 } 323 324 if ( show_processes ) { 325 tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0); 326 if (!tdb) { 327 d_printf("sessionid.tdb not initialised\n"); 328 } else { 329 d_printf("\nSamba version %s\n",SAMBA_VERSION_STRING); 330 d_printf("PID Username Group Machine \n"); 331 d_printf("-------------------------------------------------------------------\n"); 332 333 tdb_traverse(tdb, traverse_sessionid, NULL); 334 tdb_close(tdb); 335 } 336 337 if (processes_only) 338 exit(0); 339 } 340 341 if ( show_shares ) { 342 tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0); 343 if (!tdb) { 344 d_printf("%s not initialised\n", lock_path("connections.tdb")); 345 d_printf("This is normal if an SMB client has never connected to your server.\n"); 346 } else { 347 if (verbose) { 348 d_printf("Opened %s\n", lock_path("connections.tdb")); 349 } 350 351 if (brief) 352 exit(0); 353 354 d_printf("\nService pid machine Connected at\n"); 355 d_printf("-------------------------------------------------------\n"); 356 357 tdb_traverse(tdb, traverse_fn1, NULL); 358 tdb_close(tdb); 359 360 d_printf("\n"); 361 } 362 363 if ( shares_only ) 364 exit(0); 365 } 366 367 if ( show_locks ) { 368 int ret; 369 370 if (!locking_init(1)) { 371 d_printf("Can't initialise locking module - exiting\n"); 372 exit(1); 373 } 374 375 ret = share_mode_forall(print_share_mode, NULL); 376 377 if (ret == 0) { 378 d_printf("No locked files\n"); 379 } else if (ret == -1) { 380 d_printf("locked file list truncated\n"); 381 } 382 383 d_printf("\n"); 384 385 if (show_brl) { 386 brl_forall(print_brl); 387 } 388 389 locking_end(); 390 } 391 392 return (0); 393} 394