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