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