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