1/* $NetBSD$ */ 2 3/*- 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33#ifndef lint 34__COPYRIGHT("@(#) Copyright (c) 1988, 1993\ 35 The Regents of the University of California. All rights reserved."); 36#endif /* not lint */ 37 38#ifndef lint 39#if 0 40static char sccsid[] = "@(#)fstat.c 8.3 (Berkeley) 5/2/95"; 41#else 42__RCSID("$NetBSD$"); 43#endif 44#endif /* not lint */ 45 46#include <sys/types.h> 47#include <sys/param.h> 48#include <sys/time.h> 49#include <sys/proc.h> 50#include <sys/stat.h> 51#include <sys/vnode.h> 52#include <sys/socket.h> 53#include <sys/socketvar.h> 54#include <sys/domain.h> 55#include <sys/protosw.h> 56#include <sys/unpcb.h> 57#include <sys/sysctl.h> 58#include <sys/filedesc.h> 59#include <sys/pipe.h> 60#define _KERNEL 61#include <sys/mount.h> 62#undef _KERNEL 63#define _KERNEL 64#include <sys/file.h> 65#include <ufs/ufs/inode.h> 66#include <ufs/ufs/ufsmount.h> 67#undef _KERNEL 68#define NFS 69#include <nfs/nfsproto.h> 70#include <nfs/rpcv2.h> 71#include <nfs/nfs.h> 72#include <nfs/nfsnode.h> 73#undef NFS 74#include <msdosfs/denode.h> 75#include <msdosfs/bpb.h> 76#define _KERNEL 77#include <msdosfs/msdosfsmount.h> 78#undef _KERNEL 79#define _KERNEL 80#include <miscfs/genfs/layer.h> 81#undef _KERNEL 82 83#include <net/route.h> 84#include <netinet/in.h> 85#include <netinet/in_systm.h> 86#include <netinet/ip.h> 87#include <netinet/in_pcb.h> 88 89#ifdef INET6 90#include <netinet/ip6.h> 91#include <netinet6/ip6_var.h> 92#include <netinet6/in6_pcb.h> 93#endif 94 95#include <netatalk/at.h> 96#include <netatalk/ddp_var.h> 97 98#include <netdb.h> 99#include <arpa/inet.h> 100 101#include <ctype.h> 102#include <errno.h> 103#include <kvm.h> 104#include <limits.h> 105#include <nlist.h> 106#include <paths.h> 107#include <pwd.h> 108#include <stdio.h> 109#include <stdlib.h> 110#include <string.h> 111#include <unistd.h> 112#include <err.h> 113#include <util.h> 114 115#include "fstat.h" 116 117#define TEXT -1 118#define CDIR -2 119#define RDIR -3 120#define TRACE -4 121 122typedef struct devs { 123 struct devs *next; 124 long fsid; 125 ino_t ino; 126 const char *name; 127} DEVS; 128static DEVS *devs; 129 130static int fsflg, /* show files on same filesystem as file(s) argument */ 131 pflg, /* show files open by a particular pid */ 132 uflg; /* show files open by a particular (effective) user */ 133static int checkfile; /* true if restricting to particular files or filesystems */ 134static int nflg; /* (numerical) display f.s. and rdev as dev_t */ 135int vflg; /* display errors in locating kernel data objects etc... */ 136 137static fdfile_t **ofiles; /* buffer of pointers to file structures */ 138static int fstat_maxfiles; 139#define ALLOC_OFILES(d) \ 140 if ((d) > fstat_maxfiles) { \ 141 size_t len = (d) * sizeof(fdfile_t *); \ 142 free(ofiles); \ 143 ofiles = malloc(len); \ 144 if (ofiles == NULL) { \ 145 err(1, "malloc(%zu)", len); \ 146 } \ 147 fstat_maxfiles = (d); \ 148 } 149 150kvm_t *kd; 151 152static const char *const dtypes[] = { 153 DTYPE_NAMES 154}; 155 156static void dofiles(struct kinfo_proc2 *); 157static int ext2fs_filestat(struct vnode *, struct filestat *); 158static int getfname(const char *); 159static void getinetproto(int); 160static void getatproto(int); 161static char *getmnton(struct mount *); 162static const char *layer_filestat(struct vnode *, struct filestat *); 163static int msdosfs_filestat(struct vnode *, struct filestat *); 164static int nfs_filestat(struct vnode *, struct filestat *); 165static const char *inet_addrstr(char *, size_t, const struct in_addr *, 166 uint16_t); 167#ifdef INET6 168static const char *inet6_addrstr(char *, size_t, const struct in6_addr *, 169 uint16_t); 170#endif 171static const char *at_addrstr(char *, size_t, const struct sockaddr_at *); 172static void socktrans(struct socket *, int); 173static void misctrans(struct file *); 174static int ufs_filestat(struct vnode *, struct filestat *); 175static void usage(void) __dead; 176static const char *vfilestat(struct vnode *, struct filestat *); 177static void vtrans(struct vnode *, int, int); 178static void ftrans(fdfile_t *, int); 179static void ptrans(struct file *, struct pipe *, int); 180 181int 182main(int argc, char **argv) 183{ 184 struct passwd *passwd; 185 struct kinfo_proc2 *p, *plast; 186 int arg, ch, what; 187 char *memf, *nlistf; 188 char buf[_POSIX2_LINE_MAX]; 189 int cnt; 190 gid_t egid = getegid(); 191 192 (void)setegid(getgid()); 193 arg = 0; 194 what = KERN_PROC_ALL; 195 nlistf = memf = NULL; 196 while ((ch = getopt(argc, argv, "fnp:u:vN:M:")) != -1) 197 switch((char)ch) { 198 case 'f': 199 fsflg = 1; 200 break; 201 case 'M': 202 memf = optarg; 203 break; 204 case 'N': 205 nlistf = optarg; 206 break; 207 case 'n': 208 nflg = 1; 209 break; 210 case 'p': 211 if (pflg++) 212 usage(); 213 if (!isdigit((unsigned char)*optarg)) { 214 warnx("-p requires a process id"); 215 usage(); 216 } 217 what = KERN_PROC_PID; 218 arg = atoi(optarg); 219 break; 220 case 'u': 221 if (uflg++) 222 usage(); 223 if (!(passwd = getpwnam(optarg))) { 224 errx(1, "%s: unknown uid", optarg); 225 } 226 what = KERN_PROC_UID; 227 arg = passwd->pw_uid; 228 break; 229 case 'v': 230 vflg = 1; 231 break; 232 case '?': 233 default: 234 usage(); 235 } 236 237 if (*(argv += optind)) { 238 for (; *argv; ++argv) { 239 if (getfname(*argv)) 240 checkfile = 1; 241 } 242 if (!checkfile) /* file(s) specified, but none accessible */ 243 exit(1); 244 } 245 246 ALLOC_OFILES(256); /* reserve space for file pointers */ 247 248 if (fsflg && !checkfile) { 249 /* -f with no files means use wd */ 250 if (getfname(".") == 0) 251 exit(1); 252 checkfile = 1; 253 } 254 255 /* 256 * Discard setgid privileges. If not the running kernel, we toss 257 * them away totally so that bad guys can't print interesting stuff 258 * from kernel memory, otherwise switch back to kmem for the 259 * duration of the kvm_openfiles() call. 260 */ 261 if (nlistf != NULL || memf != NULL) 262 (void)setgid(getgid()); 263 else 264 (void)setegid(egid); 265 266 if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) 267 errx(1, "%s", buf); 268 269 /* get rid of it now anyway */ 270 if (nlistf == NULL && memf == NULL) 271 (void)setgid(getgid()); 272 273 if ((p = kvm_getproc2(kd, what, arg, sizeof *p, &cnt)) == NULL) { 274 errx(1, "%s", kvm_geterr(kd)); 275 } 276 if (nflg) 277 (void)printf("%s", 278"USER CMD PID FD DEV INUM MODE SZ|DV R/W"); 279 else 280 (void)printf("%s", 281"USER CMD PID FD MOUNT INUM MODE SZ|DV R/W"); 282 if (checkfile && fsflg == 0) 283 (void)printf(" NAME\n"); 284 else 285 (void)putchar('\n'); 286 287 for (plast = &p[cnt]; p < plast; ++p) { 288 if (p->p_stat == SZOMB) 289 continue; 290 dofiles(p); 291 } 292 return 0; 293} 294 295static const char *Uname, *Comm; 296pid_t Pid; 297 298#define PREFIX(i) (void)printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \ 299 switch(i) { \ 300 case TEXT: \ 301 (void)printf(" text"); \ 302 break; \ 303 case CDIR: \ 304 (void)printf(" wd"); \ 305 break; \ 306 case RDIR: \ 307 (void)printf(" root"); \ 308 break; \ 309 case TRACE: \ 310 (void)printf(" tr"); \ 311 break; \ 312 default: \ 313 (void)printf(" %4d", i); \ 314 break; \ 315 } 316 317/* 318 * print open files attributed to this process 319 */ 320static void 321dofiles(struct kinfo_proc2 *p) 322{ 323 int i; 324 struct filedesc filed; 325 struct cwdinfo cwdi; 326 struct fdtab dt; 327 328 Uname = user_from_uid(p->p_uid, 0); 329 Pid = p->p_pid; 330 Comm = p->p_comm; 331 332 if (p->p_fd == 0 || p->p_cwdi == 0) 333 return; 334 if (!KVM_READ(p->p_fd, &filed, sizeof (filed))) { 335 warnx("can't read filedesc at %p for pid %d", 336 (void *)(uintptr_t)p->p_fd, Pid); 337 return; 338 } 339 if (filed.fd_lastfile == -1) 340 return; 341 if (!KVM_READ(p->p_cwdi, &cwdi, sizeof(cwdi))) { 342 warnx("can't read cwdinfo at %p for pid %d", 343 (void *)(uintptr_t)p->p_cwdi, Pid); 344 return; 345 } 346 if (!KVM_READ(filed.fd_dt, &dt, sizeof(dt))) { 347 warnx("can't read dtab at %p for pid %d", filed.fd_dt, Pid); 348 return; 349 } 350 if ((unsigned)filed.fd_lastfile >= dt.dt_nfiles || 351 filed.fd_freefile > filed.fd_lastfile + 1) { 352 dprintf("filedesc corrupted at %p for pid %d", 353 (void *)(uintptr_t)p->p_fd, Pid); 354 return; 355 } 356 /* 357 * root directory vnode, if one 358 */ 359 if (cwdi.cwdi_rdir) 360 vtrans(cwdi.cwdi_rdir, RDIR, FREAD); 361 /* 362 * current working directory vnode 363 */ 364 vtrans(cwdi.cwdi_cdir, CDIR, FREAD); 365#if 0 366 /* 367 * Disable for now, since p->p_tracep appears to point to a ktr_desc * 368 * ktrace vnode, if one 369 */ 370 if (p->p_tracep) 371 ftrans(p->p_tracep, TRACE); 372#endif 373 /* 374 * open files 375 */ 376#define FPSIZE (sizeof (fdfile_t *)) 377 ALLOC_OFILES(filed.fd_lastfile+1); 378 if (!KVM_READ(&filed.fd_dt->dt_ff, ofiles, 379 (filed.fd_lastfile+1) * FPSIZE)) { 380 dprintf("can't read file structures at %p for pid %d", 381 &filed.fd_dt->dt_ff, Pid); 382 return; 383 } 384 for (i = 0; i <= filed.fd_lastfile; i++) { 385 if (ofiles[i] == NULL) 386 continue; 387 ftrans(ofiles[i], i); 388 } 389} 390 391static void 392ftrans(fdfile_t *fp, int i) 393{ 394 struct file file; 395 fdfile_t fdfile; 396 397 if (!KVM_READ(fp, &fdfile, sizeof(fdfile))) { 398 dprintf("can't read file %d at %p for pid %d", 399 i, fp, Pid); 400 return; 401 } 402 if (fdfile.ff_file == NULL) 403 return; 404 if (!KVM_READ(fdfile.ff_file, &file, sizeof(file))) { 405 dprintf("can't read file %d at %p for pid %d", 406 i, fdfile.ff_file, Pid); 407 return; 408 } 409 switch (file.f_type) { 410 case DTYPE_VNODE: 411 vtrans(file.f_data, i, file.f_flag); 412 break; 413 case DTYPE_SOCKET: 414 if (checkfile == 0) 415 socktrans(file.f_data, i); 416 break; 417 case DTYPE_PIPE: 418 if (checkfile == 0) 419 ptrans(&file, file.f_data, i); 420 break; 421 case DTYPE_MISC: 422 case DTYPE_KQUEUE: 423 case DTYPE_CRYPTO: 424 case DTYPE_MQUEUE: 425 case DTYPE_SEM: 426 if (checkfile == 0) 427 misctrans(&file); 428 break; 429 default: 430 dprintf("unknown file type %d for file %d of pid %d", 431 file.f_type, i, Pid); 432 break; 433 } 434} 435 436static const char dead[] = "dead"; 437 438static const char * 439vfilestat(struct vnode *vp, struct filestat *fsp) 440{ 441 const char *badtype = NULL; 442 443 if (vp->v_type == VNON) 444 badtype = "none"; 445 else if (vp->v_type == VBAD) 446 badtype = "bad"; 447 else 448 switch (vp->v_tag) { 449 case VT_NON: 450 badtype = dead; 451 break; 452 case VT_UFS: 453 case VT_LFS: 454 case VT_MFS: 455 if (!ufs_filestat(vp, fsp)) 456 badtype = "error"; 457 break; 458 case VT_MSDOSFS: 459 if (!msdosfs_filestat(vp, fsp)) 460 badtype = "error"; 461 break; 462 case VT_NFS: 463 if (!nfs_filestat(vp, fsp)) 464 badtype = "error"; 465 break; 466 case VT_EXT2FS: 467 if (!ext2fs_filestat(vp, fsp)) 468 badtype = "error"; 469 break; 470 case VT_ISOFS: 471 if (!isofs_filestat(vp, fsp)) 472 badtype = "error"; 473 break; 474 case VT_NTFS: 475 if (!ntfs_filestat(vp, fsp)) 476 badtype = "error"; 477 break; 478 case VT_PTYFS: 479 if (!ptyfs_filestat(vp, fsp)) 480 badtype = "error"; 481 break; 482 case VT_TMPFS: 483 if (!tmpfs_filestat(vp, fsp)) 484 badtype = "error"; 485 break; 486 case VT_NULL: 487 case VT_OVERLAY: 488 case VT_UMAP: 489 badtype = layer_filestat(vp, fsp); 490 break; 491 default: { 492 static char unknown[10]; 493 (void)snprintf(unknown, sizeof unknown, 494 "?(%x)", vp->v_tag); 495 badtype = unknown; 496 break; 497 } 498 } 499 return badtype; 500} 501 502static void 503vtrans(struct vnode *vp, int i, int flag) 504{ 505 struct vnode vn; 506 struct filestat fst; 507 char mode[15], rw[3]; 508 const char *badtype, *filename; 509 510 filename = NULL; 511 if (!KVM_READ(vp, &vn, sizeof(struct vnode))) { 512 dprintf("can't read vnode at %p for pid %d", vp, Pid); 513 return; 514 } 515 badtype = vfilestat(&vn, &fst); 516 if (checkfile) { 517 int fsmatch = 0; 518 DEVS *d; 519 520 if (badtype && badtype != dead) 521 return; 522 for (d = devs; d != NULL; d = d->next) 523 if (d->fsid == fst.fsid) { 524 fsmatch = 1; 525 if (d->ino == fst.fileid) { 526 filename = d->name; 527 break; 528 } 529 } 530 if (fsmatch == 0 || (filename == NULL && fsflg == 0)) 531 return; 532 } 533 PREFIX(i); 534 if (badtype == dead) { 535 char buf[1024]; 536 (void)snprintb(buf, sizeof(buf), VNODE_FLAGBITS, 537 vn.v_iflag | vn.v_vflag | vn.v_uflag); 538 (void)printf(" flags %s\n", buf); 539 return; 540 } else if (badtype) { 541 (void)printf(" - - %10s -\n", badtype); 542 return; 543 } 544 if (nflg) 545 (void)printf(" %2llu,%-2llu", 546 (unsigned long long)major(fst.fsid), 547 (unsigned long long)minor(fst.fsid)); 548 else 549 (void)printf(" %-8s", getmnton(vn.v_mount)); 550 if (nflg) 551 (void)snprintf(mode, sizeof mode, "%o", fst.mode); 552 else 553 strmode(fst.mode, mode); 554 (void)printf(" %7"PRIu64" %*s", fst.fileid, nflg ? 5 : 10, mode); 555 switch (vn.v_type) { 556 case VBLK: 557 case VCHR: { 558 char *name; 559 560 if (nflg || ((name = devname(fst.rdev, vn.v_type == VCHR ? 561 S_IFCHR : S_IFBLK)) == NULL)) 562 (void)printf(" %2llu,%-2llu", 563 (unsigned long long)major(fst.rdev), 564 (unsigned long long)minor(fst.rdev)); 565 else 566 (void)printf(" %6s", name); 567 break; 568 } 569 default: 570 (void)printf(" %6lld", (long long)fst.size); 571 } 572 rw[0] = '\0'; 573 if (flag & FREAD) 574 (void)strlcat(rw, "r", sizeof(rw)); 575 if (flag & FWRITE) 576 (void)strlcat(rw, "w", sizeof(rw)); 577 (void)printf(" %-2s", rw); 578 if (filename && !fsflg) 579 (void)printf(" %s", filename); 580 (void)putchar('\n'); 581} 582 583static int 584ufs_filestat(struct vnode *vp, struct filestat *fsp) 585{ 586 struct inode inode; 587 struct ufsmount ufsmount; 588 union dinode { 589 struct ufs1_dinode dp1; 590 struct ufs2_dinode dp2; 591 } dip; 592 593 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { 594 dprintf("can't read inode at %p for pid %d", VTOI(vp), Pid); 595 return 0; 596 } 597 598 if (!KVM_READ(inode.i_ump, &ufsmount, sizeof (struct ufsmount))) { 599 dprintf("can't read ufsmount at %p for pid %d", inode.i_ump, Pid); 600 return 0; 601 } 602 603 switch (ufsmount.um_fstype) { 604 case UFS1: 605 if (!KVM_READ(inode.i_din.ffs1_din, &dip, 606 sizeof(struct ufs1_dinode))) { 607 dprintf("can't read dinode at %p for pid %d", 608 inode.i_din.ffs1_din, Pid); 609 return 0; 610 } 611 fsp->rdev = dip.dp1.di_rdev; 612 break; 613 case UFS2: 614 if (!KVM_READ(inode.i_din.ffs2_din, &dip, 615 sizeof(struct ufs2_dinode))) { 616 dprintf("can't read dinode at %p for pid %d", 617 inode.i_din.ffs2_din, Pid); 618 return 0; 619 } 620 fsp->rdev = dip.dp2.di_rdev; 621 break; 622 default: 623 dprintf("unknown ufs type %ld for pid %d", 624 ufsmount.um_fstype, Pid); 625 break; 626 } 627 fsp->fsid = inode.i_dev & 0xffff; 628 fsp->fileid = inode.i_number; 629 fsp->mode = (mode_t)inode.i_mode; 630 fsp->size = inode.i_size; 631 632 return 1; 633} 634 635static int 636ext2fs_filestat(struct vnode *vp, struct filestat *fsp) 637{ 638 struct inode inode; 639 struct ext2fs_dinode dinode; 640 641 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { 642 dprintf("can't read inode at %p for pid %d", VTOI(vp), Pid); 643 return 0; 644 } 645 fsp->fsid = inode.i_dev & 0xffff; 646 fsp->fileid = inode.i_number; 647 648 if (!KVM_READ(inode.i_din.e2fs_din, &dinode, sizeof dinode)) { 649 dprintf("can't read ext2fs_dinode at %p for pid %d", 650 inode.i_din.e2fs_din, Pid); 651 return 0; 652 } 653 fsp->mode = dinode.e2di_mode; 654 fsp->size = dinode.e2di_size; 655 fsp->rdev = dinode.e2di_rdev; 656 657 return 1; 658} 659 660static int 661nfs_filestat(struct vnode *vp, struct filestat *fsp) 662{ 663 struct nfsnode nfsnode; 664 struct vattr va; 665 666 if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) { 667 dprintf("can't read nfsnode at %p for pid %d", VTONFS(vp), 668 Pid); 669 return 0; 670 } 671 if (!KVM_READ(nfsnode.n_vattr, &va, sizeof(va))) { 672 dprintf("can't read vnode attributes at %p for pid %d", 673 nfsnode.n_vattr, Pid); 674 return 0; 675 } 676 fsp->fsid = va.va_fsid; 677 fsp->fileid = va.va_fileid; 678 fsp->size = nfsnode.n_size; 679 fsp->rdev = va.va_rdev; 680 fsp->mode = (mode_t)va.va_mode | getftype(vp->v_type); 681 682 return 1; 683} 684 685static int 686msdosfs_filestat(struct vnode *vp, struct filestat *fsp) 687{ 688 struct denode de; 689 struct msdosfsmount mp; 690 691 if (!KVM_READ(VTONFS(vp), &de, sizeof(de))) { 692 dprintf("can't read denode at %p for pid %d", VTONFS(vp), 693 Pid); 694 return 0; 695 } 696 if (!KVM_READ(de.de_pmp, &mp, sizeof(mp))) { 697 dprintf("can't read mount struct at %p for pid %d", de.de_pmp, 698 Pid); 699 return 0; 700 } 701 702 fsp->fsid = de.de_dev & 0xffff; 703 fsp->fileid = 0; /* XXX see msdosfs_vptofh() for more info */ 704 fsp->size = de.de_FileSize; 705 fsp->rdev = 0; /* msdosfs doesn't support device files */ 706 fsp->mode = (0777 & mp.pm_mask) | getftype(vp->v_type); 707 return 1; 708} 709 710static const char * 711layer_filestat(struct vnode *vp, struct filestat *fsp) 712{ 713 struct layer_node layer_node; 714 struct mount mount; 715 struct vnode vn; 716 const char *badtype; 717 718 if (!KVM_READ(VTOLAYER(vp), &layer_node, sizeof(layer_node))) { 719 dprintf("can't read layer_node at %p for pid %d", 720 VTOLAYER(vp), Pid); 721 return "error"; 722 } 723 if (!KVM_READ(vp->v_mount, &mount, sizeof(struct mount))) { 724 dprintf("can't read mount struct at %p for pid %d", 725 vp->v_mount, Pid); 726 return "error"; 727 } 728 vp = layer_node.layer_lowervp; 729 if (!KVM_READ(vp, &vn, sizeof(struct vnode))) { 730 dprintf("can't read vnode at %p for pid %d", vp, Pid); 731 return "error"; 732 } 733 if ((badtype = vfilestat(&vn, fsp)) == NULL) 734 fsp->fsid = mount.mnt_stat.f_fsidx.__fsid_val[0]; 735 return badtype; 736} 737 738static char * 739getmnton(struct mount *m) 740{ 741 static struct mount mount; 742 static struct mtab { 743 struct mtab *next; 744 struct mount *m; 745 char mntonname[MNAMELEN]; 746 } *mhead = NULL; 747 struct mtab *mt; 748 749 for (mt = mhead; mt != NULL; mt = mt->next) 750 if (m == mt->m) 751 return mt->mntonname; 752 if (!KVM_READ(m, &mount, sizeof(struct mount))) { 753 warnx("can't read mount table at %p", m); 754 return NULL; 755 } 756 if ((mt = malloc(sizeof (struct mtab))) == NULL) { 757 err(1, "malloc(%u)", (unsigned int)sizeof(struct mtab)); 758 } 759 mt->m = m; 760 (void)memmove(&mt->mntonname[0], &mount.mnt_stat.f_mntonname[0], 761 MNAMELEN); 762 mt->next = mhead; 763 mhead = mt; 764 return mt->mntonname; 765} 766 767static const char * 768inet_addrstr(char *buf, size_t len, const struct in_addr *a, uint16_t p) 769{ 770 char addr[256]; 771 772 if (a->s_addr == INADDR_ANY) { 773 if (p == 0) 774 addr[0] = '\0'; 775 else 776 strlcpy(addr, "*", sizeof(addr)); 777 } else { 778 struct sockaddr_in sin; 779 const int niflags = NI_NUMERICHOST; 780 781 (void)memset(&sin, 0, sizeof(sin)); 782 sin.sin_family = AF_INET6; 783 sin.sin_len = sizeof(sin); 784 sin.sin_addr = *a; 785 786 if (getnameinfo((struct sockaddr *)&sin, sin.sin_len, 787 addr, sizeof(addr), NULL, 0, niflags)) 788 if (inet_ntop(AF_INET, a, addr, sizeof(addr)) == NULL) 789 strlcpy(addr, "invalid", sizeof(addr)); 790 } 791 if (addr[0]) 792 snprintf(buf, len, "%s:%u", addr, p); 793 else 794 strlcpy(buf, addr, len); 795 return buf; 796} 797 798#ifdef INET6 799static const char * 800inet6_addrstr(char *buf, size_t len, const struct in6_addr *a, uint16_t p) 801{ 802 char addr[256]; 803 804 if (IN6_IS_ADDR_UNSPECIFIED(a)) { 805 if (p == 0) 806 addr[0] = '\0'; 807 else 808 strlcpy(addr, "*", sizeof(addr)); 809 } else { 810 struct sockaddr_in6 sin6; 811 const int niflags = NI_NUMERICHOST; 812 813 (void)memset(&sin6, 0, sizeof(sin6)); 814 sin6.sin6_family = AF_INET6; 815 sin6.sin6_len = sizeof(sin6); 816 sin6.sin6_addr = *a; 817 818 if (IN6_IS_ADDR_LINKLOCAL(a) && 819 *(u_int16_t *)&sin6.sin6_addr.s6_addr[2] != 0) { 820 sin6.sin6_scope_id = 821 ntohs(*(uint16_t *)&sin6.sin6_addr.s6_addr[2]); 822 sin6.sin6_addr.s6_addr[2] = 0; 823 sin6.sin6_addr.s6_addr[3] = 0; 824 } 825 826 if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 827 addr, sizeof(addr), NULL, 0, niflags)) 828 if (inet_ntop(AF_INET6, a, addr, sizeof(addr)) == NULL) 829 strlcpy(addr, "invalid", sizeof(addr)); 830 } 831 if (addr[0]) 832 snprintf(buf, len, "[%s]:%u", addr, p); 833 else 834 strlcpy(buf, addr, len); 835 836 return buf; 837} 838#endif 839 840static const char * 841at_addrstr(char *buf, size_t len, const struct sockaddr_at *sat) 842{ 843 const struct netrange *nr = &sat->sat_range.r_netrange; 844 const struct at_addr *at = &sat->sat_addr; 845 char addr[64], phase[64], range[64]; 846 847 if (sat->sat_port || at->s_net || at->s_node) { 848 if (at->s_net || at->s_node) 849 snprintf(addr, sizeof(addr), "%u.%u:%u", 850 ntohs(at->s_net), at->s_node, sat->sat_port); 851 else 852 snprintf(addr, sizeof(addr), "*:%u", sat->sat_port); 853 } else 854 addr[0] = '\0'; 855 856 if (nr->nr_phase) 857 snprintf(phase, sizeof(phase), " phase %u", nr->nr_phase); 858 else 859 phase[0] = '\0'; 860 861 if (nr->nr_firstnet || nr->nr_lastnet) 862 snprintf(range, sizeof(range), " range [%u-%u]", 863 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet)); 864 else 865 range[0] = '\0'; 866 867 snprintf(buf, len, "%s%s%s", addr, phase, range); 868 return buf; 869} 870 871static void 872socktrans(struct socket *sock, int i) 873{ 874 static const char *stypename[] = { 875 "unused", /* 0 */ 876 "stream", /* 1 */ 877 "dgram", /* 2 */ 878 "raw", /* 3 */ 879 "rdm", /* 4 */ 880 "seqpak" /* 5 */ 881 }; 882#define STYPEMAX 5 883 struct socket so; 884 struct protosw proto; 885 struct domain dom; 886 struct inpcb inpcb; 887#ifdef INET6 888 struct in6pcb in6pcb; 889#endif 890 struct unpcb unpcb; 891 struct ddpcb ddpcb; 892 int len; 893 char dname[32]; 894 char lbuf[512], fbuf[512]; 895 PREFIX(i); 896 897 /* fill in socket */ 898 if (!KVM_READ(sock, &so, sizeof(struct socket))) { 899 dprintf("can't read sock at %p", sock); 900 goto bad; 901 } 902 903 /* fill in protosw entry */ 904 if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) { 905 dprintf("can't read protosw at %p", so.so_proto); 906 goto bad; 907 } 908 909 /* fill in domain */ 910 if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) { 911 dprintf("can't read domain at %p", proto.pr_domain); 912 goto bad; 913 } 914 915 if ((len = kvm_read(kd, (u_long)dom.dom_name, dname, 916 sizeof(dname) - 1)) != sizeof(dname) -1) { 917 dprintf("can't read domain name at %p", dom.dom_name); 918 dname[0] = '\0'; 919 } 920 else 921 dname[len] = '\0'; 922 923 if ((u_short)so.so_type > STYPEMAX) 924 (void)printf("* %s ?%d", dname, so.so_type); 925 else 926 (void)printf("* %s %s", dname, stypename[so.so_type]); 927 928 /* 929 * protocol specific formatting 930 * 931 * Try to find interesting things to print. For TCP, the interesting 932 * thing is the address of the tcpcb, for UDP and others, just the 933 * inpcb (socket pcb). For UNIX domain, its the address of the socket 934 * pcb and the address of the connected pcb (if connected). Otherwise 935 * just print the protocol number and address of the socket itself. 936 * The idea is not to duplicate netstat, but to make available enough 937 * information for further analysis. 938 */ 939 fbuf[0] = '\0'; 940 lbuf[0] = '\0'; 941 switch(dom.dom_family) { 942 case AF_INET: 943 getinetproto(proto.pr_protocol); 944 switch (proto.pr_protocol) { 945 case IPPROTO_TCP: 946 case IPPROTO_UDP: 947 if (so.so_pcb == NULL) 948 break; 949 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, 950 sizeof(inpcb)) != sizeof(inpcb)) { 951 dprintf("can't read inpcb at %p", so.so_pcb); 952 goto bad; 953 } 954 inet_addrstr(lbuf, sizeof(lbuf), &inpcb.inp_laddr, 955 ntohs(inpcb.inp_lport)); 956 inet_addrstr(fbuf, sizeof(fbuf), &inpcb.inp_faddr, 957 ntohs(inpcb.inp_fport)); 958 break; 959 default: 960 break; 961 } 962 break; 963#ifdef INET6 964 case AF_INET6: 965 getinetproto(proto.pr_protocol); 966 switch (proto.pr_protocol) { 967 case IPPROTO_TCP: 968 case IPPROTO_UDP: 969 if (so.so_pcb == NULL) 970 break; 971 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&in6pcb, 972 sizeof(in6pcb)) != sizeof(in6pcb)) { 973 dprintf("can't read in6pcb at %p", so.so_pcb); 974 goto bad; 975 } 976 inet6_addrstr(lbuf, sizeof(lbuf), &in6pcb.in6p_laddr, 977 ntohs(in6pcb.in6p_lport)); 978 inet6_addrstr(fbuf, sizeof(fbuf), &in6pcb.in6p_faddr, 979 ntohs(in6pcb.in6p_fport)); 980 break; 981 default: 982 break; 983 } 984 break; 985#endif 986 case AF_LOCAL: 987 /* print address of pcb and connected pcb */ 988 if (so.so_pcb) { 989 char shoconn[4], *cp; 990 991 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb, 992 sizeof(struct unpcb)) != sizeof(struct unpcb)){ 993 dprintf("can't read unpcb at %p", so.so_pcb); 994 goto bad; 995 } 996 997 cp = shoconn; 998 if (!(so.so_state & SS_CANTRCVMORE)) 999 *cp++ = '<'; 1000 *cp++ = '-'; 1001 if (!(so.so_state & SS_CANTSENDMORE)) 1002 *cp++ = '>'; 1003 *cp = '\0'; 1004 if (unpcb.unp_addr) { 1005 struct sockaddr_un *sun = 1006 malloc(unpcb.unp_addrlen); 1007 if (sun == NULL) 1008 err(1, "malloc(%zu)", 1009 unpcb.unp_addrlen); 1010 if (kvm_read(kd, (u_long)unpcb.unp_addr, 1011 sun, unpcb.unp_addrlen) != 1012 (ssize_t)unpcb.unp_addrlen) { 1013 dprintf("can't read sun at %p", 1014 unpcb.unp_addr); 1015 free(sun); 1016 } else { 1017 snprintf(fbuf, sizeof(fbuf), " %s %s", 1018 shoconn, sun->sun_path); 1019 free(sun); 1020 break; 1021 } 1022 } 1023 if (unpcb.unp_conn) 1024 snprintf(fbuf, sizeof(fbuf), " %s %lx", shoconn, 1025 (long)unpcb.unp_conn); 1026 } 1027 break; 1028 case AF_APPLETALK: 1029 getatproto(proto.pr_protocol); 1030 if (so.so_pcb) { 1031 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&ddpcb, 1032 sizeof(ddpcb)) != sizeof(ddpcb)){ 1033 dprintf("can't read ddpcb at %p", so.so_pcb); 1034 goto bad; 1035 } 1036 at_addrstr(fbuf, sizeof(fbuf), &ddpcb.ddp_fsat); 1037 at_addrstr(lbuf, sizeof(lbuf), &ddpcb.ddp_lsat); 1038 } 1039 break; 1040 default: 1041 /* print protocol number and socket address */ 1042 snprintf(fbuf, sizeof(fbuf), " %d %jx", proto.pr_protocol, 1043 (uintmax_t)(uintptr_t)sock); 1044 break; 1045 } 1046 if (fbuf[0] || lbuf[0]) 1047 printf(" %s%s%s", fbuf, (fbuf[0] && lbuf[0]) ? " <-> " : "", 1048 lbuf); 1049 else if (so.so_pcb) 1050 printf(" %jx", (uintmax_t)(uintptr_t)so.so_pcb); 1051 (void)printf("\n"); 1052 return; 1053bad: 1054 (void)printf("* error\n"); 1055} 1056 1057static void 1058ptrans(struct file *fp, struct pipe *cpipe, int i) 1059{ 1060 struct pipe cp; 1061 1062 PREFIX(i); 1063 1064 /* fill in pipe */ 1065 if (!KVM_READ(cpipe, &cp, sizeof(struct pipe))) { 1066 dprintf("can't read pipe at %p", cpipe); 1067 goto bad; 1068 } 1069 1070 /* pipe descriptor is either read or write, never both */ 1071 (void)printf("* pipe %p %s %p %s%s%s", cpipe, 1072 (fp->f_flag & FWRITE) ? "->" : "<-", 1073 cp.pipe_peer, 1074 (fp->f_flag & FWRITE) ? "w" : "r", 1075 (fp->f_flag & FNONBLOCK) ? "n" : "", 1076 (cp.pipe_state & PIPE_ASYNC) ? "a" : ""); 1077 (void)printf("\n"); 1078 return; 1079bad: 1080 (void)printf("* error\n"); 1081} 1082 1083static void 1084misctrans(struct file *file) 1085{ 1086 1087 PREFIX((int)file->f_type); 1088 pmisc(file, dtypes[file->f_type]); 1089} 1090 1091/* 1092 * getinetproto -- 1093 * print name of protocol number 1094 */ 1095static void 1096getinetproto(int number) 1097{ 1098 const char *cp; 1099 1100 switch (number) { 1101 case IPPROTO_IP: 1102 cp = "ip"; break; 1103 case IPPROTO_ICMP: 1104 cp ="icmp"; break; 1105 case IPPROTO_GGP: 1106 cp ="ggp"; break; 1107 case IPPROTO_TCP: 1108 cp ="tcp"; break; 1109 case IPPROTO_EGP: 1110 cp ="egp"; break; 1111 case IPPROTO_PUP: 1112 cp ="pup"; break; 1113 case IPPROTO_UDP: 1114 cp ="udp"; break; 1115 case IPPROTO_IDP: 1116 cp ="idp"; break; 1117 case IPPROTO_RAW: 1118 cp ="raw"; break; 1119 case IPPROTO_ICMPV6: 1120 cp ="icmp6"; break; 1121 default: 1122 (void)printf(" %d", number); 1123 return; 1124 } 1125 (void)printf(" %s", cp); 1126} 1127 1128/* 1129 * getatproto -- 1130 * print name of protocol number 1131 */ 1132static void 1133getatproto(int number) 1134{ 1135 const char *cp; 1136 1137 switch (number) { 1138 case ATPROTO_DDP: 1139 cp = "ddp"; break; 1140 case ATPROTO_AARP: 1141 cp ="aarp"; break; 1142 default: 1143 (void)printf(" %d", number); 1144 return; 1145 } 1146 (void)printf(" %s", cp); 1147} 1148 1149static int 1150getfname(const char *filename) 1151{ 1152 struct stat statbuf; 1153 DEVS *cur; 1154 1155 if (stat(filename, &statbuf)) { 1156 warn("stat(%s)", filename); 1157 return 0; 1158 } 1159 if ((cur = malloc(sizeof(*cur))) == NULL) { 1160 err(1, "malloc(%zu)", sizeof(*cur)); 1161 } 1162 cur->next = devs; 1163 devs = cur; 1164 1165 cur->ino = statbuf.st_ino; 1166 cur->fsid = statbuf.st_dev & 0xffff; 1167 cur->name = filename; 1168 return 1; 1169} 1170 1171mode_t 1172getftype(enum vtype v_type) 1173{ 1174 mode_t ftype; 1175 1176 switch (v_type) { 1177 case VREG: 1178 ftype = S_IFREG; 1179 break; 1180 case VDIR: 1181 ftype = S_IFDIR; 1182 break; 1183 case VBLK: 1184 ftype = S_IFBLK; 1185 break; 1186 case VCHR: 1187 ftype = S_IFCHR; 1188 break; 1189 case VLNK: 1190 ftype = S_IFLNK; 1191 break; 1192 case VSOCK: 1193 ftype = S_IFSOCK; 1194 break; 1195 case VFIFO: 1196 ftype = S_IFIFO; 1197 break; 1198 default: 1199 ftype = 0; 1200 break; 1201 }; 1202 1203 return ftype; 1204} 1205 1206static void 1207usage(void) 1208{ 1209 (void)fprintf(stderr, "Usage: %s [-fnv] [-p pid] [-u user] " 1210 "[-N system] [-M core] [file ...]\n", getprogname()); 1211 exit(1); 1212} 1213