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