Print this page
    
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/ptools/pfiles/pfiles.c
          +++ new/usr/src/cmd/ptools/pfiles/pfiles.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
  25   25   */
  26   26  /*
  27   27   * Copyright (c) 2014 Joyent, Inc.  All Rights reserved.
  28   28   */
  29   29  
  30   30  #include <stdio.h>
  31   31  #include <stdlib.h>
  32   32  #include <unistd.h>
  33   33  #include <fcntl.h>
  34   34  #include <ctype.h>
  35   35  #include <string.h>
  36   36  #include <signal.h>
  37   37  #include <dirent.h>
  38   38  #include <limits.h>
  39   39  #include <door.h>
  40   40  #include <sys/types.h>
  41   41  #include <sys/socket.h>
  42   42  #include <sys/stat.h>
  43   43  #include <sys/mkdev.h>
  44   44  #include <sys/stropts.h>
  45   45  #include <sys/timod.h>
  46   46  #include <sys/un.h>
  47   47  #include <libproc.h>
  48   48  #include <netinet/in.h>
  49   49  #include <netinet/udp.h>
  50   50  #include <arpa/inet.h>
  51   51  #include <ucred.h>
  52   52  #include <zone.h>
  53   53  
  54   54  #define copyflock(dst, src) \
  55   55          (dst).l_type = (src).l_type;            \
  56   56          (dst).l_whence = (src).l_whence;        \
  57   57          (dst).l_start = (src).l_start;          \
  58   58          (dst).l_len = (src).l_len;              \
  59   59          (dst).l_sysid = (src).l_sysid;          \
  60   60          (dst).l_pid = (src).l_pid;
  61   61  
  62   62  static char *command;
  63   63  static volatile int interrupt;
  64   64  static int Fflag;
  65   65  static boolean_t nflag = B_FALSE;
  66   66  
  67   67  static  void    intr(int);
  68   68  static  void    dofcntl(struct ps_prochandle *, prfdinfo_t *, int, int);
  69   69  static  void    dosocket(struct ps_prochandle *, int);
  70   70  static  void    dofifo(struct ps_prochandle *, int);
  71   71  static  void    dotli(struct ps_prochandle *, int);
  72   72  static  void    show_files(struct ps_prochandle *);
  73   73  static  void    show_fileflags(int);
  74   74  static  void    show_door(struct ps_prochandle *, int);
  75   75  static  int     getflock(struct ps_prochandle *, int, struct flock *);
  76   76  
  77   77  int
  78   78  main(int argc, char **argv)
  79   79  {
  80   80          int retc = 0;
  81   81          int opt;
  82   82          int errflg = 0;
  83   83          struct ps_prochandle *Pr;
  84   84  
  85   85          if ((command = strrchr(argv[0], '/')) != NULL)
  86   86                  command++;
  87   87          else
  88   88                  command = argv[0];
  89   89  
  90   90          /* options */
  91   91          while ((opt = getopt(argc, argv, "Fn")) != EOF) {
  92   92                  switch (opt) {
  93   93                  case 'F':               /* force grabbing (no O_EXCL) */
  94   94                          Fflag = PGRAB_FORCE;
  95   95                          break;
  96   96                  case 'n':
  97   97                          nflag = B_TRUE;
  98   98                          break;
  99   99                  default:
 100  100                          errflg = 1;
 101  101                          break;
 102  102                  }
 103  103          }
 104  104  
 105  105          argc -= optind;
 106  106          argv += optind;
 107  107  
 108  108          if (errflg || argc <= 0) {
 109  109                  (void) fprintf(stderr, "usage:\t%s [-F] { pid | core } ...\n",
 110  110                      command);
 111  111                  (void) fprintf(stderr,
 112  112                      "  (report open files of each process)\n");
 113  113                  (void) fprintf(stderr,
 114  114                      "  -F: force grabbing of the target process\n");
 115  115                  exit(2);
 116  116          }
 117  117  
 118  118          /* catch signals from terminal */
 119  119          if (sigset(SIGHUP, SIG_IGN) == SIG_DFL)
 120  120                  (void) sigset(SIGHUP, intr);
 121  121          if (sigset(SIGINT, SIG_IGN) == SIG_DFL)
 122  122                  (void) sigset(SIGINT, intr);
 123  123          if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL)
 124  124                  (void) sigset(SIGQUIT, intr);
 125  125          (void) sigset(SIGPIPE, intr);
 126  126          (void) sigset(SIGTERM, intr);
 127  127  
 128  128          (void) proc_initstdio();
 129  129  
 130  130  
 131  131          while (--argc >= 0 && !interrupt) {
 132  132                  char *arg;
 133  133                  psinfo_t psinfo;
 134  134                  pid_t pid;
 135  135                  int gret;
 136  136  
 137  137                  (void) proc_flushstdio();
 138  138  
 139  139                  arg = *argv++;
 140  140  
 141  141                  /* get the specified pid and the psinfo struct */
 142  142                  if ((pid = proc_arg_psinfo(arg, PR_ARG_PIDS,
 143  143                      &psinfo, &gret)) == -1) {
 144  144  
 145  145                          if ((Pr = proc_arg_xgrab(arg, NULL, PR_ARG_CORES,
 146  146                              Fflag, &gret, NULL)) == NULL) {
 147  147                                  (void) fprintf(stderr,
 148  148                                      "%s: cannot examine %s: %s\n",
 149  149                                      command, arg, Pgrab_error(gret));
 150  150                                  retc++;
 151  151                                  continue;
 152  152                          }
 153  153                          if (proc_arg_psinfo(arg, PR_ARG_ANY, &psinfo,
 154  154                              &gret) < 0) {
 155  155                                  (void) fprintf(stderr,
 156  156                                      "%s: cannot examine %s: %s\n",
 157  157                                      command, arg, Pgrab_error(gret));
 158  158                                  retc++;
 159  159                                  Prelease(Pr, 0);
 160  160                                  continue;
 161  161                          }
 162  162                          (void) printf("core '%s' of %d:\t%.70s\n",
 163  163                              arg, (int)psinfo.pr_pid, psinfo.pr_psargs);
 164  164  
 165  165                          show_files(Pr);
 166  166                          Prelease(Pr, 0);
 167  167  
 168  168                  } else if ((Pr = Pgrab(pid, Fflag, &gret)) != NULL) {
 169  169                          if (Pcreate_agent(Pr) == 0) {
 170  170                                  proc_unctrl_psinfo(&psinfo);
 171  171                                  (void) printf("%d:\t%.70s\n",
 172  172                                      (int)pid, psinfo.pr_psargs);
 173  173                                  show_files(Pr);
 174  174                                  Pdestroy_agent(Pr);
 175  175                          } else {
 176  176                                  (void) fprintf(stderr,
 177  177                                      "%s: cannot control process %d\n",
 178  178                                      command, (int)pid);
 179  179                                  retc++;
 180  180                          }
 181  181                          Prelease(Pr, 0);
 182  182                          Pr = NULL;
 183  183                  } else {
 184  184                          switch (gret) {
 185  185                          case G_SYS:
 186  186                                  proc_unctrl_psinfo(&psinfo);
 187  187                                  (void) printf("%d:\t%.70s\n", (int)pid,
 188  188                                      psinfo.pr_psargs);
 189  189                                  (void) printf("  [system process]\n");
 190  190                                  break;
 191  191                          default:
 192  192                                  (void) fprintf(stderr, "%s: %s: %d\n",
 193  193                                      command, Pgrab_error(gret), (int)pid);
 194  194                                  retc++;
 195  195                                  break;
 196  196                          }
 197  197                  }
 198  198          }
 199  199  
 200  200          (void) proc_finistdio();
 201  201  
 202  202          if (interrupt && retc == 0)
 203  203                  retc++;
 204  204          return (retc);
 205  205  }
 206  206  
 207  207  /* ARGSUSED */
 208  208  static void
 209  209  intr(int sig)
 210  210  {
 211  211          interrupt = 1;
 212  212  }
 213  213  
 214  214  /* ------ begin specific code ------ */
 215  215  
 216  216  static int
 217  217  show_file(void *data, prfdinfo_t *info)
 218  218  {
 219  219          struct ps_prochandle *Pr = data;
 220  220          char unknown[12];
 221  221          char *s;
 222  222          mode_t mode;
 223  223  
 224  224          if (interrupt)
 225  225                  return (1);
 226  226  
 227  227          mode = info->pr_mode;
 228  228  
 229  229          switch (mode & S_IFMT) {
 230  230          case S_IFCHR: s = "S_IFCHR"; break;
 231  231          case S_IFBLK: s = "S_IFBLK"; break;
 232  232          case S_IFIFO: s = "S_IFIFO"; break;
 233  233          case S_IFDIR: s = "S_IFDIR"; break;
 234  234          case S_IFREG: s = "S_IFREG"; break;
 235  235          case S_IFLNK: s = "S_IFLNK"; break;
 236  236          case S_IFSOCK: s = "S_IFSOCK"; break;
 237  237          case S_IFDOOR: s = "S_IFDOOR"; break;
 238  238          case S_IFPORT: s = "S_IFPORT"; break;
 239  239          default:
 240  240                  s = unknown;
 241  241                  (void) sprintf(s, "0x%.4x ", (int)mode & S_IFMT);
 242  242                  break;
 243  243          }
 244  244  
 245  245          (void) printf("%4d: %s mode:0%.3o", info->pr_fd, s,
 246  246              (int)mode & ~S_IFMT);
 247  247  
 248  248          (void) printf(" dev:%u,%u",
 249  249              (unsigned)info->pr_major, (unsigned)info->pr_minor);
 250  250  
 251  251          if ((mode & S_IFMT) == S_IFPORT) {
 252  252                  (void) printf(" uid:%d gid:%d",
 253  253                      (int)info->pr_uid, (int)info->pr_gid);
 254  254                  (void) printf(" size:%lld\n", (longlong_t)info->pr_size);
 255  255                  return (0);
 256  256          }
 257  257  
 258  258          (void) printf(" ino:%llu uid:%d gid:%d",
 259  259              (u_longlong_t)info->pr_ino, (int)info->pr_uid, (int)info->pr_gid);
 260  260  
 261  261          if ((info->pr_rmajor == (major_t)NODEV) &&
 262  262              (info->pr_rminor == (minor_t)NODEV))
 263  263                  (void) printf(" size:%lld\n", (longlong_t)info->pr_size);
 264  264          else
 265  265                  (void) printf(" rdev:%u,%u\n",
 266  266                      (unsigned)info->pr_rmajor, (unsigned)info->pr_rminor);
 267  267  
 268  268          if (!nflag) {
 269  269                  dofcntl(Pr, info,
 270  270                      (mode & (S_IFMT|S_ENFMT|S_IXGRP)) == (S_IFREG|S_ENFMT),
 271  271                      (mode & S_IFMT) == S_IFDOOR);
 272  272  
 273  273                  if (Pstate(Pr) != PS_DEAD) {
 274  274                          char *dev = NULL;
 275  275  
 276  276                          if ((mode & S_IFMT) == S_IFSOCK)
 277  277                                  dosocket(Pr, info->pr_fd);
 278  278                          else if ((mode & S_IFMT) == S_IFIFO)
 279  279                                  dofifo(Pr, info->pr_fd);
 280  280  
 281  281                          if ((mode & S_IFMT) == S_IFCHR) {
 282  282                                  /*
 283  283                                   * There's no elegant way to determine
 284  284                                   * if a character device supports TLI,
 285  285                                   * so we lame out and just check a
 286  286                                   * hardcoded list of known TLI devices.
 287  287                                   */
 288  288                                  int i;
 289  289                                  const char *tlidevs[] = {
 290  290                                      "tcp", "tcp6", "udp", "udp6", NULL
 291  291                                  };
 292  292  
 293  293                                  /* global zone: /devices paths */
 294  294                                  dev = strrchr(info->pr_path, ':');
 295  295                                  /* also check the /dev path for zones */
 296  296                                  if (dev == NULL)
 297  297                                          dev = strrchr(info->pr_path, '/');
 298  298                                  if (dev != NULL) {
 299  299                                          dev++; /* skip past the `:' or '/' */
 300  300  
 301  301                                          for (i = 0; tlidevs[i] != NULL; i++) {
 302  302                                                  if (strcmp(dev, tlidevs[i]) ==
 303  303                                                      0) {
 304  304                                                          dotli(Pr, info->pr_fd);
 305  305                                                          break;
 306  306                                                  }
 307  307                                          }
 308  308                                  }
 309  309                          }
 310  310                  }
 311  311  
 312  312                  if (info->pr_path[0] != '\0')
 313  313                          (void) printf("      %s\n", info->pr_path);
 314  314  
 315  315                  if (info->pr_offset != -1) {
 316  316                          (void) printf("      offset:%lld\n",
 317  317                              (long long)info->pr_offset);
 318  318                  }
 319  319          }
 320  320          return (0);
 321  321  }
 322  322  
 323  323  static void
 324  324  show_files(struct ps_prochandle *Pr)
 325  325  {
 326  326          struct rlimit rlim;
 327  327  
 328  328          if (pr_getrlimit(Pr, RLIMIT_NOFILE, &rlim) == 0) {
 329  329                  ulong_t nfd = rlim.rlim_cur;
 330  330                  if (nfd == RLIM_INFINITY)
 331  331                          (void) printf(
 332  332                              "  Current rlimit: unlimited file descriptors\n");
 333  333                  else
 334  334                          (void) printf(
 335  335                              "  Current rlimit: %lu file descriptors\n", nfd);
 336  336          }
 337  337  
 338  338          (void) Pfdinfo_iter(Pr, show_file, Pr);
 339  339  }
 340  340  
 341  341  
 342  342  static int
 343  343  getflock(struct ps_prochandle *Pr, int fd, struct flock *flock_native)
 344  344  {
 345  345          int ret;
 346  346  #ifdef _LP64
 347  347          struct flock64_32 flock_target;
 348  348  
 349  349          if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
 350  350                  copyflock(flock_target, *flock_native);
 351  351                  ret = pr_fcntl(Pr, fd, F_GETLK, &flock_target);
 352  352                  copyflock(*flock_native, flock_target);
 353  353                  return (ret);
 354  354          }
 355  355  #endif /* _LP64 */
 356  356          ret = pr_fcntl(Pr, fd, F_GETLK, flock_native);
 357  357          return (ret);
 358  358  }
 359  359  
 360  360  /* examine open file with fcntl() */
 361  361  static void
 362  362  dofcntl(struct ps_prochandle *Pr, prfdinfo_t *info, int mandatory, int isdoor)
 363  363  {
 364  364          struct flock flock;
 365  365          int fileflags;
 366  366          int fdflags;
 367  367          int fd;
 368  368  
 369  369          fd = info->pr_fd;
 370  370  
 371  371          fileflags = info->pr_fileflags;
 372  372          fdflags = info->pr_fdflags;
 373  373  
 374  374          if (fileflags != -1 || fdflags != -1) {
 375  375                  (void) printf("      ");
 376  376                  if (fileflags != -1)
 377  377                          show_fileflags(fileflags);
 378  378                  if (fdflags != -1 && (fdflags & FD_CLOEXEC))
 379  379                          (void) printf(" FD_CLOEXEC");
 380  380                  if (isdoor && (Pstate(Pr) != PS_DEAD))
 381  381                          show_door(Pr, fd);
 382  382                  (void) fputc('\n', stdout);
 383  383          } else if (isdoor && (Pstate(Pr) != PS_DEAD)) {
 384  384                  (void) printf("    ");
 385  385                  show_door(Pr, fd);
 386  386                  (void) fputc('\n', stdout);
 387  387          }
 388  388  
 389  389          flock.l_type = F_WRLCK;
 390  390          flock.l_whence = 0;
 391  391          flock.l_start = 0;
 392  392          flock.l_len = 0;
 393  393          flock.l_sysid = 0;
 394  394          flock.l_pid = 0;
 395  395          if ((Pstate(Pr) != PS_DEAD) && (getflock(Pr, fd, &flock) != -1)) {
 396  396                  if (flock.l_type != F_UNLCK && (flock.l_sysid || flock.l_pid)) {
 397  397                          unsigned long sysid = flock.l_sysid;
 398  398  
 399  399                          (void) printf("      %s %s lock set by",
 400  400                              mandatory ? "mandatory" : "advisory",
 401  401                              flock.l_type == F_RDLCK? "read" : "write");
 402  402                          if (sysid)
 403  403                                  (void) printf(" system 0x%lX", sysid);
 404  404                          if (flock.l_pid)
 405  405                                  (void) printf(" process %d", (int)flock.l_pid);
 406  406                          (void) fputc('\n', stdout);
 407  407                  }
 408  408          }
 409  409  }
 410  410  
 411  411  #define ALL_O_FLAGS     O_ACCMODE | O_NDELAY | O_NONBLOCK | O_APPEND | \
 412  412                          O_SYNC | O_DSYNC | O_RSYNC | O_XATTR | \
 413  413                          O_CREAT | O_TRUNC | O_EXCL | O_NOCTTY | O_LARGEFILE
 414  414  
 415  415  static void
 416  416  show_fileflags(int flags)
 417  417  {
 418  418          char buffer[136];
 419  419          char *str = buffer;
 420  420  
 421  421          switch (flags & O_ACCMODE) {
 422  422          case O_RDONLY:
 423  423                  (void) strcpy(str, "O_RDONLY");
 424  424                  break;
 425  425          case O_WRONLY:
 426  426                  (void) strcpy(str, "O_WRONLY");
 427  427                  break;
 428  428          case O_RDWR:
 429  429                  (void) strcpy(str, "O_RDWR");
 430  430                  break;
 431  431          case O_SEARCH:
 432  432                  (void) strcpy(str, "O_SEARCH");
 433  433                  break;
 434  434          case O_EXEC:
 435  435                  (void) strcpy(str, "O_EXEC");
 436  436                  break;
 437  437          default:
 438  438                  (void) sprintf(str, "0x%x", flags & O_ACCMODE);
 439  439                  break;
 440  440          }
 441  441  
 442  442          if (flags & O_NDELAY)
 443  443                  (void) strcat(str, "|O_NDELAY");
 444  444          if (flags & O_NONBLOCK)
 445  445                  (void) strcat(str, "|O_NONBLOCK");
 446  446          if (flags & O_APPEND)
 447  447                  (void) strcat(str, "|O_APPEND");
 448  448          if (flags & O_SYNC)
 449  449                  (void) strcat(str, "|O_SYNC");
 450  450          if (flags & O_DSYNC)
 451  451                  (void) strcat(str, "|O_DSYNC");
 452  452          if (flags & O_RSYNC)
 453  453                  (void) strcat(str, "|O_RSYNC");
 454  454          if (flags & O_CREAT)
 455  455                  (void) strcat(str, "|O_CREAT");
 456  456          if (flags & O_TRUNC)
 457  457                  (void) strcat(str, "|O_TRUNC");
 458  458          if (flags & O_EXCL)
 459  459                  (void) strcat(str, "|O_EXCL");
 460  460          if (flags & O_NOCTTY)
 461  461                  (void) strcat(str, "|O_NOCTTY");
 462  462          if (flags & O_LARGEFILE)
 463  463                  (void) strcat(str, "|O_LARGEFILE");
 464  464          if (flags & O_XATTR)
 465  465                  (void) strcat(str, "|O_XATTR");
 466  466          if (flags & ~(ALL_O_FLAGS))
 467  467                  (void) sprintf(str + strlen(str), "|0x%x",
 468  468                      flags & ~(ALL_O_FLAGS));
 469  469  
 470  470          (void) printf("%s", str);
 471  471  }
 472  472  
 473  473  /* show process on the other end of a door, socket or fifo */
 474  474  static void
 475  475  show_peer_process(pid_t ppid)
 476  476  {
 477  477          psinfo_t psinfo;
 478  478  
 479  479          if (proc_get_psinfo(ppid, &psinfo) == 0)
 480  480                  (void) printf(" %s[%d]", psinfo.pr_fname, (int)ppid);
 481  481          else
 482  482                  (void) printf(" pid %d", (int)ppid);
 483  483  }
 484  484  
 485  485  /* show door info */
 486  486  static void
 487  487  show_door(struct ps_prochandle *Pr, int fd)
 488  488  {
 489  489          door_info_t door_info;
 490  490  
 491  491          if (pr_door_info(Pr, fd, &door_info) != 0)
 492  492                  return;
 493  493  
 494  494          (void) printf("  door to");
 495  495          show_peer_process(door_info.di_target);
 496  496  }
 497  497  
 498  498  /*
 499  499   * Print out the socket address pointed to by `sa'.  `len' is only
 500  500   * needed for AF_UNIX sockets.
 501  501   */
 502  502  static void
 503  503  show_sockaddr(const char *str, struct sockaddr *sa, socklen_t len)
 504  504  {
 505  505          struct sockaddr_in *so_in = (struct sockaddr_in *)(void *)sa;
 506  506          struct sockaddr_in6 *so_in6 = (struct sockaddr_in6 *)(void *)sa;
 507  507          struct sockaddr_un *so_un = (struct sockaddr_un *)sa;
 508  508          char  abuf[INET6_ADDRSTRLEN];
 509  509          const char *p;
 510  510  
 511  511          if (len == 0)
 512  512                  return;
 513  513  
 514  514          switch (sa->sa_family) {
 515  515          default:
 516  516                  return;
 517  517          case AF_INET:
 518  518                  (void) printf("\t%s: AF_INET %s  port: %u\n", str,
 519  519                      inet_ntop(AF_INET, &so_in->sin_addr, abuf, sizeof (abuf)),
 520  520                      ntohs(so_in->sin_port));
 521  521                  return;
 522  522          case AF_INET6:
 523  523                  (void) printf("\t%s: AF_INET6 %s  port: %u\n", str,
 524  524                      inet_ntop(AF_INET6, &so_in6->sin6_addr,
 525  525                      abuf, sizeof (abuf)),
 526  526                      ntohs(so_in->sin_port));
 527  527                  return;
 528  528          case AF_UNIX:
 529  529                  if (len >= sizeof (so_un->sun_family)) {
 530  530                          /* Null terminate */
 531  531                          len -= sizeof (so_un->sun_family);
 532  532                          so_un->sun_path[len] = '\0';
 533  533                          (void) printf("\t%s: AF_UNIX %s\n",
 534  534                              str, so_un->sun_path);
 535  535                  }
 536  536                  return;
 537  537          case AF_IMPLINK:        p = "AF_IMPLINK";       break;
 538  538          case AF_PUP:            p = "AF_PUP";           break;
 539  539          case AF_CHAOS:          p = "AF_CHAOS";         break;
 540  540          case AF_NS:             p = "AF_NS";            break;
 541  541          case AF_NBS:            p = "AF_NBS";           break;
 542  542          case AF_ECMA:           p = "AF_ECMA";          break;
 543  543          case AF_DATAKIT:        p = "AF_DATAKIT";       break;
 544  544          case AF_CCITT:          p = "AF_CCITT";         break;
 545  545          case AF_SNA:            p = "AF_SNA";           break;
 546  546          case AF_DECnet:         p = "AF_DECnet";        break;
 547  547          case AF_DLI:            p = "AF_DLI";           break;
 548  548          case AF_LAT:            p = "AF_LAT";           break;
 549  549          case AF_HYLINK:         p = "AF_HYLINK";        break;
 550  550          case AF_APPLETALK:      p = "AF_APPLETALK";     break;
 551  551          case AF_NIT:            p = "AF_NIT";           break;
 552  552          case AF_802:            p = "AF_802";           break;
 553  553          case AF_OSI:            p = "AF_OSI";           break;
 554  554          case AF_X25:            p = "AF_X25";           break;
 555  555          case AF_OSINET:         p = "AF_OSINET";        break;
 556  556          case AF_GOSIP:          p = "AF_GOSIP";         break;
 557  557          case AF_IPX:            p = "AF_IPX";           break;
 558  558          case AF_ROUTE:          p = "AF_ROUTE";         break;
 559  559          case AF_LINK:           p = "AF_LINK";          break;
 560  560          case AF_LX_NETLINK:     p = "AF_LX_NETLINK";    break;
 561  561          }
 562  562  
 563  563          (void) printf("\t%s: %s\n", str, p);
 564  564  }
 565  565  
 566  566  /*
 567  567   * Print out the process information for the other end of local sockets
 568  568   * and fifos
 569  569   */
 570  570  static void
 571  571  show_ucred(const char *str, ucred_t *cred)
 572  572  {
 573  573          pid_t upid = ucred_getpid(cred);
 574  574          zoneid_t uzid = ucred_getzoneid(cred);
 575  575          char zonename[ZONENAME_MAX];
 576  576  
 577  577          if ((upid != -1) || (uzid != -1)) {
 578  578                  (void) printf("\t%s:", str);
 579  579                  if (upid != -1) {
 580  580                          show_peer_process(upid);
 581  581                  }
 582  582                  if (uzid != -1) {
 583  583                          if (getzonenamebyid(uzid, zonename, sizeof (zonename))
 584  584                              != -1) {
 585  585                                  (void) printf(" zone: %s[%d]", zonename,
 586  586                                      (int)uzid);
 587  587                          } else {
 588  588                                  (void) printf(" zoneid: %d", (int)uzid);
 589  589                          }
 590  590                  }
 591  591                  (void) printf("\n");
 592  592          }
 593  593  }
 594  594  
 595  595  static void
 596  596  show_socktype(uint_t type)
 597  597  {
 598  598          static const char *types[] = {
 599  599                  NULL, "DGRAM", "STREAM", NULL, "RAW", "RDM", "SEQPACKET"
 600  600          };
 601  601  
 602  602          if (type < sizeof (types) / sizeof (*types) && types[type] != NULL)
 603  603                  (void) printf("\tSOCK_%s\n", types[type]);
 604  604          else
 605  605                  (void) printf("\tunknown socket type %u\n", type);
 606  606  }
 607  607  
 608  608  #define BUFSIZE 200
 609  609  static void
 610  610  show_sockopts(struct ps_prochandle *Pr, int fd)
 611  611  {
 612  612          int val, vlen;
 613  613          char buf[BUFSIZE];
 614  614          char buf1[32];
 615  615          char ipaddr[INET_ADDRSTRLEN];
 616  616          int i;
 617  617          in_addr_t nexthop_val;
 618  618          struct boolopt {
 619  619                  int             level;
 620  620                  int             opt;
 621  621                  const char      *name;
 622  622          };
 623  623          static struct boolopt boolopts[] = {
 624  624              { SOL_SOCKET, SO_DEBUG,             "SO_DEBUG,"     },
 625  625              { SOL_SOCKET, SO_REUSEADDR,         "SO_REUSEADDR," },
 626  626              { SOL_SOCKET, SO_KEEPALIVE,         "SO_KEEPALIVE," },
 627  627              { SOL_SOCKET, SO_DONTROUTE,         "SO_DONTROUTE," },
 628  628              { SOL_SOCKET, SO_BROADCAST,         "SO_BROADCAST," },
 629  629              { SOL_SOCKET, SO_OOBINLINE,         "SO_OOBINLINE," },
 630  630              { SOL_SOCKET, SO_DGRAM_ERRIND,      "SO_DGRAM_ERRIND,"},
 631  631              { SOL_SOCKET, SO_ALLZONES,          "SO_ALLZONES,"  },
 632  632              { SOL_SOCKET, SO_MAC_EXEMPT,        "SO_MAC_EXEMPT," },
 633  633              { SOL_SOCKET, SO_MAC_IMPLICIT,      "SO_MAC_IMPLICIT," },
 634  634              { SOL_SOCKET, SO_EXCLBIND,          "SO_EXCLBIND," },
 635  635              { SOL_SOCKET, SO_VRRP,              "SO_VRRP," },
 636  636              { IPPROTO_UDP, UDP_NAT_T_ENDPOINT,  "UDP_NAT_T_ENDPOINT," },
 637  637          };
 638  638          struct linger l;
 639  639  
 640  640          buf[0] = '!';           /* sentinel value, never printed */
 641  641          buf[1] = '\0';
 642  642  
 643  643          for (i = 0; i < sizeof (boolopts) / sizeof (boolopts[0]); i++) {
 644  644                  vlen = sizeof (val);
 645  645                  if (pr_getsockopt(Pr, fd, boolopts[i].level, boolopts[i].opt,
 646  646                      &val, &vlen) == 0 && val != 0)
 647  647                          (void) strlcat(buf, boolopts[i].name, sizeof (buf));
 648  648          }
 649  649  
 650  650          vlen = sizeof (l);
 651  651          if (pr_getsockopt(Pr, fd, SOL_SOCKET, SO_LINGER, &l, &vlen) == 0 &&
 652  652              l.l_onoff != 0) {
 653  653                  (void) snprintf(buf1, sizeof (buf1), "SO_LINGER(%d),",
 654  654                      l.l_linger);
 655  655                  (void) strlcat(buf, buf1, sizeof (buf));
 656  656          }
 657  657  
 658  658          vlen = sizeof (val);
 659  659          if (pr_getsockopt(Pr, fd, SOL_SOCKET, SO_SNDBUF, &val, &vlen) == 0) {
 660  660                  (void) snprintf(buf1, sizeof (buf1), "SO_SNDBUF(%d),", val);
 661  661                  (void) strlcat(buf, buf1, sizeof (buf));
 662  662          }
 663  663          vlen = sizeof (val);
 664  664          if (pr_getsockopt(Pr, fd, SOL_SOCKET, SO_RCVBUF, &val, &vlen) == 0) {
 665  665                  (void) snprintf(buf1, sizeof (buf1), "SO_RCVBUF(%d),", val);
 666  666                  (void) strlcat(buf, buf1, sizeof (buf));
 667  667          }
 668  668          vlen = sizeof (nexthop_val);
 669  669          if (pr_getsockopt(Pr, fd, IPPROTO_IP, IP_NEXTHOP, &nexthop_val,
 670  670              &vlen) == 0) {
 671  671                  if (vlen > 0) {
 672  672                          (void) inet_ntop(AF_INET, (void *) &nexthop_val,
 673  673                              ipaddr, sizeof (ipaddr));
 674  674                          (void) snprintf(buf1, sizeof (buf1), "IP_NEXTHOP(%s),",
 675  675                              ipaddr);
 676  676                          (void) strlcat(buf, buf1, sizeof (buf));
 677  677                  }
 678  678          }
 679  679  
 680  680          buf[strlen(buf) - 1] = '\0'; /* overwrites sentinel if no options */
 681  681          if (buf[1] != '\0')
 682  682                  (void) printf("\t%s\n", buf+1);
 683  683  }
 684  684  
 685  685  #define MAXNALLOC       32
 686  686  static void
 687  687  show_sockfilters(struct ps_prochandle *Pr, int fd)
 688  688  {
 689  689          struct fil_info *fi;
 690  690          int i = 0, nalloc = 2, len = nalloc * sizeof (*fi);
 691  691          boolean_t printhdr = B_TRUE;
 692  692  
 693  693          fi = calloc(nalloc, sizeof (*fi));
 694  694          if (fi == NULL) {
 695  695                  perror("calloc");
 696  696                  return;
 697  697          }
 698  698          /* CONSTCOND */
 699  699          while (1) {
 700  700                  if (pr_getsockopt(Pr, fd, SOL_FILTER, FIL_LIST, fi, &len) != 0)
 701  701                          break;
 702  702                  /* No filters */
 703  703                  if (len == 0)
 704  704                          break;
 705  705                  /* Make sure buffer was large enough */
 706  706                  if (fi->fi_pos >= nalloc) {
 707  707                          struct fil_info *new;
 708  708  
 709  709                          nalloc = fi->fi_pos + 1;
 710  710                          if (nalloc > MAXNALLOC)
 711  711                                  break;
 712  712                          len = nalloc * sizeof (*fi);
 713  713                          new = realloc(fi, nalloc * sizeof (*fi));
 714  714                          if (new == NULL) {
 715  715                                  perror("realloc");
 716  716                                  break;
 717  717                          }
 718  718                          fi = new;
 719  719                          continue;
 720  720                  }
 721  721  
 722  722                  for (i = 0; (i + 1) * sizeof (*fi) <= len; i++) {
 723  723                          if (fi[i].fi_flags & FILF_BYPASS)
 724  724                                  continue;
 725  725                          if (printhdr) {
 726  726                                  (void) printf("\tfilters: ");
 727  727                                  printhdr = B_FALSE;
 728  728                          }
 729  729                          (void) printf("%s", fi[i].fi_name);
 730  730                          if (fi[i].fi_flags != 0) {
 731  731                                  (void) printf("(");
 732  732                                  if (fi[i].fi_flags & FILF_AUTO)
 733  733                                          (void) printf("auto,");
 734  734                                  if (fi[i].fi_flags & FILF_PROG)
 735  735                                          (void) printf("prog,");
 736  736                                  (void) printf("\b)");
 737  737                          }
 738  738                          if (fi[i].fi_pos == 0) /* last one */
 739  739                                  break;
 740  740                          (void) printf(",");
 741  741                  }
 742  742                  if (!printhdr)
 743  743                          (void) printf("\n");
 744  744                  break;
 745  745          }
 746  746          free(fi);
 747  747  }
 748  748  
 749  749  /* print peer credentials for sockets and named pipes */
 750  750  static void
 751  751  dopeerucred(struct ps_prochandle *Pr, int fd)
 752  752  {
 753  753          ucred_t *peercred = NULL;       /* allocated by getpeerucred */
 754  754  
 755  755          if (pr_getpeerucred(Pr, fd, &peercred) == 0) {
 756  756                  show_ucred("peer", peercred);
 757  757                  ucred_free(peercred);
 758  758          }
 759  759  }
 760  760  
 761  761  /* the file is a socket */
 762  762  static void
 763  763  dosocket(struct ps_prochandle *Pr, int fd)
 764  764  {
 765  765          /* A buffer large enough for PATH_MAX size AF_UNIX address */
 766  766          long buf[(sizeof (short) + PATH_MAX + sizeof (long) - 1)
 767  767              / sizeof (long)];
 768  768          struct sockaddr *sa = (struct sockaddr *)buf;
 769  769          socklen_t len;
 770  770          int type, tlen;
 771  771  
 772  772          tlen = sizeof (type);
 773  773          if (pr_getsockopt(Pr, fd, SOL_SOCKET, SO_TYPE, &type, &tlen) == 0)
 774  774                  show_socktype((uint_t)type);
 775  775  
 776  776          show_sockopts(Pr, fd);
 777  777          show_sockfilters(Pr, fd);
 778  778  
 779  779          len = sizeof (buf);
 780  780          if (pr_getsockname(Pr, fd, sa, &len) == 0)
 781  781                  show_sockaddr("sockname", sa, len);
 782  782  
 783  783          len = sizeof (buf);
 784  784          if (pr_getpeername(Pr, fd, sa, &len) == 0)
 785  785                  show_sockaddr("peername", sa, len);
 786  786  
 787  787          dopeerucred(Pr, fd);
 788  788  }
 789  789  
 790  790  /* the file is a fifo (aka "named pipe") */
 791  791  static void
 792  792  dofifo(struct ps_prochandle *Pr, int fd)
 793  793  {
 794  794          dopeerucred(Pr, fd);
 795  795  }
 796  796  
 797  797  /* the file is a TLI endpoint */
 798  798  static void
 799  799  dotli(struct ps_prochandle *Pr, int fd)
 800  800  {
 801  801          struct strcmd strcmd;
 802  802  
 803  803          strcmd.sc_len = STRCMDBUFSIZE;
 804  804          strcmd.sc_timeout = 5;
 805  805  
 806  806          strcmd.sc_cmd = TI_GETMYNAME;
 807  807          if (pr_ioctl(Pr, fd, _I_CMD, &strcmd, sizeof (strcmd)) == 0)
 808  808                  show_sockaddr("sockname", (void *)&strcmd.sc_buf,
 809  809                      (size_t)strcmd.sc_len);
 810  810  
 811  811          strcmd.sc_cmd = TI_GETPEERNAME;
 812  812          if (pr_ioctl(Pr, fd, _I_CMD, &strcmd, sizeof (strcmd)) == 0)
 813  813                  show_sockaddr("peername", (void *)&strcmd.sc_buf,
 814  814                      (size_t)strcmd.sc_len);
 815  815  }
  
    | 
      ↓ open down ↓ | 
    815 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX