1 /* $NetBSD: fstat.c,v 1.100 2012/11/25 00:36:23 christos Exp $ */ 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 40 static char sccsid[] = "@(#)fstat.c 8.3 (Berkeley) 5/2/95"; 41 #else 42 __RCSID("$NetBSD: fstat.c,v 1.100 2012/11/25 00:36:23 christos Exp $"); 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 122 typedef struct devs { 123 struct devs *next; 124 long fsid; 125 ino_t ino; 126 const char *name; 127 } DEVS; 128 static DEVS *devs; 129 130 static 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 */ 133 static int checkfile; /* true if restricting to particular files or filesystems */ 134 static int nflg; /* (numerical) display f.s. and rdev as dev_t */ 135 int vflg; /* display errors in locating kernel data objects etc... */ 136 137 static fdfile_t **ofiles; /* buffer of pointers to file structures */ 138 static 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 150 kvm_t *kd; 151 152 static const char *const dtypes[] = { 153 DTYPE_NAMES 154 }; 155 156 static void dofiles(struct kinfo_proc2 *); 157 static int ext2fs_filestat(struct vnode *, struct filestat *); 158 static int getfname(const char *); 159 static void getinetproto(int); 160 static void getatproto(int); 161 static char *getmnton(struct mount *); 162 static const char *layer_filestat(struct vnode *, struct filestat *); 163 static int msdosfs_filestat(struct vnode *, struct filestat *); 164 static int nfs_filestat(struct vnode *, struct filestat *); 165 static const char *inet_addrstr(char *, size_t, const struct in_addr *, 166 uint16_t); 167 #ifdef INET6 168 static const char *inet6_addrstr(char *, size_t, const struct in6_addr *, 169 uint16_t); 170 #endif 171 static const char *at_addrstr(char *, size_t, const struct sockaddr_at *); 172 static void socktrans(struct socket *, int); 173 static void misctrans(struct file *, int); 174 static int ufs_filestat(struct vnode *, struct filestat *); 175 static void usage(void) __dead; 176 static const char *vfilestat(struct vnode *, struct filestat *); 177 static void vtrans(struct vnode *, int, int); 178 static void ftrans(fdfile_t *, int); 179 static void ptrans(struct file *, struct pipe *, int); 180 static void kdriver_init(void); 181 182 int 183 main(int argc, char **argv) 184 { 185 struct passwd *passwd; 186 struct kinfo_proc2 *p, *plast; 187 int arg, ch, what; 188 char *memf, *nlistf; 189 char buf[_POSIX2_LINE_MAX]; 190 int cnt; 191 gid_t egid = getegid(); 192 193 (void)setegid(getgid()); 194 arg = 0; 195 what = KERN_PROC_ALL; 196 nlistf = memf = NULL; 197 while ((ch = getopt(argc, argv, "fnp:u:vN:M:")) != -1) 198 switch((char)ch) { 199 case 'f': 200 fsflg = 1; 201 break; 202 case 'M': 203 memf = optarg; 204 break; 205 case 'N': 206 nlistf = optarg; 207 break; 208 case 'n': 209 nflg = 1; 210 break; 211 case 'p': 212 if (pflg++) 213 usage(); 214 if (!isdigit((unsigned char)*optarg)) { 215 warnx("-p requires a process id"); 216 usage(); 217 } 218 what = KERN_PROC_PID; 219 arg = atoi(optarg); 220 break; 221 case 'u': 222 if (uflg++) 223 usage(); 224 if (!(passwd = getpwnam(optarg))) { 225 errx(1, "%s: unknown uid", optarg); 226 } 227 what = KERN_PROC_UID; 228 arg = passwd->pw_uid; 229 break; 230 case 'v': 231 vflg = 1; 232 break; 233 case '?': 234 default: 235 usage(); 236 } 237 238 kdriver_init(); 239 240 if (*(argv += optind)) { 241 for (; *argv; ++argv) { 242 if (getfname(*argv)) 243 checkfile = 1; 244 } 245 if (!checkfile) /* file(s) specified, but none accessible */ 246 exit(1); 247 } 248 249 ALLOC_OFILES(256); /* reserve space for file pointers */ 250 251 if (fsflg && !checkfile) { 252 /* -f with no files means use wd */ 253 if (getfname(".") == 0) 254 exit(1); 255 checkfile = 1; 256 } 257 258 /* 259 * Discard setgid privileges. If not the running kernel, we toss 260 * them away totally so that bad guys can't print interesting stuff 261 * from kernel memory, otherwise switch back to kmem for the 262 * duration of the kvm_openfiles() call. 263 */ 264 if (nlistf != NULL || memf != NULL) 265 (void)setgid(getgid()); 266 else 267 (void)setegid(egid); 268 269 if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) 270 errx(1, "%s", buf); 271 272 /* get rid of it now anyway */ 273 if (nlistf == NULL && memf == NULL) 274 (void)setgid(getgid()); 275 276 if ((p = kvm_getproc2(kd, what, arg, sizeof *p, &cnt)) == NULL) { 277 errx(1, "%s", kvm_geterr(kd)); 278 } 279 if (nflg) 280 (void)printf("%s", 281 "USER CMD PID FD DEV INUM MODE SZ|DV R/W"); 282 else 283 (void)printf("%s", 284 "USER CMD PID FD MOUNT INUM MODE SZ|DV R/W"); 285 if (checkfile && fsflg == 0) 286 (void)printf(" NAME\n"); 287 else 288 (void)putchar('\n'); 289 290 for (plast = &p[cnt]; p < plast; ++p) { 291 if (p->p_stat == SZOMB) 292 continue; 293 dofiles(p); 294 } 295 return 0; 296 } 297 298 static const char *Uname, *Comm; 299 pid_t Pid; 300 301 #define PREFIX(i) (void)printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \ 302 switch(i) { \ 303 case TEXT: \ 304 (void)printf(" text"); \ 305 break; \ 306 case CDIR: \ 307 (void)printf(" wd"); \ 308 break; \ 309 case RDIR: \ 310 (void)printf(" root"); \ 311 break; \ 312 case TRACE: \ 313 (void)printf(" tr"); \ 314 break; \ 315 default: \ 316 (void)printf(" %4d", i); \ 317 break; \ 318 } 319 320 static struct kinfo_drivers *kdriver; 321 static size_t kdriverlen; 322 323 static int 324 kdriver_comp(const void *a, const void *b) 325 { 326 const struct kinfo_drivers *ka = a; 327 const struct kinfo_drivers *kb = b; 328 int kac = ka->d_cmajor == -1 ? 0 : ka->d_cmajor; 329 int kbc = kb->d_cmajor == -1 ? 0 : kb->d_cmajor; 330 int kab = ka->d_bmajor == -1 ? 0 : ka->d_bmajor; 331 int kbb = kb->d_bmajor == -1 ? 0 : kb->d_bmajor; 332 int c = kac - kbc; 333 if (c == 0) 334 return kab - kbb; 335 else 336 return c; 337 } 338 339 static const char * 340 kdriver_search(int type, dev_t num) 341 { 342 struct kinfo_drivers k, *kp; 343 static char buf[64]; 344 345 if (nflg) 346 goto out; 347 348 if (type == VBLK) { 349 k.d_bmajor = num; 350 k.d_cmajor = -1; 351 } else { 352 k.d_bmajor = -1; 353 k.d_cmajor = num; 354 } 355 kp = bsearch(&k, kdriver, kdriverlen, sizeof(*kdriver), kdriver_comp); 356 if (kp) 357 return kp->d_name; 358 out: 359 snprintf(buf, sizeof(buf), "%llu", (unsigned long long)num); 360 return buf; 361 } 362 363 364 static void 365 kdriver_init(void) 366 { 367 size_t sz; 368 int error; 369 static const int name[2] = { CTL_KERN, KERN_DRIVERS }; 370 371 error = sysctl(name, __arraycount(name), NULL, &sz, NULL, 0); 372 if (error == -1) { 373 warn("sysctl kern.drivers"); 374 return; 375 } 376 377 if (sz % sizeof(*kdriver)) { 378 warnx("bad size %zu for kern.drivers", sz); 379 return; 380 } 381 382 kdriver = malloc(sz); 383 if (kdriver == NULL) { 384 warn("malloc"); 385 return; 386 } 387 388 error = sysctl(name, __arraycount(name), kdriver, &sz, NULL, 0); 389 if (error == -1) { 390 warn("sysctl kern.drivers"); 391 return; 392 } 393 394 kdriverlen = sz / sizeof(*kdriver); 395 qsort(kdriver, kdriverlen, sizeof(*kdriver), kdriver_comp); 396 #ifdef DEBUG 397 for (size_t i = 0; i < kdriverlen; i++) 398 printf("%d %d %s\n", kdriver[i].d_cmajor, kdriver[i].d_bmajor, 399 kdriver[i].d_name); 400 #endif 401 } 402 403 /* 404 * print open files attributed to this process 405 */ 406 static void 407 dofiles(struct kinfo_proc2 *p) 408 { 409 int i; 410 struct filedesc filed; 411 struct cwdinfo cwdi; 412 struct fdtab dt; 413 414 Uname = user_from_uid(p->p_uid, 0); 415 Pid = p->p_pid; 416 Comm = p->p_comm; 417 418 if (p->p_fd == 0 || p->p_cwdi == 0) 419 return; 420 if (!KVM_READ(p->p_fd, &filed, sizeof (filed))) { 421 warnx("can't read filedesc at %p for pid %d", 422 (void *)(uintptr_t)p->p_fd, Pid); 423 return; 424 } 425 if (filed.fd_lastfile == -1) 426 return; 427 if (!KVM_READ(p->p_cwdi, &cwdi, sizeof(cwdi))) { 428 warnx("can't read cwdinfo at %p for pid %d", 429 (void *)(uintptr_t)p->p_cwdi, Pid); 430 return; 431 } 432 if (!KVM_READ(filed.fd_dt, &dt, sizeof(dt))) { 433 warnx("can't read dtab at %p for pid %d", filed.fd_dt, Pid); 434 return; 435 } 436 if ((unsigned)filed.fd_lastfile >= dt.dt_nfiles || 437 filed.fd_freefile > filed.fd_lastfile + 1) { 438 dprintf("filedesc corrupted at %p for pid %d", 439 (void *)(uintptr_t)p->p_fd, Pid); 440 return; 441 } 442 /* 443 * root directory vnode, if one 444 */ 445 if (cwdi.cwdi_rdir) 446 vtrans(cwdi.cwdi_rdir, RDIR, FREAD); 447 /* 448 * current working directory vnode 449 */ 450 vtrans(cwdi.cwdi_cdir, CDIR, FREAD); 451 #if 0 452 /* 453 * Disable for now, since p->p_tracep appears to point to a ktr_desc * 454 * ktrace vnode, if one 455 */ 456 if (p->p_tracep) 457 ftrans(p->p_tracep, TRACE); 458 #endif 459 /* 460 * open files 461 */ 462 #define FPSIZE (sizeof (fdfile_t *)) 463 ALLOC_OFILES(filed.fd_lastfile+1); 464 if (!KVM_READ(&filed.fd_dt->dt_ff, ofiles, 465 (filed.fd_lastfile+1) * FPSIZE)) { 466 dprintf("can't read file structures at %p for pid %d", 467 &filed.fd_dt->dt_ff, Pid); 468 return; 469 } 470 for (i = 0; i <= filed.fd_lastfile; i++) { 471 if (ofiles[i] == NULL) 472 continue; 473 ftrans(ofiles[i], i); 474 } 475 } 476 477 static void 478 ftrans(fdfile_t *fp, int i) 479 { 480 struct file file; 481 fdfile_t fdfile; 482 483 if (!KVM_READ(fp, &fdfile, sizeof(fdfile))) { 484 dprintf("can't read file %d at %p for pid %d", 485 i, fp, Pid); 486 return; 487 } 488 if (fdfile.ff_file == NULL) { 489 dprintf("null ff_file for %d at %p for pid %d", 490 i, fp, Pid); 491 return; 492 } 493 if (!KVM_READ(fdfile.ff_file, &file, sizeof(file))) { 494 dprintf("can't read file %d at %p for pid %d", 495 i, fdfile.ff_file, Pid); 496 return; 497 } 498 switch (file.f_type) { 499 case DTYPE_VNODE: 500 vtrans(file.f_data, i, file.f_flag); 501 break; 502 case DTYPE_SOCKET: 503 if (checkfile == 0) 504 socktrans(file.f_data, i); 505 break; 506 case DTYPE_PIPE: 507 if (checkfile == 0) 508 ptrans(&file, file.f_data, i); 509 break; 510 case DTYPE_MISC: 511 case DTYPE_KQUEUE: 512 case DTYPE_CRYPTO: 513 case DTYPE_MQUEUE: 514 case DTYPE_SEM: 515 if (checkfile == 0) 516 misctrans(&file, i); 517 break; 518 default: 519 dprintf("unknown file type %d for file %d of pid %d", 520 file.f_type, i, Pid); 521 break; 522 } 523 } 524 525 static const char dead[] = "dead"; 526 527 static const char * 528 vfilestat(struct vnode *vp, struct filestat *fsp) 529 { 530 const char *badtype = NULL; 531 532 if (vp->v_type == VNON) 533 badtype = "none"; 534 else if (vp->v_type == VBAD) 535 badtype = "bad"; 536 else 537 switch (vp->v_tag) { 538 case VT_NON: 539 badtype = dead; 540 break; 541 case VT_UFS: 542 case VT_LFS: 543 case VT_MFS: 544 if (!ufs_filestat(vp, fsp)) 545 badtype = "error"; 546 break; 547 case VT_MSDOSFS: 548 if (!msdosfs_filestat(vp, fsp)) 549 badtype = "error"; 550 break; 551 case VT_NFS: 552 if (!nfs_filestat(vp, fsp)) 553 badtype = "error"; 554 break; 555 case VT_EXT2FS: 556 if (!ext2fs_filestat(vp, fsp)) 557 badtype = "error"; 558 break; 559 case VT_ISOFS: 560 if (!isofs_filestat(vp, fsp)) 561 badtype = "error"; 562 break; 563 case VT_NTFS: 564 if (!ntfs_filestat(vp, fsp)) 565 badtype = "error"; 566 break; 567 case VT_PTYFS: 568 if (!ptyfs_filestat(vp, fsp)) 569 badtype = "error"; 570 break; 571 case VT_TMPFS: 572 if (!tmpfs_filestat(vp, fsp)) 573 badtype = "error"; 574 break; 575 case VT_NULL: 576 case VT_OVERLAY: 577 case VT_UMAP: 578 badtype = layer_filestat(vp, fsp); 579 break; 580 default: { 581 static char unknown[10]; 582 (void)snprintf(unknown, sizeof unknown, 583 "?(%x)", vp->v_tag); 584 badtype = unknown; 585 break; 586 } 587 } 588 return badtype; 589 } 590 591 static void 592 vtrans(struct vnode *vp, int i, int flag) 593 { 594 struct vnode vn; 595 struct filestat fst; 596 char mode[15], rw[3]; 597 const char *badtype, *filename; 598 599 filename = NULL; 600 if (!KVM_READ(vp, &vn, sizeof(struct vnode))) { 601 dprintf("can't read vnode at %p for pid %d", vp, Pid); 602 return; 603 } 604 badtype = vfilestat(&vn, &fst); 605 if (checkfile) { 606 int fsmatch = 0; 607 DEVS *d; 608 609 if (badtype && badtype != dead) 610 return; 611 for (d = devs; d != NULL; d = d->next) 612 if (d->fsid == fst.fsid) { 613 fsmatch = 1; 614 if (d->ino == fst.fileid) { 615 filename = d->name; 616 break; 617 } 618 } 619 if (fsmatch == 0 || (filename == NULL && fsflg == 0)) 620 return; 621 } 622 PREFIX(i); 623 if (badtype == dead) { 624 char buf[1024]; 625 (void)snprintb(buf, sizeof(buf), VNODE_FLAGBITS, 626 vn.v_iflag | vn.v_vflag | vn.v_uflag); 627 (void)printf(" flags %s\n", buf); 628 return; 629 } else if (badtype) { 630 (void)printf(" - - %10s -\n", badtype); 631 return; 632 } 633 if (nflg) 634 (void)printf(" %2llu,%-2llu", 635 (unsigned long long)major(fst.fsid), 636 (unsigned long long)minor(fst.fsid)); 637 else 638 (void)printf(" %-8s", getmnton(vn.v_mount)); 639 if (nflg) 640 (void)snprintf(mode, sizeof mode, "%o", fst.mode); 641 else 642 strmode(fst.mode, mode); 643 (void)printf(" %7"PRIu64" %*s", fst.fileid, nflg ? 5 : 10, mode); 644 switch (vn.v_type) { 645 case VBLK: 646 case VCHR: { 647 char *name; 648 649 if (nflg || ((name = devname(fst.rdev, vn.v_type == VCHR ? 650 S_IFCHR : S_IFBLK)) == NULL)) 651 (void)printf(" %s,%-2llu", 652 kdriver_search(vn.v_type, major(fst.rdev)), 653 (unsigned long long)minor(fst.rdev)); 654 else 655 (void)printf(" %6s", name); 656 break; 657 } 658 default: 659 (void)printf(" %6lld", (long long)fst.size); 660 } 661 rw[0] = '\0'; 662 if (flag & FREAD) 663 (void)strlcat(rw, "r", sizeof(rw)); 664 if (flag & FWRITE) 665 (void)strlcat(rw, "w", sizeof(rw)); 666 (void)printf(" %-2s", rw); 667 if (filename && !fsflg) 668 (void)printf(" %s", filename); 669 (void)putchar('\n'); 670 } 671 672 static int 673 ufs_filestat(struct vnode *vp, struct filestat *fsp) 674 { 675 struct inode inode; 676 struct ufsmount ufsmount; 677 union dinode { 678 struct ufs1_dinode dp1; 679 struct ufs2_dinode dp2; 680 } dip; 681 682 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { 683 dprintf("can't read inode at %p for pid %d", VTOI(vp), Pid); 684 return 0; 685 } 686 687 if (!KVM_READ(inode.i_ump, &ufsmount, sizeof (struct ufsmount))) { 688 dprintf("can't read ufsmount at %p for pid %d", inode.i_ump, Pid); 689 return 0; 690 } 691 692 switch (ufsmount.um_fstype) { 693 case UFS1: 694 if (!KVM_READ(inode.i_din.ffs1_din, &dip, 695 sizeof(struct ufs1_dinode))) { 696 dprintf("can't read dinode at %p for pid %d", 697 inode.i_din.ffs1_din, Pid); 698 return 0; 699 } 700 fsp->rdev = dip.dp1.di_rdev; 701 break; 702 case UFS2: 703 if (!KVM_READ(inode.i_din.ffs2_din, &dip, 704 sizeof(struct ufs2_dinode))) { 705 dprintf("can't read dinode at %p for pid %d", 706 inode.i_din.ffs2_din, Pid); 707 return 0; 708 } 709 fsp->rdev = dip.dp2.di_rdev; 710 break; 711 default: 712 dprintf("unknown ufs type %ld for pid %d", 713 ufsmount.um_fstype, Pid); 714 break; 715 } 716 fsp->fsid = inode.i_dev & 0xffff; 717 fsp->fileid = inode.i_number; 718 fsp->mode = (mode_t)inode.i_mode; 719 fsp->size = inode.i_size; 720 721 return 1; 722 } 723 724 static int 725 ext2fs_filestat(struct vnode *vp, struct filestat *fsp) 726 { 727 struct inode inode; 728 struct ext2fs_dinode dinode; 729 730 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { 731 dprintf("can't read inode at %p for pid %d", VTOI(vp), Pid); 732 return 0; 733 } 734 fsp->fsid = inode.i_dev & 0xffff; 735 fsp->fileid = inode.i_number; 736 737 if (!KVM_READ(inode.i_din.e2fs_din, &dinode, sizeof dinode)) { 738 dprintf("can't read ext2fs_dinode at %p for pid %d", 739 inode.i_din.e2fs_din, Pid); 740 return 0; 741 } 742 fsp->mode = dinode.e2di_mode; 743 fsp->size = dinode.e2di_size; 744 fsp->rdev = dinode.e2di_rdev; 745 746 return 1; 747 } 748 749 static int 750 nfs_filestat(struct vnode *vp, struct filestat *fsp) 751 { 752 struct nfsnode nfsnode; 753 struct vattr va; 754 755 if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) { 756 dprintf("can't read nfsnode at %p for pid %d", VTONFS(vp), 757 Pid); 758 return 0; 759 } 760 if (!KVM_READ(nfsnode.n_vattr, &va, sizeof(va))) { 761 dprintf("can't read vnode attributes at %p for pid %d", 762 nfsnode.n_vattr, Pid); 763 return 0; 764 } 765 fsp->fsid = va.va_fsid; 766 fsp->fileid = va.va_fileid; 767 fsp->size = nfsnode.n_size; 768 fsp->rdev = va.va_rdev; 769 fsp->mode = (mode_t)va.va_mode | getftype(vp->v_type); 770 771 return 1; 772 } 773 774 static int 775 msdosfs_filestat(struct vnode *vp, struct filestat *fsp) 776 { 777 struct denode de; 778 struct msdosfsmount mp; 779 780 if (!KVM_READ(VTONFS(vp), &de, sizeof(de))) { 781 dprintf("can't read denode at %p for pid %d", VTONFS(vp), 782 Pid); 783 return 0; 784 } 785 if (!KVM_READ(de.de_pmp, &mp, sizeof(mp))) { 786 dprintf("can't read mount struct at %p for pid %d", de.de_pmp, 787 Pid); 788 return 0; 789 } 790 791 fsp->fsid = de.de_dev & 0xffff; 792 fsp->fileid = 0; /* XXX see msdosfs_vptofh() for more info */ 793 fsp->size = de.de_FileSize; 794 fsp->rdev = 0; /* msdosfs doesn't support device files */ 795 fsp->mode = (0777 & mp.pm_mask) | getftype(vp->v_type); 796 return 1; 797 } 798 799 static const char * 800 layer_filestat(struct vnode *vp, struct filestat *fsp) 801 { 802 struct layer_node layer_node; 803 struct mount mount; 804 struct vnode vn; 805 const char *badtype; 806 807 if (!KVM_READ(VTOLAYER(vp), &layer_node, sizeof(layer_node))) { 808 dprintf("can't read layer_node at %p for pid %d", 809 VTOLAYER(vp), Pid); 810 return "error"; 811 } 812 if (!KVM_READ(vp->v_mount, &mount, sizeof(struct mount))) { 813 dprintf("can't read mount struct at %p for pid %d", 814 vp->v_mount, Pid); 815 return "error"; 816 } 817 vp = layer_node.layer_lowervp; 818 if (!KVM_READ(vp, &vn, sizeof(struct vnode))) { 819 dprintf("can't read vnode at %p for pid %d", vp, Pid); 820 return "error"; 821 } 822 if ((badtype = vfilestat(&vn, fsp)) == NULL) 823 fsp->fsid = mount.mnt_stat.f_fsidx.__fsid_val[0]; 824 return badtype; 825 } 826 827 static char * 828 getmnton(struct mount *m) 829 { 830 static struct mount mount; 831 static struct mtab { 832 struct mtab *next; 833 struct mount *m; 834 char mntonname[MNAMELEN]; 835 } *mhead = NULL; 836 struct mtab *mt; 837 838 for (mt = mhead; mt != NULL; mt = mt->next) 839 if (m == mt->m) 840 return mt->mntonname; 841 if (!KVM_READ(m, &mount, sizeof(struct mount))) { 842 warnx("can't read mount table at %p", m); 843 return NULL; 844 } 845 if ((mt = malloc(sizeof (struct mtab))) == NULL) { 846 err(1, "malloc(%u)", (unsigned int)sizeof(struct mtab)); 847 } 848 mt->m = m; 849 (void)memmove(&mt->mntonname[0], &mount.mnt_stat.f_mntonname[0], 850 MNAMELEN); 851 mt->next = mhead; 852 mhead = mt; 853 return mt->mntonname; 854 } 855 856 static const char * 857 inet_addrstr(char *buf, size_t len, const struct in_addr *a, uint16_t p) 858 { 859 char addr[256], serv[256]; 860 struct sockaddr_in sin; 861 const int niflags = nflg ? (NI_NUMERICHOST|NI_NUMERICSERV) : 0; 862 863 (void)memset(&sin, 0, sizeof(sin)); 864 sin.sin_family = AF_INET; 865 sin.sin_len = sizeof(sin); 866 sin.sin_addr = *a; 867 sin.sin_port = htons(p); 868 869 serv[0] = '\0'; 870 871 if (getnameinfo((struct sockaddr *)&sin, sin.sin_len, 872 addr, sizeof(addr), serv, sizeof(serv), niflags)) { 873 if (inet_ntop(AF_INET, a, addr, sizeof(addr)) == NULL) 874 strlcpy(addr, "invalid", sizeof(addr)); 875 } 876 877 if (serv[0] == '\0') 878 snprintf(serv, sizeof(serv), "%u", p); 879 880 if (a->s_addr == INADDR_ANY) { 881 if (p == 0) 882 buf[0] = '\0'; 883 else 884 snprintf(buf, len, "*:%s", serv); 885 return buf; 886 } 887 888 snprintf(buf, len, "%s:%s", addr, serv); 889 return buf; 890 } 891 892 #ifdef INET6 893 static const char * 894 inet6_addrstr(char *buf, size_t len, const struct in6_addr *a, uint16_t p) 895 { 896 char addr[256], serv[256]; 897 struct sockaddr_in6 sin6; 898 const int niflags = nflg ? (NI_NUMERICHOST|NI_NUMERICSERV) : 0; 899 900 (void)memset(&sin6, 0, sizeof(sin6)); 901 sin6.sin6_family = AF_INET6; 902 sin6.sin6_len = sizeof(sin6); 903 sin6.sin6_addr = *a; 904 sin6.sin6_port = htons(p); 905 906 if (IN6_IS_ADDR_LINKLOCAL(a) && 907 *(u_int16_t *)&sin6.sin6_addr.s6_addr[2] != 0) { 908 sin6.sin6_scope_id = 909 ntohs(*(uint16_t *)&sin6.sin6_addr.s6_addr[2]); 910 sin6.sin6_addr.s6_addr[2] = 0; 911 sin6.sin6_addr.s6_addr[3] = 0; 912 } 913 914 serv[0] = '\0'; 915 916 if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 917 addr, sizeof(addr), serv, sizeof(serv), niflags)) { 918 if (inet_ntop(AF_INET6, a, addr, sizeof(addr)) == NULL) 919 strlcpy(addr, "invalid", sizeof(addr)); 920 } 921 922 if (serv[0] == '\0') 923 snprintf(serv, sizeof(serv), "%u", p); 924 925 if (IN6_IS_ADDR_UNSPECIFIED(a)) { 926 if (p == 0) 927 buf[0] = '\0'; 928 else 929 snprintf(buf, len, "*:%s", serv); 930 return buf; 931 } 932 933 if (strchr(addr, ':') == NULL) 934 snprintf(buf, len, "%s:%s", addr, serv); 935 else 936 snprintf(buf, len, "[%s]:%s", addr, serv); 937 938 return buf; 939 } 940 #endif 941 942 static const char * 943 at_addrstr(char *buf, size_t len, const struct sockaddr_at *sat) 944 { 945 const struct netrange *nr = &sat->sat_range.r_netrange; 946 const struct at_addr *at = &sat->sat_addr; 947 char addr[64], phase[64], range[64]; 948 949 if (sat->sat_port || at->s_net || at->s_node) { 950 if (at->s_net || at->s_node) 951 snprintf(addr, sizeof(addr), "%u.%u:%u", 952 ntohs(at->s_net), at->s_node, sat->sat_port); 953 else 954 snprintf(addr, sizeof(addr), "*:%u", sat->sat_port); 955 } else 956 addr[0] = '\0'; 957 958 if (nr->nr_phase) 959 snprintf(phase, sizeof(phase), " phase %u", nr->nr_phase); 960 else 961 phase[0] = '\0'; 962 963 if (nr->nr_firstnet || nr->nr_lastnet) 964 snprintf(range, sizeof(range), " range [%u-%u]", 965 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet)); 966 else 967 range[0] = '\0'; 968 969 snprintf(buf, len, "%s%s%s", addr, phase, range); 970 return buf; 971 } 972 973 static void 974 socktrans(struct socket *sock, int i) 975 { 976 static const char *stypename[] = { 977 "unused", /* 0 */ 978 "stream", /* 1 */ 979 "dgram", /* 2 */ 980 "raw", /* 3 */ 981 "rdm", /* 4 */ 982 "seqpak" /* 5 */ 983 }; 984 #define STYPEMAX 5 985 struct socket so; 986 struct protosw proto; 987 struct domain dom; 988 struct inpcb inpcb; 989 #ifdef INET6 990 struct in6pcb in6pcb; 991 #endif 992 struct unpcb unpcb; 993 struct ddpcb ddpcb; 994 int len; 995 char dname[32]; 996 char lbuf[512], fbuf[512]; 997 PREFIX(i); 998 999 /* fill in socket */ 1000 if (!KVM_READ(sock, &so, sizeof(struct socket))) { 1001 dprintf("can't read sock at %p", sock); 1002 goto bad; 1003 } 1004 1005 /* fill in protosw entry */ 1006 if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) { 1007 dprintf("can't read protosw at %p", so.so_proto); 1008 goto bad; 1009 } 1010 1011 /* fill in domain */ 1012 if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) { 1013 dprintf("can't read domain at %p", proto.pr_domain); 1014 goto bad; 1015 } 1016 1017 if ((len = kvm_read(kd, (u_long)dom.dom_name, dname, 1018 sizeof(dname) - 1)) != sizeof(dname) -1) { 1019 dprintf("can't read domain name at %p", dom.dom_name); 1020 dname[0] = '\0'; 1021 } 1022 else 1023 dname[len] = '\0'; 1024 1025 if ((u_short)so.so_type > STYPEMAX) 1026 (void)printf("* %s ?%d", dname, so.so_type); 1027 else 1028 (void)printf("* %s %s", dname, stypename[so.so_type]); 1029 1030 /* 1031 * protocol specific formatting 1032 * 1033 * Try to find interesting things to print. For TCP, the interesting 1034 * thing is the address of the tcpcb, for UDP and others, just the 1035 * inpcb (socket pcb). For UNIX domain, its the address of the socket 1036 * pcb and the address of the connected pcb (if connected). Otherwise 1037 * just print the protocol number and address of the socket itself. 1038 * The idea is not to duplicate netstat, but to make available enough 1039 * information for further analysis. 1040 */ 1041 fbuf[0] = '\0'; 1042 lbuf[0] = '\0'; 1043 switch(dom.dom_family) { 1044 case AF_INET: 1045 getinetproto(proto.pr_protocol); 1046 switch (proto.pr_protocol) { 1047 case IPPROTO_TCP: 1048 case IPPROTO_UDP: 1049 if (so.so_pcb == NULL) 1050 break; 1051 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, 1052 sizeof(inpcb)) != sizeof(inpcb)) { 1053 dprintf("can't read inpcb at %p", so.so_pcb); 1054 goto bad; 1055 } 1056 inet_addrstr(lbuf, sizeof(lbuf), &inpcb.inp_laddr, 1057 ntohs(inpcb.inp_lport)); 1058 inet_addrstr(fbuf, sizeof(fbuf), &inpcb.inp_faddr, 1059 ntohs(inpcb.inp_fport)); 1060 break; 1061 default: 1062 break; 1063 } 1064 break; 1065 #ifdef INET6 1066 case AF_INET6: 1067 getinetproto(proto.pr_protocol); 1068 switch (proto.pr_protocol) { 1069 case IPPROTO_TCP: 1070 case IPPROTO_UDP: 1071 if (so.so_pcb == NULL) 1072 break; 1073 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&in6pcb, 1074 sizeof(in6pcb)) != sizeof(in6pcb)) { 1075 dprintf("can't read in6pcb at %p", so.so_pcb); 1076 goto bad; 1077 } 1078 inet6_addrstr(lbuf, sizeof(lbuf), &in6pcb.in6p_laddr, 1079 ntohs(in6pcb.in6p_lport)); 1080 inet6_addrstr(fbuf, sizeof(fbuf), &in6pcb.in6p_faddr, 1081 ntohs(in6pcb.in6p_fport)); 1082 break; 1083 default: 1084 break; 1085 } 1086 break; 1087 #endif 1088 case AF_LOCAL: 1089 /* print address of pcb and connected pcb */ 1090 if (so.so_pcb) { 1091 char shoconn[4], *cp; 1092 void *pcb[2]; 1093 size_t p = 0; 1094 1095 pcb[0] = so.so_pcb; 1096 1097 cp = shoconn; 1098 if (!(so.so_state & SS_CANTRCVMORE)) 1099 *cp++ = '<'; 1100 *cp++ = '-'; 1101 if (!(so.so_state & SS_CANTSENDMORE)) 1102 *cp++ = '>'; 1103 *cp = '\0'; 1104 again: 1105 if (kvm_read(kd, (u_long)pcb[p], (char *)&unpcb, 1106 sizeof(struct unpcb)) != sizeof(struct unpcb)){ 1107 dprintf("can't read unpcb at %p", so.so_pcb); 1108 goto bad; 1109 } 1110 1111 if (unpcb.unp_addr) { 1112 struct sockaddr_un *sun = 1113 malloc(unpcb.unp_addrlen); 1114 if (sun == NULL) 1115 err(1, "malloc(%zu)", 1116 unpcb.unp_addrlen); 1117 if (kvm_read(kd, (u_long)unpcb.unp_addr, 1118 sun, unpcb.unp_addrlen) != 1119 (ssize_t)unpcb.unp_addrlen) { 1120 dprintf("can't read sun at %p", 1121 unpcb.unp_addr); 1122 free(sun); 1123 } else { 1124 snprintf(fbuf, sizeof(fbuf), " %s %s %s", 1125 shoconn, sun->sun_path, 1126 p == 0 ? "[creat]" : "[using]"); 1127 free(sun); 1128 break; 1129 } 1130 } 1131 if (unpcb.unp_conn) { 1132 if (p == 0) { 1133 pcb[++p] = unpcb.unp_conn; 1134 goto again; 1135 } else 1136 snprintf(fbuf, sizeof(fbuf), 1137 " %p %s %p", pcb[0], shoconn, 1138 pcb[1]); 1139 } 1140 } 1141 break; 1142 case AF_APPLETALK: 1143 getatproto(proto.pr_protocol); 1144 if (so.so_pcb) { 1145 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&ddpcb, 1146 sizeof(ddpcb)) != sizeof(ddpcb)){ 1147 dprintf("can't read ddpcb at %p", so.so_pcb); 1148 goto bad; 1149 } 1150 at_addrstr(fbuf, sizeof(fbuf), &ddpcb.ddp_fsat); 1151 at_addrstr(lbuf, sizeof(lbuf), &ddpcb.ddp_lsat); 1152 } 1153 break; 1154 default: 1155 /* print protocol number and socket address */ 1156 snprintf(fbuf, sizeof(fbuf), " %d %jx", proto.pr_protocol, 1157 (uintmax_t)(uintptr_t)sock); 1158 break; 1159 } 1160 if (fbuf[0] || lbuf[0]) 1161 printf(" %s%s%s", fbuf, (fbuf[0] && lbuf[0]) ? " <-> " : "", 1162 lbuf); 1163 else if (so.so_pcb) 1164 printf(" %jx", (uintmax_t)(uintptr_t)so.so_pcb); 1165 (void)printf("\n"); 1166 return; 1167 bad: 1168 (void)printf("* error\n"); 1169 } 1170 1171 static void 1172 ptrans(struct file *fp, struct pipe *cpipe, int i) 1173 { 1174 struct pipe cp; 1175 1176 PREFIX(i); 1177 1178 /* fill in pipe */ 1179 if (!KVM_READ(cpipe, &cp, sizeof(struct pipe))) { 1180 dprintf("can't read pipe at %p", cpipe); 1181 goto bad; 1182 } 1183 1184 /* pipe descriptor is either read or write, never both */ 1185 (void)printf("* pipe %p %s %p %s%s%s", cpipe, 1186 (fp->f_flag & FWRITE) ? "->" : "<-", 1187 cp.pipe_peer, 1188 (fp->f_flag & FWRITE) ? "w" : "r", 1189 (fp->f_flag & FNONBLOCK) ? "n" : "", 1190 (cp.pipe_state & PIPE_ASYNC) ? "a" : ""); 1191 (void)printf("\n"); 1192 return; 1193 bad: 1194 (void)printf("* error\n"); 1195 } 1196 1197 static void 1198 misctrans(struct file *file, int i) 1199 { 1200 1201 PREFIX(i); 1202 pmisc(file, dtypes[file->f_type]); 1203 } 1204 1205 /* 1206 * getinetproto -- 1207 * print name of protocol number 1208 */ 1209 static void 1210 getinetproto(int number) 1211 { 1212 const char *cp; 1213 1214 switch (number) { 1215 case IPPROTO_IP: 1216 cp = "ip"; break; 1217 case IPPROTO_ICMP: 1218 cp ="icmp"; break; 1219 case IPPROTO_GGP: 1220 cp ="ggp"; break; 1221 case IPPROTO_TCP: 1222 cp ="tcp"; break; 1223 case IPPROTO_EGP: 1224 cp ="egp"; break; 1225 case IPPROTO_PUP: 1226 cp ="pup"; break; 1227 case IPPROTO_UDP: 1228 cp ="udp"; break; 1229 case IPPROTO_IDP: 1230 cp ="idp"; break; 1231 case IPPROTO_RAW: 1232 cp ="raw"; break; 1233 case IPPROTO_ICMPV6: 1234 cp ="icmp6"; break; 1235 default: 1236 (void)printf(" %d", number); 1237 return; 1238 } 1239 (void)printf(" %s", cp); 1240 } 1241 1242 /* 1243 * getatproto -- 1244 * print name of protocol number 1245 */ 1246 static void 1247 getatproto(int number) 1248 { 1249 const char *cp; 1250 1251 switch (number) { 1252 case ATPROTO_DDP: 1253 cp = "ddp"; break; 1254 case ATPROTO_AARP: 1255 cp ="aarp"; break; 1256 default: 1257 (void)printf(" %d", number); 1258 return; 1259 } 1260 (void)printf(" %s", cp); 1261 } 1262 1263 static int 1264 getfname(const char *filename) 1265 { 1266 struct stat statbuf; 1267 DEVS *cur; 1268 1269 if (stat(filename, &statbuf)) { 1270 warn("stat(%s)", filename); 1271 return 0; 1272 } 1273 if ((cur = malloc(sizeof(*cur))) == NULL) { 1274 err(1, "malloc(%zu)", sizeof(*cur)); 1275 } 1276 cur->next = devs; 1277 devs = cur; 1278 1279 cur->ino = statbuf.st_ino; 1280 cur->fsid = statbuf.st_dev & 0xffff; 1281 cur->name = filename; 1282 return 1; 1283 } 1284 1285 mode_t 1286 getftype(enum vtype v_type) 1287 { 1288 mode_t ftype; 1289 1290 switch (v_type) { 1291 case VREG: 1292 ftype = S_IFREG; 1293 break; 1294 case VDIR: 1295 ftype = S_IFDIR; 1296 break; 1297 case VBLK: 1298 ftype = S_IFBLK; 1299 break; 1300 case VCHR: 1301 ftype = S_IFCHR; 1302 break; 1303 case VLNK: 1304 ftype = S_IFLNK; 1305 break; 1306 case VSOCK: 1307 ftype = S_IFSOCK; 1308 break; 1309 case VFIFO: 1310 ftype = S_IFIFO; 1311 break; 1312 default: 1313 ftype = 0; 1314 break; 1315 }; 1316 1317 return ftype; 1318 } 1319 1320 static void 1321 usage(void) 1322 { 1323 (void)fprintf(stderr, "Usage: %s [-fnv] [-p pid] [-u user] " 1324 "[-N system] [-M core] [file ...]\n", getprogname()); 1325 exit(1); 1326 } 1327