1 /* $OpenBSD: fstat.c,v 1.57 2006/06/19 22:31:20 deraadt 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 #ifndef lint 33 static char copyright[] = 34 "@(#) Copyright (c) 1988, 1993\n\ 35 The Regents of the University of California. All rights reserved.\n"; 36 #endif /* not lint */ 37 38 #ifndef lint 39 /*static char sccsid[] = "from: @(#)fstat.c 8.1 (Berkeley) 6/6/93";*/ 40 static char *rcsid = "$OpenBSD: fstat.c,v 1.57 2006/06/19 22:31:20 deraadt Exp $"; 41 #endif /* not lint */ 42 43 #include <sys/param.h> 44 #include <sys/time.h> 45 #include <sys/proc.h> 46 #include <sys/user.h> 47 #include <sys/stat.h> 48 #include <sys/vnode.h> 49 #include <sys/socket.h> 50 #include <sys/socketvar.h> 51 #include <sys/domain.h> 52 #include <sys/protosw.h> 53 #include <sys/event.h> 54 #include <sys/eventvar.h> 55 #include <sys/unpcb.h> 56 #include <sys/sysctl.h> 57 #include <sys/filedesc.h> 58 #define _KERNEL 59 #include <sys/mount.h> 60 #include <crypto/cryptodev.h> 61 #include <dev/systrace.h> 62 #include <sys/file.h> 63 #include <ufs/ufs/quota.h> 64 #include <ufs/ufs/inode.h> 65 #undef _KERNEL 66 #define NFS 67 #include <nfs/nfsproto.h> 68 #include <nfs/rpcv2.h> 69 #include <nfs/nfs.h> 70 #include <nfs/nfsnode.h> 71 #undef NFS 72 73 #include <xfs/xfs_config.h> 74 #include <xfs/xfs_node.h> 75 76 #include <net/route.h> 77 #include <netinet/in.h> 78 #include <netinet/in_systm.h> 79 #include <netinet/ip.h> 80 #include <netinet/in_pcb.h> 81 82 #ifdef INET6 83 #include <netinet/ip6.h> 84 #include <netinet6/ip6_var.h> 85 #endif 86 87 #include <netdb.h> 88 #include <arpa/inet.h> 89 90 #include <sys/pipe.h> 91 92 #include <ctype.h> 93 #include <errno.h> 94 #include <kvm.h> 95 #include <limits.h> 96 #include <nlist.h> 97 #include <paths.h> 98 #include <pwd.h> 99 #include <stdio.h> 100 #include <stdlib.h> 101 #include <string.h> 102 #include <unistd.h> 103 #include <netdb.h> 104 #include <err.h> 105 #include "fstat.h" 106 107 #define TEXT -1 108 #define CDIR -2 109 #define RDIR -3 110 #define TRACE -4 111 112 typedef struct devs { 113 struct devs *next; 114 long fsid; 115 ino_t ino; 116 char *name; 117 } DEVS; 118 DEVS *devs; 119 120 int fsflg; /* show files on same filesystem as file(s) argument */ 121 int pflg; /* show files open by a particular pid */ 122 int uflg; /* show files open by a particular (effective) user */ 123 int checkfile; /* true if restricting to particular files or filesystems */ 124 int nflg; /* (numerical) display f.s. and rdev as dev_t */ 125 int oflg; /* display file offset */ 126 int sflg; /* display file xfer/bytes counters */ 127 int vflg; /* display errors in locating kernel data objects etc... */ 128 129 struct file **ofiles; /* buffer of pointers to file structures */ 130 int maxfiles; 131 #define ALLOC_OFILES(d) \ 132 if ((d) > maxfiles) { \ 133 free(ofiles); \ 134 ofiles = malloc((d) * sizeof(struct file *)); \ 135 if (ofiles == NULL) \ 136 err(1, "malloc"); \ 137 maxfiles = (d); \ 138 } 139 140 /* 141 * a kvm_read that returns true if everything is read 142 */ 143 #define KVM_READ(kaddr, paddr, len) \ 144 (kvm_read(kd, (u_long)(kaddr), (void *)(paddr), (len)) == (len)) 145 146 kvm_t *kd; 147 148 int ufs_filestat(struct vnode *, struct filestat *); 149 int ext2fs_filestat(struct vnode *, struct filestat *); 150 int isofs_filestat(struct vnode *, struct filestat *); 151 int msdos_filestat(struct vnode *, struct filestat *); 152 int nfs_filestat(struct vnode *, struct filestat *); 153 int xfs_filestat(struct vnode *, struct filestat *); 154 void dofiles(struct kinfo_proc2 *); 155 void getinetproto(int); 156 void usage(void); 157 int getfname(char *); 158 void socktrans(struct socket *, int, struct file *); 159 void vtrans(struct vnode *, int, int, struct file *); 160 void pipetrans(struct pipe *, int, struct file *); 161 void kqueuetrans(struct kqueue *, int, struct file *); 162 void cryptotrans(void *, int, struct file *); 163 void systracetrans(struct fsystrace *, int, struct file *); 164 char *getmnton(struct mount *); 165 const char *inet6_addrstr(struct in6_addr *); 166 167 int 168 main(int argc, char *argv[]) 169 { 170 extern char *optarg; 171 extern int optind; 172 struct passwd *passwd; 173 struct kinfo_proc2 *p, *plast; 174 int arg, ch, what; 175 char *memf, *nlistf; 176 char buf[_POSIX2_LINE_MAX]; 177 int cnt; 178 gid_t gid; 179 180 arg = 0; 181 what = KERN_PROC_ALL; 182 nlistf = memf = NULL; 183 oflg = 0; 184 while ((ch = getopt(argc, argv, "fnop:su:vN:M:")) != -1) 185 switch((char)ch) { 186 case 'f': 187 fsflg = 1; 188 break; 189 case 'M': 190 memf = optarg; 191 break; 192 case 'N': 193 nlistf = optarg; 194 break; 195 case 'n': 196 nflg = 1; 197 break; 198 case 'o': 199 oflg = 1; 200 break; 201 case 'p': 202 if (pflg++) 203 usage(); 204 if (!isdigit(*optarg)) { 205 warnx( "-p requires a process id"); 206 usage(); 207 } 208 what = KERN_PROC_PID; 209 arg = atoi(optarg); 210 break; 211 case 's': 212 sflg = 1; 213 break; 214 case 'u': 215 if (uflg++) 216 usage(); 217 if (!(passwd = getpwnam(optarg))) 218 errx(1, "%s: unknown uid", optarg); 219 what = KERN_PROC_UID; 220 arg = passwd->pw_uid; 221 break; 222 case 'v': 223 vflg = 1; 224 break; 225 default: 226 usage(); 227 } 228 229 /* 230 * Discard setgid privileges if not the running kernel so that bad 231 * guys can't print interesting stuff from kernel memory. 232 */ 233 gid = getgid(); 234 if (nlistf != NULL || memf != NULL) 235 if (setresgid(gid, gid, gid) == -1) 236 err(1, "setresgid"); 237 238 if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) 239 errx(1, "%s", buf); 240 241 if (nlistf == NULL && memf == NULL) 242 if (setresgid(gid, gid, gid) == -1) 243 err(1, "setresgid"); 244 245 if (*(argv += optind)) { 246 for (; *argv; ++argv) { 247 if (getfname(*argv)) 248 checkfile = 1; 249 } 250 if (!checkfile) /* file(s) specified, but none accessible */ 251 exit(1); 252 } 253 254 ALLOC_OFILES(256); /* reserve space for file pointers */ 255 256 if (fsflg && !checkfile) { 257 /* -f with no files means use wd */ 258 if (getfname(".") == 0) 259 exit(1); 260 checkfile = 1; 261 } 262 263 if ((p = kvm_getproc2(kd, what, arg, sizeof(*p), &cnt)) == NULL) 264 errx(1, "%s", kvm_geterr(kd)); 265 if (nflg) 266 printf("%s", 267 "USER CMD PID FD DEV INUM MODE R/W DV|SZ"); 268 else 269 printf("%s", 270 "USER CMD PID FD MOUNT INUM MODE R/W DV|SZ"); 271 if (oflg) 272 printf("%s", ":OFFSET "); 273 if (checkfile && fsflg == 0) 274 printf(" NAME"); 275 if (sflg) 276 printf(" XFERS KBYTES"); 277 putchar('\n'); 278 279 for (plast = &p[cnt]; p < plast; ++p) { 280 if (p->p_stat == SZOMB) 281 continue; 282 dofiles(p); 283 } 284 exit(0); 285 } 286 287 char *Uname, *Comm; 288 pid_t Pid; 289 290 #define PREFIX(i) do { \ 291 printf("%-8.8s %-10s %5ld", Uname, Comm, (long)Pid); \ 292 switch(i) { \ 293 case TEXT: \ 294 printf(" text"); \ 295 break; \ 296 case CDIR: \ 297 printf(" wd"); \ 298 break; \ 299 case RDIR: \ 300 printf(" root"); \ 301 break; \ 302 case TRACE: \ 303 printf(" tr"); \ 304 break; \ 305 default: \ 306 printf(" %4d", i); \ 307 break; \ 308 } \ 309 } while (0) 310 311 /* 312 * print open files attributed to this process 313 */ 314 void 315 dofiles(struct kinfo_proc2 *kp) 316 { 317 int i; 318 struct file file; 319 struct filedesc0 filed0; 320 #define filed filed0.fd_fd 321 322 Uname = user_from_uid(kp->p_uid, 0); 323 Pid = kp->p_pid; 324 Comm = kp->p_comm; 325 326 if (kp->p_fd == 0) 327 return; 328 if (!KVM_READ(kp->p_fd, &filed0, sizeof (filed0))) { 329 dprintf("can't read filedesc at %p for pid %ld", 330 (void *)(u_long)kp->p_fd, (long)Pid); 331 return; 332 } 333 if (filed.fd_nfiles < 0 || filed.fd_lastfile >= filed.fd_nfiles || 334 filed.fd_freefile > filed.fd_lastfile + 1) { 335 dprintf("filedesc corrupted at %p for pid %ld", 336 (void *)(u_long)kp->p_fd, (long)Pid); 337 return; 338 } 339 /* 340 * root directory vnode, if one 341 */ 342 if (filed.fd_rdir) 343 vtrans(filed.fd_rdir, RDIR, FREAD, NULL); 344 /* 345 * current working directory vnode 346 */ 347 vtrans(filed.fd_cdir, CDIR, FREAD, NULL); 348 349 /* 350 * ktrace vnode, if one 351 */ 352 if (kp->p_tracep) 353 vtrans((struct vnode *)(u_long)kp->p_tracep, TRACE, FREAD|FWRITE, NULL); 354 /* 355 * open files 356 */ 357 #define FPSIZE (sizeof (struct file *)) 358 ALLOC_OFILES(filed.fd_lastfile+1); 359 if (filed.fd_nfiles > NDFILE) { 360 if (!KVM_READ(filed.fd_ofiles, ofiles, 361 (filed.fd_lastfile+1) * FPSIZE)) { 362 dprintf("can't read file structures at %p for pid %ld", 363 filed.fd_ofiles, (long)Pid); 364 return; 365 } 366 } else 367 bcopy(filed0.fd_dfiles, ofiles, (filed.fd_lastfile+1) * FPSIZE); 368 for (i = 0; i <= filed.fd_lastfile; i++) { 369 if (ofiles[i] == NULL) 370 continue; 371 if (!KVM_READ(ofiles[i], &file, sizeof (struct file))) { 372 dprintf("can't read file %d at %p for pid %ld", 373 i, ofiles[i], (long)Pid); 374 continue; 375 } 376 if (file.f_type == DTYPE_VNODE) 377 vtrans((struct vnode *)file.f_data, i, file.f_flag, 378 &file); 379 else if (file.f_type == DTYPE_SOCKET) { 380 if (checkfile == 0) 381 socktrans((struct socket *)file.f_data, i, 382 &file); 383 } else if (file.f_type == DTYPE_PIPE) { 384 if (checkfile == 0) 385 pipetrans((struct pipe *)file.f_data, i, &file); 386 } else if (file.f_type == DTYPE_KQUEUE) { 387 if (checkfile == 0) 388 kqueuetrans((struct kqueue *)file.f_data, i, 389 &file); 390 } else if (file.f_type == DTYPE_CRYPTO) { 391 if (checkfile == 0) 392 cryptotrans(file.f_data, i, &file); 393 } else if (file.f_type == DTYPE_SYSTRACE) { 394 if (checkfile == 0) 395 systracetrans((struct fsystrace *)file.f_data, 396 i, &file); 397 } else { 398 dprintf("unknown file type %d for file %d of pid %ld", 399 file.f_type, i, (long)Pid); 400 } 401 } 402 } 403 404 void 405 vtrans(struct vnode *vp, int i, int flag, struct file *fp) 406 { 407 struct vnode vn; 408 struct filestat fst; 409 char rw[3], mode[17]; 410 char *badtype = NULL, *filename; 411 412 filename = badtype = NULL; 413 if (!KVM_READ(vp, &vn, sizeof (struct vnode))) { 414 dprintf("can't read vnode at %p for pid %ld", vp, (long)Pid); 415 return; 416 } 417 if (vn.v_type == VNON || vn.v_tag == VT_NON) 418 badtype = "none"; 419 else if (vn.v_type == VBAD) 420 badtype = "bad"; 421 else 422 switch (vn.v_tag) { 423 case VT_UFS: 424 case VT_MFS: 425 if (!ufs_filestat(&vn, &fst)) 426 badtype = "error"; 427 break; 428 case VT_NFS: 429 if (!nfs_filestat(&vn, &fst)) 430 badtype = "error"; 431 break; 432 case VT_EXT2FS: 433 if (!ext2fs_filestat(&vn, &fst)) 434 badtype = "error"; 435 break; 436 case VT_ISOFS: 437 if (!isofs_filestat(&vn, &fst)) 438 badtype = "error"; 439 break; 440 case VT_MSDOSFS: 441 if (!msdos_filestat(&vn, &fst)) 442 badtype = "error"; 443 break; 444 case VT_XFS: 445 if (!xfs_filestat(&vn, &fst)) 446 badtype = "error"; 447 break; 448 default: { 449 static char unknown[30]; 450 snprintf(badtype = unknown, sizeof unknown, 451 "?(%x)", vn.v_tag); 452 break; 453 } 454 } 455 if (checkfile) { 456 int fsmatch = 0; 457 DEVS *d; 458 459 if (badtype) 460 return; 461 for (d = devs; d != NULL; d = d->next) 462 if (d->fsid == fst.fsid) { 463 fsmatch = 1; 464 if (d->ino == fst.fileid) { 465 filename = d->name; 466 break; 467 } 468 } 469 if (fsmatch == 0 || (filename == NULL && fsflg == 0)) 470 return; 471 } 472 PREFIX(i); 473 if (badtype) { 474 (void)printf(" - - %10s -\n", badtype); 475 return; 476 } 477 if (nflg) 478 (void)printf(" %2ld,%-2ld", (long)major(fst.fsid), 479 (long)minor(fst.fsid)); 480 else 481 (void)printf(" %-8s", getmnton(vn.v_mount)); 482 if (nflg) 483 (void)snprintf(mode, sizeof mode, "%o", fst.mode); 484 else 485 strmode(fst.mode, mode); 486 (void)printf(" %8ld %11s", fst.fileid, mode); 487 rw[0] = '\0'; 488 if (flag & FREAD) 489 strlcat(rw, "r", sizeof rw); 490 if (flag & FWRITE) 491 strlcat(rw, "w", sizeof rw); 492 printf(" %2s", rw); 493 switch (vn.v_type) { 494 case VBLK: 495 case VCHR: { 496 char *name; 497 498 if (nflg || ((name = devname(fst.rdev, vn.v_type == VCHR ? 499 S_IFCHR : S_IFBLK)) == NULL)) 500 printf(" %2d,%-3d", major(fst.rdev), minor(fst.rdev)); 501 else 502 printf(" %7s", name); 503 if (oflg) 504 printf(" "); 505 break; 506 } 507 default: 508 printf(" %8lld", (long long)fst.size); 509 if (oflg) 510 printf(":%-8lld", (long long)(fp? fp->f_offset : 0)); 511 } 512 if (sflg) 513 printf(" %8lld %8lld", 514 (long long)(fp? fp->f_rxfer + fp->f_wxfer : 0), 515 (long long)(fp? fp->f_rbytes + fp->f_wbytes : 0) / 1024); 516 if (filename && !fsflg) 517 printf(" %s", filename); 518 putchar('\n'); 519 } 520 521 int 522 ufs_filestat(struct vnode *vp, struct filestat *fsp) 523 { 524 struct inode inode; 525 struct ufs1_dinode di1; 526 527 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { 528 dprintf("can't read inode at %p for pid %ld", 529 VTOI(vp), (long)Pid); 530 return 0; 531 } 532 533 if (!KVM_READ(inode.i_din1, &di1, sizeof(struct ufs1_dinode))) { 534 dprintf("can't read dinode at %p for pid %ld", 535 inode.i_din1, (long)Pid); 536 return (0); 537 } 538 539 inode.i_din1 = &di1; 540 541 fsp->fsid = inode.i_dev & 0xffff; 542 fsp->fileid = (long)inode.i_number; 543 fsp->mode = inode.i_ffs1_mode; 544 fsp->size = inode.i_ffs1_size; 545 fsp->rdev = inode.i_ffs1_rdev; 546 547 return 1; 548 } 549 550 int 551 ext2fs_filestat(struct vnode *vp, struct filestat *fsp) 552 { 553 struct inode inode; 554 struct ext2fs_dinode e2di; 555 556 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { 557 dprintf("can't read inode at %p for pid %ld", 558 VTOI(vp), (long)Pid); 559 return 0; 560 } 561 562 if (!KVM_READ(inode.i_e2din, &e2di, sizeof(struct ext2fs_dinode))) { 563 dprintf("can't read dinode at %p for pid %ld", 564 inode.i_e2din, (long)Pid); 565 return (0); 566 } 567 568 inode.i_e2din = &e2di; 569 570 fsp->fsid = inode.i_dev & 0xffff; 571 fsp->fileid = (long)inode.i_number; 572 fsp->mode = inode.i_e2fs_mode; 573 fsp->size = inode.i_e2fs_size; 574 fsp->rdev = 0; /* XXX */ 575 576 return 1; 577 } 578 579 int 580 msdos_filestat(struct vnode *vp, struct filestat *fsp) 581 { 582 #if 0 583 struct inode inode; 584 585 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { 586 dprintf("can't read inode at %p for pid %ld", 587 VTOI(vp), (long)Pid); 588 return 0; 589 } 590 fsp->fsid = inode.i_dev & 0xffff; 591 fsp->fileid = (long)inode.i_number; 592 fsp->mode = inode.i_e2fs_mode; 593 fsp->size = inode.i_e2fs_size; 594 fsp->rdev = 0; /* XXX */ 595 #endif 596 597 return 1; 598 } 599 600 int 601 nfs_filestat(struct vnode *vp, struct filestat *fsp) 602 { 603 struct nfsnode nfsnode; 604 mode_t mode; 605 606 if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) { 607 dprintf("can't read nfsnode at %p for pid %ld", 608 VTONFS(vp), (long)Pid); 609 return 0; 610 } 611 fsp->fsid = nfsnode.n_vattr.va_fsid; 612 fsp->fileid = nfsnode.n_vattr.va_fileid; 613 fsp->size = nfsnode.n_size; 614 fsp->rdev = nfsnode.n_vattr.va_rdev; 615 mode = (mode_t)nfsnode.n_vattr.va_mode; 616 switch (vp->v_type) { 617 case VREG: 618 mode |= S_IFREG; 619 break; 620 case VDIR: 621 mode |= S_IFDIR; 622 break; 623 case VBLK: 624 mode |= S_IFBLK; 625 break; 626 case VCHR: 627 mode |= S_IFCHR; 628 break; 629 case VLNK: 630 mode |= S_IFLNK; 631 break; 632 case VSOCK: 633 mode |= S_IFSOCK; 634 break; 635 case VFIFO: 636 mode |= S_IFIFO; 637 break; 638 default: 639 break; 640 } 641 fsp->mode = mode; 642 643 return 1; 644 } 645 646 int 647 xfs_filestat(struct vnode *vp, struct filestat *fsp) 648 { 649 struct xfs_node xfs_node; 650 651 if (!KVM_READ(VNODE_TO_XNODE(vp), &xfs_node, sizeof (xfs_node))) { 652 dprintf("can't read xfs_node at %p for pid %ld", 653 VTOI(vp), (long)Pid); 654 return 0; 655 } 656 fsp->fsid = xfs_node.attr.va_fsid; 657 fsp->fileid = (long)xfs_node.attr.va_fileid; 658 fsp->mode = xfs_node.attr.va_mode; 659 fsp->size = xfs_node.attr.va_size; 660 fsp->rdev = xfs_node.attr.va_rdev; 661 662 return 1; 663 } 664 665 char * 666 getmnton(struct mount *m) 667 { 668 static struct mount mount; 669 static struct mtab { 670 struct mtab *next; 671 struct mount *m; 672 char mntonname[MNAMELEN]; 673 } *mhead = NULL; 674 struct mtab *mt; 675 676 for (mt = mhead; mt != NULL; mt = mt->next) 677 if (m == mt->m) 678 return (mt->mntonname); 679 if (!KVM_READ(m, &mount, sizeof(struct mount))) { 680 warn("can't read mount table at %p", m); 681 return (NULL); 682 } 683 if ((mt = malloc(sizeof (struct mtab))) == NULL) 684 err(1, "malloc"); 685 mt->m = m; 686 bcopy(&mount.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN); 687 mt->next = mhead; 688 mhead = mt; 689 return (mt->mntonname); 690 } 691 692 void 693 pipetrans(struct pipe *pipe, int i, struct file *fp) 694 { 695 struct pipe pi; 696 void *maxaddr; 697 698 PREFIX(i); 699 700 printf(" "); 701 702 /* fill in socket */ 703 if (!KVM_READ(pipe, &pi, sizeof(struct pipe))) { 704 dprintf("can't read pipe at %p", pipe); 705 goto bad; 706 } 707 708 /* 709 * We don't have enough space to fit both peer and own address, so 710 * we select the higher address so both ends of the pipe have the 711 * same visible addr. (it's the higher address because when the other 712 * end closes, it becomes 0) 713 */ 714 maxaddr = MAX(pipe, pi.pipe_peer); 715 716 printf("pipe %p state: %s%s%s", maxaddr, 717 (pi.pipe_state & PIPE_WANTR) ? "R" : "", 718 (pi.pipe_state & PIPE_WANTW) ? "W" : "", 719 (pi.pipe_state & PIPE_EOF) ? "E" : ""); 720 if (sflg) 721 printf("\t%8lld %8lld", 722 (long long)(fp? fp->f_rxfer + fp->f_wxfer : 0), 723 (long long)(fp? fp->f_rbytes + fp->f_wbytes : 0) / 1024); 724 printf("\n"); 725 return; 726 bad: 727 printf("* error\n"); 728 } 729 730 void 731 kqueuetrans(struct kqueue *kq, int i, struct file *fp) 732 { 733 struct kqueue kqi; 734 735 PREFIX(i); 736 737 printf(" "); 738 739 /* fill it in */ 740 if (!KVM_READ(kq, &kqi, sizeof(struct kqueue))) { 741 dprintf("can't read kqueue at %p", kq); 742 goto bad; 743 } 744 745 printf("kqueue %p %d state: %s%s\n", kq, kqi.kq_count, 746 (kqi.kq_state & KQ_SEL) ? "S" : "", 747 (kqi.kq_state & KQ_SLEEP) ? "W" : ""); 748 return; 749 bad: 750 printf("* error\n"); 751 } 752 753 void 754 cryptotrans(void *f, int i, struct file *fp) 755 { 756 PREFIX(i); 757 758 printf(" "); 759 760 printf("crypto %p\n", f); 761 } 762 763 void 764 systracetrans(struct fsystrace *f, int i, struct file *fp) 765 { 766 struct fsystrace fi; 767 768 PREFIX(i); 769 770 printf(" "); 771 772 /* fill it in */ 773 if (!KVM_READ(f, &fi, sizeof(fi))) { 774 dprintf("can't read fsystrace at %p", f); 775 goto bad; 776 } 777 778 printf("systrace %p npol %d\n", f, fi.npolicies); 779 return; 780 bad: 781 printf("* error\n"); 782 } 783 784 #ifdef INET6 785 const char * 786 inet6_addrstr(struct in6_addr *p) 787 { 788 struct sockaddr_in6 sin6; 789 static char hbuf[NI_MAXHOST]; 790 const int niflags = NI_NUMERICHOST; 791 792 memset(&sin6, 0, sizeof(sin6)); 793 sin6.sin6_family = AF_INET6; 794 sin6.sin6_len = sizeof(struct sockaddr_in6); 795 sin6.sin6_addr = *p; 796 if (IN6_IS_ADDR_LINKLOCAL(p) && 797 *(u_int16_t *)&sin6.sin6_addr.s6_addr[2] != 0) { 798 sin6.sin6_scope_id = 799 ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); 800 sin6.sin6_addr.s6_addr[2] = sin6.sin6_addr.s6_addr[3] = 0; 801 } 802 803 if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 804 hbuf, sizeof(hbuf), NULL, 0, niflags)) 805 return "invalid"; 806 807 return hbuf; 808 } 809 #endif 810 811 void 812 socktrans(struct socket *sock, int i, struct file *fp) 813 { 814 static char *stypename[] = { 815 "unused", /* 0 */ 816 "stream", /* 1 */ 817 "dgram", /* 2 */ 818 "raw", /* 3 */ 819 "rdm", /* 4 */ 820 "seqpak" /* 5 */ 821 }; 822 #define STYPEMAX 5 823 struct socket so; 824 struct protosw proto; 825 struct domain dom; 826 struct inpcb inpcb; 827 struct unpcb unpcb; 828 int len; 829 char dname[32]; 830 #ifdef INET6 831 char xaddrbuf[NI_MAXHOST + 2]; 832 #endif 833 834 PREFIX(i); 835 836 /* fill in socket */ 837 if (!KVM_READ(sock, &so, sizeof(struct socket))) { 838 dprintf("can't read sock at %p", sock); 839 goto bad; 840 } 841 842 /* fill in protosw entry */ 843 if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) { 844 dprintf("can't read protosw at %p", so.so_proto); 845 goto bad; 846 } 847 848 /* fill in domain */ 849 if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) { 850 dprintf("can't read domain at %p", proto.pr_domain); 851 goto bad; 852 } 853 854 if ((len = kvm_read(kd, (u_long)dom.dom_name, dname, 855 sizeof(dname) - 1)) != sizeof(dname) -1) { 856 dprintf("can't read domain name at %p", dom.dom_name); 857 dname[0] = '\0'; 858 } else 859 dname[len] = '\0'; 860 861 if ((u_short)so.so_type > STYPEMAX) 862 printf("* %s ?%d", dname, so.so_type); 863 else 864 printf("* %s %s", dname, stypename[so.so_type]); 865 866 /* 867 * protocol specific formatting 868 * 869 * Try to find interesting things to print. For tcp, the interesting 870 * thing is the address of the tcpcb, for udp and others, just the 871 * inpcb (socket pcb). For unix domain, its the address of the socket 872 * pcb and the address of the connected pcb (if connected). Otherwise 873 * just print the protocol number and address of the socket itself. 874 * The idea is not to duplicate netstat, but to make available enough 875 * information for further analysis. 876 */ 877 switch(dom.dom_family) { 878 case AF_INET: 879 getinetproto(proto.pr_protocol); 880 if (proto.pr_protocol == IPPROTO_TCP) { 881 if (so.so_pcb == NULL) 882 break; 883 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, 884 sizeof(struct inpcb)) != sizeof(struct inpcb)) { 885 dprintf("can't read inpcb at %p", so.so_pcb); 886 goto bad; 887 } 888 printf(" %p", inpcb.inp_ppcb); 889 printf(" %s:%d", 890 inpcb.inp_laddr.s_addr == INADDR_ANY ? "*" : 891 inet_ntoa(inpcb.inp_laddr), 892 ntohs(inpcb.inp_lport)); 893 if (inpcb.inp_fport) { 894 if (so.so_state & SS_CONNECTOUT) 895 printf(" --> "); 896 else 897 printf(" <-- "); 898 printf("%s:%d", 899 inpcb.inp_faddr.s_addr == INADDR_ANY ? "*" : 900 inet_ntoa(inpcb.inp_faddr), 901 ntohs(inpcb.inp_fport)); 902 } 903 } else if (proto.pr_protocol == IPPROTO_UDP) { 904 if (so.so_pcb == NULL) 905 break; 906 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, 907 sizeof(struct inpcb)) != sizeof(struct inpcb)) { 908 dprintf("can't read inpcb at %p", so.so_pcb); 909 goto bad; 910 } 911 printf(" %s:%d", 912 inpcb.inp_laddr.s_addr == INADDR_ANY ? "*" : 913 inet_ntoa(inpcb.inp_laddr), 914 ntohs(inpcb.inp_lport)); 915 if (inpcb.inp_fport) 916 printf(" <-> %s:%d", 917 inpcb.inp_faddr.s_addr == INADDR_ANY ? "*" : 918 inet_ntoa(inpcb.inp_faddr), 919 ntohs(inpcb.inp_fport)); 920 } else if (so.so_pcb) 921 printf(" %p", so.so_pcb); 922 break; 923 #ifdef INET6 924 case AF_INET6: 925 getinetproto(proto.pr_protocol); 926 if (proto.pr_protocol == IPPROTO_TCP) { 927 if (so.so_pcb == NULL) 928 break; 929 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, 930 sizeof(struct inpcb)) != sizeof(struct inpcb)) { 931 dprintf("can't read inpcb at %p", so.so_pcb); 932 goto bad; 933 } 934 printf(" %p", inpcb.inp_ppcb); 935 snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]", 936 inet6_addrstr(&inpcb.inp_laddr6)); 937 printf(" %s:%d", 938 IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_laddr6) ? "*" : 939 xaddrbuf, 940 ntohs(inpcb.inp_lport)); 941 if (inpcb.inp_fport) { 942 if (so.so_state & SS_CONNECTOUT) 943 printf(" --> "); 944 else 945 printf(" <-- "); 946 snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]", 947 inet6_addrstr(&inpcb.inp_faddr6)); 948 printf("%s:%d", 949 IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_faddr6) ? "*" : 950 xaddrbuf, 951 ntohs(inpcb.inp_fport)); 952 } 953 } else if (proto.pr_protocol == IPPROTO_UDP) { 954 if (so.so_pcb == NULL) 955 break; 956 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, 957 sizeof(struct inpcb)) != sizeof(struct inpcb)) { 958 dprintf("can't read inpcb at %p", so.so_pcb); 959 goto bad; 960 } 961 snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]", 962 inet6_addrstr(&inpcb.inp_laddr6)); 963 printf(" %s:%d", 964 IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_laddr6) ? "*" : 965 xaddrbuf, 966 ntohs(inpcb.inp_lport)); 967 if (inpcb.inp_fport) { 968 snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]", 969 inet6_addrstr(&inpcb.inp_faddr6)); 970 printf(" <-> %s:%d", 971 IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_faddr6) ? "*" : 972 xaddrbuf, 973 ntohs(inpcb.inp_fport)); 974 } 975 } else if (so.so_pcb) 976 printf(" %p", so.so_pcb); 977 break; 978 #endif 979 case AF_UNIX: 980 /* print address of pcb and connected pcb */ 981 if (so.so_pcb) { 982 printf(" %p", so.so_pcb); 983 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb, 984 sizeof(struct unpcb)) != sizeof(struct unpcb)){ 985 dprintf("can't read unpcb at %p", so.so_pcb); 986 goto bad; 987 } 988 if (unpcb.unp_conn) { 989 char shoconn[4], *cp; 990 991 cp = shoconn; 992 if (!(so.so_state & SS_CANTRCVMORE)) 993 *cp++ = '<'; 994 *cp++ = '-'; 995 if (!(so.so_state & SS_CANTSENDMORE)) 996 *cp++ = '>'; 997 *cp = '\0'; 998 printf(" %s %p", shoconn, 999 unpcb.unp_conn); 1000 } 1001 } 1002 break; 1003 default: 1004 /* print protocol number and socket address */ 1005 printf(" %d %p", proto.pr_protocol, sock); 1006 } 1007 if (sflg) 1008 printf("\t%8lld %8lld", 1009 (long long)(fp? fp->f_rxfer + fp->f_wxfer : 0), 1010 (long long)(fp? fp->f_rbytes + fp->f_wbytes : 0) / 1024); 1011 printf("\n"); 1012 return; 1013 bad: 1014 printf("* error\n"); 1015 } 1016 1017 /* 1018 * getinetproto -- 1019 * print name of protocol number 1020 */ 1021 void 1022 getinetproto(number) 1023 int number; 1024 { 1025 static int isopen; 1026 struct protoent *pe; 1027 1028 if (!isopen) 1029 setprotoent(++isopen); 1030 if ((pe = getprotobynumber(number)) != NULL) 1031 printf(" %s", pe->p_name); 1032 else 1033 printf(" %d", number); 1034 } 1035 1036 int 1037 getfname(char *filename) 1038 { 1039 struct stat statbuf; 1040 DEVS *cur; 1041 1042 if (stat(filename, &statbuf)) { 1043 warn("%s", filename); 1044 return(0); 1045 } 1046 if ((cur = malloc(sizeof(DEVS))) == NULL) 1047 err(1, "malloc"); 1048 cur->next = devs; 1049 devs = cur; 1050 1051 cur->ino = statbuf.st_ino; 1052 cur->fsid = statbuf.st_dev & 0xffff; 1053 cur->name = filename; 1054 return(1); 1055 } 1056 1057 void 1058 usage(void) 1059 { 1060 fprintf(stderr, "usage: fstat [-fnosv] [-M core] [-N system] " 1061 "[-p pid] [-u user] [file ...]\n"); 1062 exit(1); 1063 } 1064