root/source3/utils/status.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Ucrit_addUid
  2. Ucrit_checkUid
  3. Ucrit_checkPid
  4. Ucrit_addPid
  5. print_share_mode
  6. print_brl
  7. traverse_fn1
  8. traverse_sessionid
  9. main

   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 3 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, see <http://www.gnu.org/licenses/>.
  18 
  19    Revision History:
  20 
  21    12 aug 96: Erik.Devriendt@te6.siemens.be
  22    added support for shared memory implementation of share mode locking
  23 
  24    21-Jul-1998: rsharpe@ns.aus.com (Richard Sharpe)
  25    Added -L (locks only) -S (shares only) flags and code
  26 
  27 */
  28 
  29 /*
  30  * This program reports current SMB connections
  31  */
  32 
  33 #include "includes.h"
  34 
  35 #define SMB_MAXPIDS             2048
  36 static uid_t            Ucrit_uid = 0;               /* added by OH */
  37 static struct server_id Ucrit_pid[SMB_MAXPIDS];  /* Ugly !!! */   /* added by OH */
  38 static int              Ucrit_MaxPid=0;                    /* added by OH */
  39 static unsigned int     Ucrit_IsActive = 0;                /* added by OH */
  40 
  41 static bool verbose, brief;
  42 static bool shares_only;            /* Added by RJS */
  43 static bool locks_only;            /* Added by RJS */
  44 static bool processes_only;
  45 static bool show_brl;
  46 static bool numeric_only;
  47 
  48 const char *username = NULL;
  49 
  50 extern bool status_profile_dump(bool be_verbose);
  51 extern bool status_profile_rates(bool be_verbose);
  52 
  53 /* added by OH */
  54 static void Ucrit_addUid(uid_t uid)
     /* [<][>][^][v][top][bottom][index][help] */
  55 {
  56         Ucrit_uid = uid;
  57         Ucrit_IsActive = 1;
  58 }
  59 
  60 static unsigned int Ucrit_checkUid(uid_t uid)
     /* [<][>][^][v][top][bottom][index][help] */
  61 {
  62         if ( !Ucrit_IsActive ) 
  63                 return 1;
  64         
  65         if ( uid == Ucrit_uid ) 
  66                 return 1;
  67         
  68         return 0;
  69 }
  70 
  71 static unsigned int Ucrit_checkPid(struct server_id pid)
     /* [<][>][^][v][top][bottom][index][help] */
  72 {
  73         int i;
  74         
  75         if ( !Ucrit_IsActive ) 
  76                 return 1;
  77         
  78         for (i=0;i<Ucrit_MaxPid;i++) {
  79                 if (cluster_id_equal(&pid, &Ucrit_pid[i])) 
  80                         return 1;
  81         }
  82         
  83         return 0;
  84 }
  85 
  86 static bool Ucrit_addPid( struct server_id pid )
     /* [<][>][^][v][top][bottom][index][help] */
  87 {
  88         if ( !Ucrit_IsActive )
  89                 return True;
  90 
  91         if ( Ucrit_MaxPid >= SMB_MAXPIDS ) {
  92                 d_printf("ERROR: More than %d pids for user %s!\n",
  93                          SMB_MAXPIDS, uidtoname(Ucrit_uid));
  94 
  95                 return False;
  96         }
  97 
  98         Ucrit_pid[Ucrit_MaxPid++] = pid;
  99         
 100         return True;
 101 }
 102 
 103 static void print_share_mode(const struct share_mode_entry *e,
     /* [<][>][^][v][top][bottom][index][help] */
 104                              const char *sharepath,
 105                              const char *fname,
 106                              void *dummy)
 107 {
 108         static int count;
 109 
 110         if (!is_valid_share_mode_entry(e)) {
 111                 return;
 112         }
 113 
 114         if (!process_exists(e->pid)) {
 115                 return;
 116         }
 117 
 118         if (count==0) {
 119                 d_printf("Locked files:\n");
 120                 d_printf("Pid          Uid        DenyMode   Access      R/W        Oplock           SharePath   Name   Time\n");
 121                 d_printf("--------------------------------------------------------------------------------------------------\n");
 122         }
 123         count++;
 124 
 125         if (Ucrit_checkPid(e->pid)) {
 126                 d_printf("%-11s  ",procid_str_static(&e->pid));
 127                 d_printf("%-9u  ", (unsigned int)e->uid);
 128                 switch (map_share_mode_to_deny_mode(e->share_access,
 129                                                     e->private_options)) {
 130                         case DENY_NONE: d_printf("DENY_NONE  "); break;
 131                         case DENY_ALL:  d_printf("DENY_ALL   "); break;
 132                         case DENY_DOS:  d_printf("DENY_DOS   "); break;
 133                         case DENY_READ: d_printf("DENY_READ  "); break;
 134                         case DENY_WRITE:printf("DENY_WRITE "); break;
 135                         case DENY_FCB:  d_printf("DENY_FCB "); break;
 136                         default: {
 137                                 d_printf("unknown-please report ! "
 138                                          "e->share_access = 0x%x, "
 139                                          "e->private_options = 0x%x\n",
 140                                          (unsigned int)e->share_access,
 141                                          (unsigned int)e->private_options );
 142                                 break;
 143                         }
 144                 }
 145                 d_printf("0x%-8x  ",(unsigned int)e->access_mask);
 146                 if ((e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))==
 147                                 (FILE_READ_DATA|FILE_WRITE_DATA)) {
 148                         d_printf("RDWR       ");
 149                 } else if (e->access_mask & FILE_WRITE_DATA) {
 150                         d_printf("WRONLY     ");
 151                 } else {
 152                         d_printf("RDONLY     ");
 153                 }
 154 
 155                 if((e->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == 
 156                                         (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) {
 157                         d_printf("EXCLUSIVE+BATCH ");
 158                 } else if (e->op_type & EXCLUSIVE_OPLOCK) {
 159                         d_printf("EXCLUSIVE       ");
 160                 } else if (e->op_type & BATCH_OPLOCK) {
 161                         d_printf("BATCH           ");
 162                 } else if (e->op_type & LEVEL_II_OPLOCK) {
 163                         d_printf("LEVEL_II        ");
 164                 } else {
 165                         d_printf("NONE            ");
 166                 }
 167 
 168                 d_printf(" %s   %s   %s",sharepath, fname, time_to_asc((time_t)e->time.tv_sec));
 169         }
 170 }
 171 
 172 static void print_brl(struct file_id id,
     /* [<][>][^][v][top][bottom][index][help] */
 173                         struct server_id pid, 
 174                         enum brl_type lock_type,
 175                         enum brl_flavour lock_flav,
 176                         br_off start,
 177                         br_off size,
 178                         void *private_data)
 179 {
 180         static int count;
 181         int i;
 182         static const struct {
 183                 enum brl_type lock_type;
 184                 const char *desc;
 185         } lock_types[] = {
 186                 { READ_LOCK, "R" },
 187                 { WRITE_LOCK, "W" },
 188                 { PENDING_READ_LOCK, "PR" },
 189                 { PENDING_WRITE_LOCK, "PW" },
 190                 { UNLOCK_LOCK, "U" }
 191         };
 192         const char *desc="X";
 193         const char *sharepath = "";
 194         const char *fname = "";
 195         struct share_mode_lock *share_mode;
 196 
 197         if (count==0) {
 198                 d_printf("Byte range locks:\n");
 199                 d_printf("Pid        dev:inode       R/W  start     size      SharePath               Name\n");
 200                 d_printf("--------------------------------------------------------------------------------\n");
 201         }
 202         count++;
 203 
 204         share_mode = fetch_share_mode_unlocked(NULL, id, "__unspecified__", "__unspecified__");
 205         if (share_mode) {
 206                 sharepath = share_mode->servicepath;
 207                 fname = share_mode->filename;
 208         }
 209 
 210         for (i=0;i<ARRAY_SIZE(lock_types);i++) {
 211                 if (lock_type == lock_types[i].lock_type) {
 212                         desc = lock_types[i].desc;
 213                 }
 214         }
 215 
 216         d_printf("%-10s %-15s %-4s %-9.0f %-9.0f %-24s %-24s\n", 
 217                  procid_str_static(&pid), file_id_string_tos(&id),
 218                  desc,
 219                  (double)start, (double)size,
 220                  sharepath, fname);
 221 
 222         TALLOC_FREE(share_mode);
 223 }
 224 
 225 static int traverse_fn1(struct db_record *rec,
     /* [<][>][^][v][top][bottom][index][help] */
 226                         const struct connections_key *key,
 227                         const struct connections_data *crec,
 228                         void *state)
 229 {
 230         if (crec->cnum == -1)
 231                 return 0;
 232 
 233         if (!process_exists(crec->pid) || !Ucrit_checkUid(crec->uid)) {
 234                 return 0;
 235         }
 236 
 237         d_printf("%-10s   %s   %-12s  %s",
 238                  crec->servicename,procid_str_static(&crec->pid),
 239                  crec->machine,
 240                  time_to_asc(crec->start));
 241 
 242         return 0;
 243 }
 244 
 245 static int traverse_sessionid(struct db_record *db, void *state)
     /* [<][>][^][v][top][bottom][index][help] */
 246 {
 247         struct sessionid sessionid;
 248         fstring uid_str, gid_str;
 249 
 250         if (db->value.dsize != sizeof(sessionid))
 251                 return 0;
 252 
 253         memcpy(&sessionid, db->value.dptr, sizeof(sessionid));
 254 
 255         if (!process_exists(sessionid.pid) || !Ucrit_checkUid(sessionid.uid)) {
 256                 return 0;
 257         }
 258 
 259         Ucrit_addPid( sessionid.pid );
 260 
 261         fstr_sprintf(uid_str, "%u", (unsigned int)sessionid.uid);
 262         fstr_sprintf(gid_str, "%u", (unsigned int)sessionid.gid);
 263 
 264         d_printf("%-7s   %-12s  %-12s  %-12s (%s)\n",
 265                  procid_str_static(&sessionid.pid),
 266                  numeric_only ? uid_str : uidtoname(sessionid.uid),
 267                  numeric_only ? gid_str : gidtoname(sessionid.gid), 
 268                  sessionid.remote_machine, sessionid.hostname);
 269         
 270         return 0;
 271 }
 272 
 273 
 274 
 275 
 276  int main(int argc, char *argv[])
     /* [<][>][^][v][top][bottom][index][help] */
 277 {
 278         int c;
 279         int profile_only = 0;
 280         bool show_processes, show_locks, show_shares;
 281         poptContext pc;
 282         struct poptOption long_options[] = {
 283                 POPT_AUTOHELP
 284                 {"processes",   'p', POPT_ARG_NONE,     NULL, 'p', "Show processes only" },
 285                 {"verbose",     'v', POPT_ARG_NONE,     NULL, 'v', "Be verbose" },
 286                 {"locks",       'L', POPT_ARG_NONE,     NULL, 'L', "Show locks only" },
 287                 {"shares",      'S', POPT_ARG_NONE,     NULL, 'S', "Show shares only" },
 288                 {"user",        'u', POPT_ARG_STRING,   &username, 'u', "Switch to user" },
 289                 {"brief",       'b', POPT_ARG_NONE,     NULL, 'b', "Be brief" },
 290                 {"profile",     'P', POPT_ARG_NONE, NULL, 'P', "Do profiling" },
 291                 {"profile-rates", 'R', POPT_ARG_NONE, NULL, 'R', "Show call rates" },
 292                 {"byterange",   'B', POPT_ARG_NONE,     NULL, 'B', "Include byte range locks"},
 293                 {"numeric",     'n', POPT_ARG_NONE,     NULL, 'n', "Numeric uid/gid"},
 294                 POPT_COMMON_SAMBA
 295                 POPT_TABLEEND
 296         };
 297         TALLOC_CTX *frame = talloc_stackframe();
 298         int ret = 0;
 299         struct messaging_context *msg_ctx;
 300 
 301         sec_init();
 302         load_case_tables();
 303 
 304         setup_logging(argv[0],True);
 305         
 306         dbf = x_stderr;
 307         
 308         if (getuid() != geteuid()) {
 309                 d_printf("smbstatus should not be run setuid\n");
 310                 ret = 1;
 311                 goto done;
 312         }
 313 
 314         pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
 315                             POPT_CONTEXT_KEEP_FIRST);
 316         
 317         while ((c = poptGetNextOpt(pc)) != -1) {
 318                 switch (c) {
 319                 case 'p':
 320                         processes_only = true;
 321                         break;
 322                 case 'v':
 323                         verbose = true;
 324                         break;
 325                 case 'L':
 326                         locks_only = true;
 327                         break;
 328                 case 'S':
 329                         shares_only = true;
 330                         break;
 331                 case 'b':
 332                         brief = true;
 333                         break;
 334                 case 'u':
 335                         Ucrit_addUid(nametouid(poptGetOptArg(pc)));
 336                         break;
 337                 case 'P':
 338                 case 'R':
 339                         profile_only = c;
 340                         break;
 341                 case 'B':
 342                         show_brl = true;
 343                         break;
 344                 case 'n':
 345                         numeric_only = true;
 346                         break;
 347                 }
 348         }
 349 
 350         /* setup the flags based on the possible combincations */
 351 
 352         show_processes = !(shares_only || locks_only || profile_only) || processes_only;
 353         show_locks     = !(shares_only || processes_only || profile_only) || locks_only;
 354         show_shares    = !(processes_only || locks_only || profile_only) || shares_only;
 355 
 356         if ( username )
 357                 Ucrit_addUid( nametouid(username) );
 358 
 359         if (verbose) {
 360                 d_printf("using configfile = %s\n", get_dyn_CONFIGFILE());
 361         }
 362 
 363         if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
 364                 fprintf(stderr, "Can't load %s - run testparm to debug it\n",
 365                         get_dyn_CONFIGFILE());
 366                 ret = -1;
 367                 goto done;
 368         }
 369 
 370 
 371         if (lp_clustering()) {
 372                 /*
 373                  * This implicitly initializes the global ctdbd
 374                  * connection, usable by the db_open() calls further
 375                  * down.
 376                  */
 377                 msg_ctx = messaging_init(NULL, procid_self(),
 378                                          event_context_init(NULL));
 379                 if (msg_ctx == NULL) {
 380                         fprintf(stderr, "messaging_init failed\n");
 381                         ret = -1;
 382                         goto done;
 383                 }
 384         }
 385 
 386         if (!lp_load(get_dyn_CONFIGFILE(),False,False,False,True)) {
 387                 fprintf(stderr, "Can't load %s - run testparm to debug it\n",
 388                         get_dyn_CONFIGFILE());
 389                 ret = -1;
 390                 goto done;
 391         }
 392 
 393         switch (profile_only) {
 394                 case 'P':
 395                         /* Dump profile data */
 396                         return status_profile_dump(verbose);
 397                 case 'R':
 398                         /* Continuously display rate-converted data */
 399                         return status_profile_rates(verbose);
 400                 default:
 401                         break;
 402         }
 403 
 404         if ( show_processes ) {
 405                 struct db_context *db;
 406                 db = db_open(NULL, lock_path("sessionid.tdb"), 0,
 407                              TDB_CLEAR_IF_FIRST, O_RDONLY, 0644);
 408                 if (!db) {
 409                         d_printf("sessionid.tdb not initialised\n");
 410                 } else {
 411                         d_printf("\nSamba version %s\n",samba_version_string());
 412                         d_printf("PID     Username      Group         Machine                        \n");
 413                         d_printf("-------------------------------------------------------------------\n");
 414                         if (lp_security() == SEC_SHARE) {
 415                                 d_printf(" <processes do not show up in "
 416                                     "anonymous mode>\n");
 417                         }
 418 
 419                         db->traverse_read(db, traverse_sessionid, NULL);
 420                         TALLOC_FREE(db);
 421                 }
 422 
 423                 if (processes_only) {
 424                         goto done;
 425                 }
 426         }
 427   
 428         if ( show_shares ) {
 429                 if (verbose) {
 430                         d_printf("Opened %s\n", lock_path("connections.tdb"));
 431                 }
 432 
 433                 if (brief) {
 434                         goto done;
 435                 }
 436                 
 437                 d_printf("\nService      pid     machine       Connected at\n");
 438                 d_printf("-------------------------------------------------------\n");
 439         
 440                 connections_forall(traverse_fn1, NULL);
 441 
 442                 d_printf("\n");
 443 
 444                 if ( shares_only ) {
 445                         goto done;
 446                 }
 447         }
 448 
 449         if ( show_locks ) {
 450                 int result;
 451                 struct db_context *db;
 452                 db = db_open(NULL, lock_path("locking.tdb"), 0,
 453                              TDB_CLEAR_IF_FIRST, O_RDONLY, 0);
 454 
 455                 if (!db) {
 456                         d_printf("%s not initialised\n",
 457                                  lock_path("locking.tdb"));
 458                         d_printf("This is normal if an SMB client has never "
 459                                  "connected to your server.\n");
 460                         exit(0);
 461                 } else {
 462                         TALLOC_FREE(db);
 463                 }
 464 
 465                 if (!locking_init_readonly()) {
 466                         d_printf("Can't initialise locking module - exiting\n");
 467                         ret = 1;
 468                         goto done;
 469                 }
 470                 
 471                 result = share_mode_forall(print_share_mode, NULL);
 472 
 473                 if (result == 0) {
 474                         d_printf("No locked files\n");
 475                 } else if (result == -1) {
 476                         d_printf("locked file list truncated\n");
 477                 }
 478                 
 479                 d_printf("\n");
 480 
 481                 if (show_brl) {
 482                         brl_forall(print_brl, NULL);
 483                 }
 484                 
 485                 locking_end();
 486         }
 487 
 488 done:
 489         TALLOC_FREE(frame);
 490         return ret;
 491 }

/* [<][>][^][v][top][bottom][index][help] */