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