xref: /onnv-gate/usr/src/cmd/mdb/common/modules/genunix/vfs.c (revision 13009:29fc56bd19a6)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53507Svb160487  * Common Development and Distribution License (the "License").
63507Svb160487  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*13009SChandrasekar.Marimuthu@Sun.COM  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
260Sstevel@tonic-gate #include <mdb/mdb_ks.h>
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <sys/types.h>
290Sstevel@tonic-gate #include <sys/systm.h>
300Sstevel@tonic-gate #include <sys/door.h>
310Sstevel@tonic-gate #include <sys/file.h>
320Sstevel@tonic-gate #include <sys/mount.h>
330Sstevel@tonic-gate #include <sys/proc.h>
340Sstevel@tonic-gate #include <sys/procfs.h>
350Sstevel@tonic-gate #include <sys/proc/prdata.h>
360Sstevel@tonic-gate #include <sys/stat.h>
370Sstevel@tonic-gate #include <sys/vfs.h>
380Sstevel@tonic-gate #include <sys/vnode.h>
390Sstevel@tonic-gate #include <sys/fs/snode.h>
400Sstevel@tonic-gate #include <sys/fs/fifonode.h>
410Sstevel@tonic-gate #include <sys/fs/namenode.h>
420Sstevel@tonic-gate #include <sys/socket.h>
430Sstevel@tonic-gate #include <sys/stropts.h>
440Sstevel@tonic-gate #include <sys/socketvar.h>
450Sstevel@tonic-gate #include <sys/strsubr.h>
460Sstevel@tonic-gate #include <sys/un.h>
478348SEric.Yu@Sun.COM #include <fs/sockfs/socktpi_impl.h>
488348SEric.Yu@Sun.COM #include <inet/ipclassifier.h>
498348SEric.Yu@Sun.COM #include <inet/ip_if.h>
508348SEric.Yu@Sun.COM #include <inet/sctp/sctp_impl.h>
518348SEric.Yu@Sun.COM #include <inet/sctp/sctp_addr.h>
520Sstevel@tonic-gate 
530Sstevel@tonic-gate int
vfs_walk_init(mdb_walk_state_t * wsp)540Sstevel@tonic-gate vfs_walk_init(mdb_walk_state_t *wsp)
550Sstevel@tonic-gate {
560Sstevel@tonic-gate 	if (wsp->walk_addr == NULL &&
570Sstevel@tonic-gate 	    mdb_readvar(&wsp->walk_addr, "rootvfs") == -1) {
580Sstevel@tonic-gate 		mdb_warn("failed to read 'rootvfs'");
590Sstevel@tonic-gate 		return (WALK_ERR);
600Sstevel@tonic-gate 	}
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	wsp->walk_data = (void *)wsp->walk_addr;
630Sstevel@tonic-gate 	return (WALK_NEXT);
640Sstevel@tonic-gate }
650Sstevel@tonic-gate 
660Sstevel@tonic-gate int
vfs_walk_step(mdb_walk_state_t * wsp)670Sstevel@tonic-gate vfs_walk_step(mdb_walk_state_t *wsp)
680Sstevel@tonic-gate {
690Sstevel@tonic-gate 	vfs_t vfs;
700Sstevel@tonic-gate 	int status;
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	if (mdb_vread(&vfs, sizeof (vfs), wsp->walk_addr) == -1) {
730Sstevel@tonic-gate 		mdb_warn("failed to read vfs_t at %p", wsp->walk_addr);
740Sstevel@tonic-gate 		return (WALK_DONE);
750Sstevel@tonic-gate 	}
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, &vfs, wsp->walk_cbdata);
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	if (vfs.vfs_next == wsp->walk_data)
800Sstevel@tonic-gate 		return (WALK_DONE);
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)vfs.vfs_next;
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 	return (status);
850Sstevel@tonic-gate }
860Sstevel@tonic-gate 
870Sstevel@tonic-gate /*
880Sstevel@tonic-gate  * Utility routine to read in a filesystem name given a vfs pointer.  If
890Sstevel@tonic-gate  * no vfssw entry for the vfs is available (as is the case with some pseudo-
900Sstevel@tonic-gate  * filesystems), we check against some known problem fs's: doorfs and
910Sstevel@tonic-gate  * portfs.  If that fails, we try to guess the filesystem name using
920Sstevel@tonic-gate  * symbol names.  fsname should be a buffer of size _ST_FSTYPSZ.
930Sstevel@tonic-gate  */
940Sstevel@tonic-gate static int
read_fsname(uintptr_t vfsp,char * fsname)950Sstevel@tonic-gate read_fsname(uintptr_t vfsp, char *fsname)
960Sstevel@tonic-gate {
970Sstevel@tonic-gate 	vfs_t vfs;
980Sstevel@tonic-gate 	struct vfssw vfssw_entry;
990Sstevel@tonic-gate 	GElf_Sym vfssw_sym, test_sym;
1000Sstevel@tonic-gate 	char testname[MDB_SYM_NAMLEN];
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 	if (mdb_vread(&vfs, sizeof (vfs), vfsp) == -1) {
1030Sstevel@tonic-gate 		mdb_warn("failed to read vfs %p", vfsp);
1040Sstevel@tonic-gate 		return (-1);
1050Sstevel@tonic-gate 	}
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 	if (mdb_lookup_by_name("vfssw", &vfssw_sym) == -1) {
1080Sstevel@tonic-gate 		mdb_warn("failed to find vfssw");
1090Sstevel@tonic-gate 		return (-1);
1100Sstevel@tonic-gate 	}
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	/*
1130Sstevel@tonic-gate 	 * vfssw is an array; we need vfssw[vfs.vfs_fstype].
1140Sstevel@tonic-gate 	 */
1150Sstevel@tonic-gate 	if (mdb_vread(&vfssw_entry, sizeof (vfssw_entry),
1160Sstevel@tonic-gate 	    vfssw_sym.st_value + (sizeof (struct vfssw) * vfs.vfs_fstype))
1170Sstevel@tonic-gate 	    == -1) {
1180Sstevel@tonic-gate 		mdb_warn("failed to read vfssw index %d", vfs.vfs_fstype);
1190Sstevel@tonic-gate 		return (-1);
1200Sstevel@tonic-gate 	}
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate 	if (vfs.vfs_fstype != 0) {
1230Sstevel@tonic-gate 		if (mdb_readstr(fsname, _ST_FSTYPSZ,
1240Sstevel@tonic-gate 		    (uintptr_t)vfssw_entry.vsw_name) == -1) {
1250Sstevel@tonic-gate 			mdb_warn("failed to find fs name %p",
1260Sstevel@tonic-gate 			    vfssw_entry.vsw_name);
1270Sstevel@tonic-gate 			return (-1);
1280Sstevel@tonic-gate 		}
1290Sstevel@tonic-gate 		return (0);
1300Sstevel@tonic-gate 	}
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	/*
1330Sstevel@tonic-gate 	 * Do precise detection for certain filesystem types that we
1340Sstevel@tonic-gate 	 * know do not appear in vfssw[], and that we depend upon in other
1350Sstevel@tonic-gate 	 * parts of the code: doorfs and portfs.
1360Sstevel@tonic-gate 	 */
1370Sstevel@tonic-gate 	if (mdb_lookup_by_name("door_vfs", &test_sym) != -1) {
1380Sstevel@tonic-gate 		if (test_sym.st_value == vfsp) {
1390Sstevel@tonic-gate 			strcpy(fsname, "doorfs");
1400Sstevel@tonic-gate 			return (0);
1410Sstevel@tonic-gate 		}
1420Sstevel@tonic-gate 	}
1430Sstevel@tonic-gate 	if (mdb_lookup_by_name("port_vfs", &test_sym) != -1) {
1440Sstevel@tonic-gate 		if (test_sym.st_value == vfsp) {
1450Sstevel@tonic-gate 			strcpy(fsname, "portfs");
1460Sstevel@tonic-gate 			return (0);
1470Sstevel@tonic-gate 		}
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	/*
1510Sstevel@tonic-gate 	 * Heuristic detection for other filesystems that don't have a
1520Sstevel@tonic-gate 	 * vfssw[] entry.  These tend to be named <fsname>_vfs, so we do a
1530Sstevel@tonic-gate 	 * lookup_by_addr and see if we find a symbol of that name.
1540Sstevel@tonic-gate 	 */
1550Sstevel@tonic-gate 	if (mdb_lookup_by_addr(vfsp, MDB_SYM_EXACT, testname, sizeof (testname),
1560Sstevel@tonic-gate 	    &test_sym) != -1) {
1570Sstevel@tonic-gate 		if ((strlen(testname) > 4) &&
1580Sstevel@tonic-gate 		    (strcmp(testname + strlen(testname) - 4, "_vfs") == 0)) {
1590Sstevel@tonic-gate 			testname[strlen(testname) - 4] = '\0';
1600Sstevel@tonic-gate 			strncpy(fsname, testname, _ST_FSTYPSZ);
1610Sstevel@tonic-gate 			return (0);
1620Sstevel@tonic-gate 		}
1630Sstevel@tonic-gate 	}
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	mdb_warn("unknown filesystem type for vfs %p", vfsp);
1660Sstevel@tonic-gate 	return (-1);
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate  * Column widths for mount point display in ::fsinfo output.
1710Sstevel@tonic-gate  */
1720Sstevel@tonic-gate #ifdef _LP64
1730Sstevel@tonic-gate #define	FSINFO_MNTLEN	48
1740Sstevel@tonic-gate #else
1750Sstevel@tonic-gate #define	FSINFO_MNTLEN	56
1760Sstevel@tonic-gate #endif
1770Sstevel@tonic-gate 
1788348SEric.Yu@Sun.COM /* ARGSUSED */
1790Sstevel@tonic-gate int
fsinfo(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1800Sstevel@tonic-gate fsinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1810Sstevel@tonic-gate {
1820Sstevel@tonic-gate 	vfs_t vfs;
1830Sstevel@tonic-gate 	int len;
1840Sstevel@tonic-gate 	int opt_v = 0;
1850Sstevel@tonic-gate 	char buf[MAXPATHLEN];
1860Sstevel@tonic-gate 	char fsname[_ST_FSTYPSZ];
1870Sstevel@tonic-gate 	mntopt_t *mntopts;
1880Sstevel@tonic-gate 	size_t size;
1890Sstevel@tonic-gate 	int i;
1900Sstevel@tonic-gate 	int first = 1;
1910Sstevel@tonic-gate 	char opt[MAX_MNTOPT_STR];
1920Sstevel@tonic-gate 	uintptr_t global_zone;
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
1950Sstevel@tonic-gate 		if (mdb_walk_dcmd("vfs", "fsinfo", argc, argv) == -1) {
1960Sstevel@tonic-gate 			mdb_warn("failed to walk file system list");
1970Sstevel@tonic-gate 			return (DCMD_ERR);
1980Sstevel@tonic-gate 		}
1990Sstevel@tonic-gate 		return (DCMD_OK);
2000Sstevel@tonic-gate 	}
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
2030Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc)
2040Sstevel@tonic-gate 		return (DCMD_USAGE);
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags))
2070Sstevel@tonic-gate 		mdb_printf("%<u>%?s %-15s %s%</u>\n",
2080Sstevel@tonic-gate 		    "VFSP", "FS", "MOUNT");
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	if (mdb_vread(&vfs, sizeof (vfs), addr) == -1) {
2110Sstevel@tonic-gate 		mdb_warn("failed to read vfs_t %p", addr);
2120Sstevel@tonic-gate 		return (DCMD_ERR);
2130Sstevel@tonic-gate 	}
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	if ((len = mdb_read_refstr((uintptr_t)vfs.vfs_mntpt, buf,
2160Sstevel@tonic-gate 	    sizeof (buf))) <= 0)
2170Sstevel@tonic-gate 		strcpy(buf, "??");
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 	else if (!opt_v && (len >= FSINFO_MNTLEN))
2200Sstevel@tonic-gate 		/*
2210Sstevel@tonic-gate 		 * In normal mode, we truncate the path to keep the output
2220Sstevel@tonic-gate 		 * clean.  In -v mode, we just print the full path.
2230Sstevel@tonic-gate 		 */
2240Sstevel@tonic-gate 		strcpy(&buf[FSINFO_MNTLEN - 4], "...");
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	if (read_fsname(addr, fsname) == -1)
2270Sstevel@tonic-gate 		return (DCMD_ERR);
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	mdb_printf("%0?p %-15s %s\n", addr, fsname, buf);
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	if (!opt_v)
2320Sstevel@tonic-gate 		return (DCMD_OK);
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	/*
2350Sstevel@tonic-gate 	 * Print 'resource' string; this shows what we're mounted upon.
2360Sstevel@tonic-gate 	 */
2370Sstevel@tonic-gate 	if (mdb_read_refstr((uintptr_t)vfs.vfs_resource, buf,
2380Sstevel@tonic-gate 	    MAXPATHLEN) <= 0)
2390Sstevel@tonic-gate 		strcpy(buf, "??");
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	mdb_printf("%?s %s\n", "R:", buf);
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	/*
2440Sstevel@tonic-gate 	 * Print mount options array; it sucks to be a mimic, but we copy
2450Sstevel@tonic-gate 	 * the same logic as in mntvnops.c for adding zone= tags, and we
2460Sstevel@tonic-gate 	 * don't bother with the obsolete dev= option.
2470Sstevel@tonic-gate 	 */
2480Sstevel@tonic-gate 	size = vfs.vfs_mntopts.mo_count * sizeof (mntopt_t);
2490Sstevel@tonic-gate 	mntopts = mdb_alloc(size, UM_SLEEP | UM_GC);
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	if (mdb_vread(mntopts, size,
2520Sstevel@tonic-gate 	    (uintptr_t)vfs.vfs_mntopts.mo_list) == -1) {
2530Sstevel@tonic-gate 		mdb_warn("failed to read mntopts %p", vfs.vfs_mntopts.mo_list);
2540Sstevel@tonic-gate 		return (DCMD_ERR);
2550Sstevel@tonic-gate 	}
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 	for (i = 0; i < vfs.vfs_mntopts.mo_count; i++) {
2580Sstevel@tonic-gate 		if (mntopts[i].mo_flags & MO_SET) {
2590Sstevel@tonic-gate 			if (mdb_readstr(opt, sizeof (opt),
2600Sstevel@tonic-gate 			    (uintptr_t)mntopts[i].mo_name) == -1) {
2610Sstevel@tonic-gate 				mdb_warn("failed to read mntopt name %p",
2620Sstevel@tonic-gate 				    mntopts[i].mo_name);
2630Sstevel@tonic-gate 				return (DCMD_ERR);
2640Sstevel@tonic-gate 			}
2650Sstevel@tonic-gate 			if (first) {
2660Sstevel@tonic-gate 				mdb_printf("%?s ", "O:");
2670Sstevel@tonic-gate 				first = 0;
2680Sstevel@tonic-gate 			} else {
2690Sstevel@tonic-gate 				mdb_printf(",");
2700Sstevel@tonic-gate 			}
2710Sstevel@tonic-gate 			mdb_printf("%s", opt);
2720Sstevel@tonic-gate 			if (mntopts[i].mo_flags & MO_HASVALUE) {
2730Sstevel@tonic-gate 				if (mdb_readstr(opt, sizeof (opt),
2740Sstevel@tonic-gate 				    (uintptr_t)mntopts[i].mo_arg) == -1) {
2750Sstevel@tonic-gate 					mdb_warn("failed to read mntopt "
2760Sstevel@tonic-gate 					    "value %p", mntopts[i].mo_arg);
2770Sstevel@tonic-gate 					return (DCMD_ERR);
2780Sstevel@tonic-gate 				}
2790Sstevel@tonic-gate 				mdb_printf("=%s", opt);
2800Sstevel@tonic-gate 			}
2810Sstevel@tonic-gate 		}
2820Sstevel@tonic-gate 	}
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	if (mdb_readvar(&global_zone, "global_zone") == -1) {
2850Sstevel@tonic-gate 		mdb_warn("failed to locate global_zone");
2860Sstevel@tonic-gate 		return (DCMD_ERR);
2870Sstevel@tonic-gate 	}
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	if ((vfs.vfs_zone != NULL) &&
2900Sstevel@tonic-gate 	    ((uintptr_t)vfs.vfs_zone != global_zone)) {
2910Sstevel@tonic-gate 		zone_t z;
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 		if (mdb_vread(&z, sizeof (z), (uintptr_t)vfs.vfs_zone) == -1) {
2940Sstevel@tonic-gate 			mdb_warn("failed to read zone");
2950Sstevel@tonic-gate 			return (DCMD_ERR);
2960Sstevel@tonic-gate 		}
2970Sstevel@tonic-gate 		/*
2980Sstevel@tonic-gate 		 * zone names are much shorter than MAX_MNTOPT_STR
2990Sstevel@tonic-gate 		 */
3000Sstevel@tonic-gate 		if (mdb_readstr(opt, sizeof (opt),
3010Sstevel@tonic-gate 		    (uintptr_t)z.zone_name) == -1) {
3020Sstevel@tonic-gate 			mdb_warn("failed to read zone name");
3030Sstevel@tonic-gate 			return (DCMD_ERR);
3040Sstevel@tonic-gate 		}
3050Sstevel@tonic-gate 		if (first) {
3060Sstevel@tonic-gate 			mdb_printf("%?s ", "O:");
3070Sstevel@tonic-gate 		} else {
3080Sstevel@tonic-gate 			mdb_printf(",");
3090Sstevel@tonic-gate 		}
3100Sstevel@tonic-gate 		mdb_printf("zone=%s", opt);
3110Sstevel@tonic-gate 	}
3120Sstevel@tonic-gate 	return (DCMD_OK);
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate #define	REALVP_DONE	0
3170Sstevel@tonic-gate #define	REALVP_ERR	1
3180Sstevel@tonic-gate #define	REALVP_CONTINUE	2
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate static int
next_realvp(uintptr_t invp,struct vnode * outvn,uintptr_t * outvp)3210Sstevel@tonic-gate next_realvp(uintptr_t invp, struct vnode *outvn, uintptr_t *outvp)
3220Sstevel@tonic-gate {
3230Sstevel@tonic-gate 	char fsname[_ST_FSTYPSZ];
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	*outvp = invp;
3260Sstevel@tonic-gate 	if (mdb_vread(outvn, sizeof (struct vnode), invp) == -1) {
3270Sstevel@tonic-gate 		mdb_warn("failed to read vnode at %p", invp);
3280Sstevel@tonic-gate 		return (REALVP_ERR);
3290Sstevel@tonic-gate 	}
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 	if (read_fsname((uintptr_t)outvn->v_vfsp, fsname) == -1)
3320Sstevel@tonic-gate 		return (REALVP_ERR);
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	/*
3350Sstevel@tonic-gate 	 * We know how to do 'realvp' for as many filesystems as possible;
3360Sstevel@tonic-gate 	 * for all other filesystems, we assume that the vp we are given
3370Sstevel@tonic-gate 	 * is the realvp.  In the kernel, a realvp operation will sometimes
3380Sstevel@tonic-gate 	 * dig through multiple layers.  Here, we only fetch the pointer
3390Sstevel@tonic-gate 	 * to the next layer down.  This allows dcmds to print out the
3400Sstevel@tonic-gate 	 * various layers.
3410Sstevel@tonic-gate 	 */
3420Sstevel@tonic-gate 	if (strcmp(fsname, "fifofs") == 0) {
3430Sstevel@tonic-gate 		fifonode_t fn;
3440Sstevel@tonic-gate 		if (mdb_vread(&fn, sizeof (fn),
3450Sstevel@tonic-gate 		    (uintptr_t)outvn->v_data) == -1) {
3460Sstevel@tonic-gate 			mdb_warn("failed to read fifonode");
3470Sstevel@tonic-gate 			return (REALVP_ERR);
3480Sstevel@tonic-gate 		}
3490Sstevel@tonic-gate 		*outvp = (uintptr_t)fn.fn_realvp;
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 	} else if (strcmp(fsname, "namefs") == 0) {
3520Sstevel@tonic-gate 		struct namenode nn;
3530Sstevel@tonic-gate 		if (mdb_vread(&nn, sizeof (nn),
3540Sstevel@tonic-gate 		    (uintptr_t)outvn->v_data) == -1) {
3550Sstevel@tonic-gate 			mdb_warn("failed to read namenode");
3560Sstevel@tonic-gate 			return (REALVP_ERR);
3570Sstevel@tonic-gate 		}
3580Sstevel@tonic-gate 		*outvp = (uintptr_t)nn.nm_filevp;
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	} else if (outvn->v_type == VSOCK && outvn->v_stream != NULL) {
3610Sstevel@tonic-gate 		struct stdata stream;
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 		/*
3640Sstevel@tonic-gate 		 * Sockets have a strange and different layering scheme; we
3650Sstevel@tonic-gate 		 * hop over into the sockfs vnode (accessible via the stream
3660Sstevel@tonic-gate 		 * head) if possible.
3670Sstevel@tonic-gate 		 */
3680Sstevel@tonic-gate 		if (mdb_vread(&stream, sizeof (stream),
3690Sstevel@tonic-gate 		    (uintptr_t)outvn->v_stream) == -1) {
3700Sstevel@tonic-gate 			mdb_warn("failed to read stream data");
3710Sstevel@tonic-gate 			return (REALVP_ERR);
3720Sstevel@tonic-gate 		}
3730Sstevel@tonic-gate 		*outvp = (uintptr_t)stream.sd_vnode;
3740Sstevel@tonic-gate 	}
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	if (*outvp == invp || *outvp == NULL)
3770Sstevel@tonic-gate 		return (REALVP_DONE);
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	return (REALVP_CONTINUE);
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate static void
pfiles_print_addr(struct sockaddr * addr)3830Sstevel@tonic-gate pfiles_print_addr(struct sockaddr *addr)
3840Sstevel@tonic-gate {
3850Sstevel@tonic-gate 	struct sockaddr_in *s_in;
3860Sstevel@tonic-gate 	struct sockaddr_un *s_un;
3870Sstevel@tonic-gate 	struct sockaddr_in6 *s_in6;
3883507Svb160487 	in_port_t port;
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 	switch (addr->sa_family) {
3910Sstevel@tonic-gate 	case AF_INET:
3928348SEric.Yu@Sun.COM 		/* LINTED: alignment */
3930Sstevel@tonic-gate 		s_in = (struct sockaddr_in *)addr;
3943507Svb160487 		mdb_nhconvert(&port, &s_in->sin_port, sizeof (port));
3953507Svb160487 		mdb_printf("AF_INET %I %d ", s_in->sin_addr.s_addr, port);
3960Sstevel@tonic-gate 		break;
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 	case AF_INET6:
3998348SEric.Yu@Sun.COM 		/* LINTED: alignment */
4000Sstevel@tonic-gate 		s_in6 = (struct sockaddr_in6 *)addr;
4013507Svb160487 		mdb_nhconvert(&port, &s_in6->sin6_port, sizeof (port));
4023507Svb160487 		mdb_printf("AF_INET6 %N %d ", &(s_in6->sin6_addr), port);
4030Sstevel@tonic-gate 		break;
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	case AF_UNIX:
4060Sstevel@tonic-gate 		s_un = (struct sockaddr_un *)addr;
4070Sstevel@tonic-gate 		mdb_printf("AF_UNIX %s ", s_un->sun_path);
4080Sstevel@tonic-gate 		break;
4090Sstevel@tonic-gate 	default:
4100Sstevel@tonic-gate 		mdb_printf("AF_?? (%d) ", addr->sa_family);
4110Sstevel@tonic-gate 		break;
4120Sstevel@tonic-gate 	}
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate static int
pfiles_get_sonode(vnode_t * v_sock,struct sonode * sonode)4168348SEric.Yu@Sun.COM pfiles_get_sonode(vnode_t *v_sock, struct sonode *sonode)
4170Sstevel@tonic-gate {
4188348SEric.Yu@Sun.COM 	if (mdb_vread(sonode, sizeof (struct sonode),
4198348SEric.Yu@Sun.COM 	    (uintptr_t)v_sock->v_data) == -1) {
4208348SEric.Yu@Sun.COM 		mdb_warn("failed to read sonode");
4210Sstevel@tonic-gate 		return (-1);
4220Sstevel@tonic-gate 	}
4230Sstevel@tonic-gate 
4248348SEric.Yu@Sun.COM 	return (0);
4258348SEric.Yu@Sun.COM }
4268348SEric.Yu@Sun.COM 
4278348SEric.Yu@Sun.COM static int
pfiles_get_tpi_sonode(vnode_t * v_sock,sotpi_sonode_t * sotpi_sonode)4288348SEric.Yu@Sun.COM pfiles_get_tpi_sonode(vnode_t *v_sock, sotpi_sonode_t *sotpi_sonode)
4298348SEric.Yu@Sun.COM {
4308348SEric.Yu@Sun.COM 
4318348SEric.Yu@Sun.COM 	struct stdata stream;
4328348SEric.Yu@Sun.COM 
4338348SEric.Yu@Sun.COM 	if (mdb_vread(&stream, sizeof (stream),
4348348SEric.Yu@Sun.COM 	    (uintptr_t)v_sock->v_stream) == -1) {
4350Sstevel@tonic-gate 		mdb_warn("failed to read stream data");
4360Sstevel@tonic-gate 		return (-1);
4370Sstevel@tonic-gate 	}
4380Sstevel@tonic-gate 
4398348SEric.Yu@Sun.COM 	if (mdb_vread(v_sock, sizeof (vnode_t),
4408348SEric.Yu@Sun.COM 	    (uintptr_t)stream.sd_vnode) == -1) {
4410Sstevel@tonic-gate 		mdb_warn("failed to read stream vnode");
4420Sstevel@tonic-gate 		return (-1);
4430Sstevel@tonic-gate 	}
4440Sstevel@tonic-gate 
4458348SEric.Yu@Sun.COM 	if (mdb_vread(sotpi_sonode, sizeof (sotpi_sonode_t),
4468348SEric.Yu@Sun.COM 	    (uintptr_t)v_sock->v_data) == -1) {
4478348SEric.Yu@Sun.COM 		mdb_warn("failed to read sotpi_sonode");
4480Sstevel@tonic-gate 		return (-1);
4490Sstevel@tonic-gate 	}
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	return (0);
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate /*
4550Sstevel@tonic-gate  * Do some digging to get a reasonable pathname for this vnode. 'path'
4560Sstevel@tonic-gate  * should point at a buffer of MAXPATHLEN in size.
4570Sstevel@tonic-gate  */
4580Sstevel@tonic-gate static int
pfiles_dig_pathname(uintptr_t vp,char * path)4590Sstevel@tonic-gate pfiles_dig_pathname(uintptr_t vp, char *path)
4600Sstevel@tonic-gate {
4610Sstevel@tonic-gate 	vnode_t v;
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	bzero(path, MAXPATHLEN);
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	if (mdb_vread(&v, sizeof (v), vp) == -1) {
4660Sstevel@tonic-gate 		mdb_warn("failed to read vnode");
4670Sstevel@tonic-gate 		return (-1);
4680Sstevel@tonic-gate 	}
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 	if (v.v_path == NULL) {
4710Sstevel@tonic-gate 		/*
4720Sstevel@tonic-gate 		 * fifo's and doors are special.   Some have pathnames, and
4730Sstevel@tonic-gate 		 * some do not.  And for these, it is pointless to go off to
4740Sstevel@tonic-gate 		 * mdb_vnode2path, which is very slow.
4750Sstevel@tonic-gate 		 *
4760Sstevel@tonic-gate 		 * Event ports never have a pathname.
4770Sstevel@tonic-gate 		 */
4780Sstevel@tonic-gate 		if (v.v_type == VFIFO || v.v_type == VDOOR || v.v_type == VPORT)
4790Sstevel@tonic-gate 			return (0);
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 		/*
4820Sstevel@tonic-gate 		 * For sockets, we won't find a path unless we print the path
4838348SEric.Yu@Sun.COM 		 * associated with transport's STREAM device.
4840Sstevel@tonic-gate 		 */
4850Sstevel@tonic-gate 		if (v.v_type == VSOCK) {
4860Sstevel@tonic-gate 			struct sonode sonode;
48710739Sdp@eng.sun.com 			struct sockparams sockparams;
4880Sstevel@tonic-gate 
4898348SEric.Yu@Sun.COM 			if (pfiles_get_sonode(&v, &sonode) == -1) {
4900Sstevel@tonic-gate 				return (-1);
4910Sstevel@tonic-gate 			}
49210739Sdp@eng.sun.com 			if (mdb_vread(&sockparams, sizeof (sockparams),
49310739Sdp@eng.sun.com 			    (uintptr_t)sonode.so_sockparams) == -1) {
49410739Sdp@eng.sun.com 				mdb_warn("failed to read sockparams");
49510739Sdp@eng.sun.com 				return (-1);
49610739Sdp@eng.sun.com 			}
49710739Sdp@eng.sun.com 
4988348SEric.Yu@Sun.COM 			if (!SOCK_IS_NONSTR(&sonode)) {
49910739Sdp@eng.sun.com 				vp = (uintptr_t)
50010739Sdp@eng.sun.com 				    sockparams.sp_sdev_info.sd_vnode;
5018348SEric.Yu@Sun.COM 			} else {
5028348SEric.Yu@Sun.COM 				vp = NULL;
5038348SEric.Yu@Sun.COM 			}
5040Sstevel@tonic-gate 		}
5050Sstevel@tonic-gate 	}
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	/*
5090Sstevel@tonic-gate 	 * mdb_vnode2path will print an error for us as needed, but not
5100Sstevel@tonic-gate 	 * finding a pathname is not really an error, so we plow on.
5110Sstevel@tonic-gate 	 */
5120Sstevel@tonic-gate 	(void) mdb_vnode2path(vp, path, MAXPATHLEN);
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 	/*
5150Sstevel@tonic-gate 	 * A common problem is that device pathnames are prefixed with
5160Sstevel@tonic-gate 	 * /dev/../devices/.  We just clean those up slightly:
5170Sstevel@tonic-gate 	 * 	/dev/../devices/<mumble> --> /devices/<mumble>
5180Sstevel@tonic-gate 	 * 	/dev/pts/../../devices/<mumble> --> /devices/<mumble>
5190Sstevel@tonic-gate 	 */
5200Sstevel@tonic-gate 	if (strncmp("/dev/../devices/", path, strlen("/dev/../devices/")) == 0)
5210Sstevel@tonic-gate 		strcpy(path, path + 7);
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 	if (strncmp("/dev/pts/../../devices/", path,
5240Sstevel@tonic-gate 	    strlen("/dev/pts/../../devices/")) == 0)
5250Sstevel@tonic-gate 		strcpy(path, path + 14);
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	return (0);
5280Sstevel@tonic-gate }
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate const struct fs_type {
5310Sstevel@tonic-gate 	int type;
5320Sstevel@tonic-gate 	const char *name;
5330Sstevel@tonic-gate } fs_types[] = {
5340Sstevel@tonic-gate 	{ VNON,   "NON" },
5350Sstevel@tonic-gate 	{ VREG,   "REG" },
5360Sstevel@tonic-gate 	{ VDIR,   "DIR" },
5370Sstevel@tonic-gate 	{ VBLK,   "BLK" },
5380Sstevel@tonic-gate 	{ VCHR,   "CHR" },
5390Sstevel@tonic-gate 	{ VLNK,   "LNK" },
5400Sstevel@tonic-gate 	{ VFIFO,  "FIFO" },
5410Sstevel@tonic-gate 	{ VDOOR,  "DOOR" },
5420Sstevel@tonic-gate 	{ VPROC,  "PROC" },
5430Sstevel@tonic-gate 	{ VSOCK,  "SOCK" },
5440Sstevel@tonic-gate 	{ VPORT,  "PORT" },
5450Sstevel@tonic-gate 	{ VBAD,   "BAD" }
5460Sstevel@tonic-gate };
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate #define	NUM_FS_TYPES (sizeof (fs_types) / sizeof (struct fs_type))
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate struct pfiles_cbdata {
5510Sstevel@tonic-gate 	int opt_p;
5520Sstevel@tonic-gate 	int fd;
5530Sstevel@tonic-gate };
5540Sstevel@tonic-gate 
5558348SEric.Yu@Sun.COM #define	list_d2l(a, obj) ((list_node_t *)(((char *)obj) + (a)->list_offset))
5568348SEric.Yu@Sun.COM #define	list_object(a, node) ((void *)(((char *)node) - (a)->list_offset))
5578348SEric.Yu@Sun.COM 
5588348SEric.Yu@Sun.COM /*
5598348SEric.Yu@Sun.COM  * SCTP interface for geting the first source address of a sctp_t.
5608348SEric.Yu@Sun.COM  */
5618348SEric.Yu@Sun.COM int
sctp_getsockaddr(sctp_t * sctp,struct sockaddr * addr)5628348SEric.Yu@Sun.COM sctp_getsockaddr(sctp_t *sctp, struct sockaddr *addr)
5638348SEric.Yu@Sun.COM {
5648348SEric.Yu@Sun.COM 	int			err = -1;
5658348SEric.Yu@Sun.COM 	int			i;
5668348SEric.Yu@Sun.COM 	int			l;
5678348SEric.Yu@Sun.COM 	sctp_saddr_ipif_t	*pobj;
5688348SEric.Yu@Sun.COM 	sctp_saddr_ipif_t	obj;
5698348SEric.Yu@Sun.COM 	size_t			added = 0;
5708348SEric.Yu@Sun.COM 	sin6_t			*sin6;
5718348SEric.Yu@Sun.COM 	sin_t			*sin4;
5728348SEric.Yu@Sun.COM 	int			scanned = 0;
5738348SEric.Yu@Sun.COM 	boolean_t		skip_lback = B_FALSE;
57411042SErik.Nordmark@Sun.COM 	conn_t			*connp = sctp->sctp_connp;
5758348SEric.Yu@Sun.COM 
57611042SErik.Nordmark@Sun.COM 	addr->sa_family = connp->conn_family;
5778348SEric.Yu@Sun.COM 	if (sctp->sctp_nsaddrs == 0)
5788348SEric.Yu@Sun.COM 		goto done;
5798348SEric.Yu@Sun.COM 
5808348SEric.Yu@Sun.COM 	/*
5818348SEric.Yu@Sun.COM 	 * Skip loopback addresses for non-loopback assoc.
5828348SEric.Yu@Sun.COM 	 */
5838348SEric.Yu@Sun.COM 	if (sctp->sctp_state >= SCTPS_ESTABLISHED && !sctp->sctp_loopback) {
5848348SEric.Yu@Sun.COM 		skip_lback = B_TRUE;
5858348SEric.Yu@Sun.COM 	}
5868348SEric.Yu@Sun.COM 
5878348SEric.Yu@Sun.COM 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
5888348SEric.Yu@Sun.COM 		if (sctp->sctp_saddrs[i].ipif_count == 0)
5898348SEric.Yu@Sun.COM 			continue;
5908348SEric.Yu@Sun.COM 
5918348SEric.Yu@Sun.COM 		pobj = list_object(&sctp->sctp_saddrs[i].sctp_ipif_list,
5928348SEric.Yu@Sun.COM 		    sctp->sctp_saddrs[i].sctp_ipif_list.list_head.list_next);
5938348SEric.Yu@Sun.COM 		if (mdb_vread(&obj, sizeof (sctp_saddr_ipif_t),
5948348SEric.Yu@Sun.COM 		    (uintptr_t)pobj) == -1) {
5958348SEric.Yu@Sun.COM 			mdb_warn("failed to read sctp_saddr_ipif_t");
5968348SEric.Yu@Sun.COM 			return (err);
5978348SEric.Yu@Sun.COM 		}
5988348SEric.Yu@Sun.COM 
5998348SEric.Yu@Sun.COM 		for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) {
6008348SEric.Yu@Sun.COM 			sctp_ipif_t	ipif;
6018348SEric.Yu@Sun.COM 			in6_addr_t	laddr;
6028348SEric.Yu@Sun.COM 			list_node_t 	*pnode;
6038348SEric.Yu@Sun.COM 			list_node_t	node;
6048348SEric.Yu@Sun.COM 
6058348SEric.Yu@Sun.COM 			if (mdb_vread(&ipif, sizeof (sctp_ipif_t),
6068348SEric.Yu@Sun.COM 			    (uintptr_t)obj.saddr_ipifp) == -1) {
6078348SEric.Yu@Sun.COM 				mdb_warn("failed to read sctp_ipif_t");
6088348SEric.Yu@Sun.COM 				return (err);
6098348SEric.Yu@Sun.COM 			}
6108348SEric.Yu@Sun.COM 			laddr = ipif.sctp_ipif_saddr;
6118348SEric.Yu@Sun.COM 
6128348SEric.Yu@Sun.COM 			scanned++;
6138348SEric.Yu@Sun.COM 			if ((ipif.sctp_ipif_state == SCTP_IPIFS_CONDEMNED) ||
6148348SEric.Yu@Sun.COM 			    SCTP_DONT_SRC(&obj) ||
6158348SEric.Yu@Sun.COM 			    (ipif.sctp_ipif_ill->sctp_ill_flags &
6168348SEric.Yu@Sun.COM 			    PHYI_LOOPBACK) && skip_lback) {
6178348SEric.Yu@Sun.COM 				if (scanned >= sctp->sctp_nsaddrs)
6188348SEric.Yu@Sun.COM 					goto done;
6198348SEric.Yu@Sun.COM 
6208348SEric.Yu@Sun.COM 				/* LINTED: alignment */
6218348SEric.Yu@Sun.COM 				pnode = list_d2l(&sctp->sctp_saddrs[i].
6228348SEric.Yu@Sun.COM 				    sctp_ipif_list, pobj);
6238348SEric.Yu@Sun.COM 				if (mdb_vread(&node, sizeof (list_node_t),
6248348SEric.Yu@Sun.COM 				    (uintptr_t)pnode) == -1) {
6258348SEric.Yu@Sun.COM 					mdb_warn("failed to read list_node_t");
6268348SEric.Yu@Sun.COM 					return (err);
6278348SEric.Yu@Sun.COM 				}
6288348SEric.Yu@Sun.COM 				pobj = list_object(&sctp->sctp_saddrs[i].
6298348SEric.Yu@Sun.COM 				    sctp_ipif_list, node.list_next);
6308348SEric.Yu@Sun.COM 				if (mdb_vread(&obj, sizeof (sctp_saddr_ipif_t),
6318348SEric.Yu@Sun.COM 				    (uintptr_t)pobj) == -1) {
6328348SEric.Yu@Sun.COM 					mdb_warn("failed to read "
6338348SEric.Yu@Sun.COM 					    "sctp_saddr_ipif_t");
6348348SEric.Yu@Sun.COM 					return (err);
6358348SEric.Yu@Sun.COM 				}
6368348SEric.Yu@Sun.COM 				continue;
6378348SEric.Yu@Sun.COM 			}
6388348SEric.Yu@Sun.COM 
63911042SErik.Nordmark@Sun.COM 			switch (connp->conn_family) {
6408348SEric.Yu@Sun.COM 			case AF_INET:
6418348SEric.Yu@Sun.COM 				/* LINTED: alignment */
6428348SEric.Yu@Sun.COM 				sin4 = (sin_t *)addr;
6438348SEric.Yu@Sun.COM 				if ((sctp->sctp_state <= SCTPS_LISTEN) &&
6448348SEric.Yu@Sun.COM 				    sctp->sctp_bound_to_all) {
6458348SEric.Yu@Sun.COM 					sin4->sin_addr.s_addr = INADDR_ANY;
64611042SErik.Nordmark@Sun.COM 					sin4->sin_port = connp->conn_lport;
6478348SEric.Yu@Sun.COM 				} else {
6488348SEric.Yu@Sun.COM 					sin4 += added;
6498348SEric.Yu@Sun.COM 					sin4->sin_family = AF_INET;
65011042SErik.Nordmark@Sun.COM 					sin4->sin_port = connp->conn_lport;
6518348SEric.Yu@Sun.COM 					IN6_V4MAPPED_TO_INADDR(&laddr,
6528348SEric.Yu@Sun.COM 					    &sin4->sin_addr);
6538348SEric.Yu@Sun.COM 				}
6548348SEric.Yu@Sun.COM 				break;
6558348SEric.Yu@Sun.COM 
6568348SEric.Yu@Sun.COM 			case AF_INET6:
6578348SEric.Yu@Sun.COM 				/* LINTED: alignment */
6588348SEric.Yu@Sun.COM 				sin6 = (sin6_t *)addr;
6598348SEric.Yu@Sun.COM 				if ((sctp->sctp_state <= SCTPS_LISTEN) &&
6608348SEric.Yu@Sun.COM 				    sctp->sctp_bound_to_all) {
6618348SEric.Yu@Sun.COM 					bzero(&sin6->sin6_addr,
6628348SEric.Yu@Sun.COM 					    sizeof (sin6->sin6_addr));
66311042SErik.Nordmark@Sun.COM 					sin6->sin6_port = connp->conn_lport;
6648348SEric.Yu@Sun.COM 				} else {
6658348SEric.Yu@Sun.COM 					sin6 += added;
6668348SEric.Yu@Sun.COM 					sin6->sin6_family = AF_INET6;
66711042SErik.Nordmark@Sun.COM 					sin6->sin6_port = connp->conn_lport;
6688348SEric.Yu@Sun.COM 					sin6->sin6_addr = laddr;
6698348SEric.Yu@Sun.COM 				}
67011042SErik.Nordmark@Sun.COM 				sin6->sin6_flowinfo = connp->conn_flowinfo;
6718348SEric.Yu@Sun.COM 				sin6->sin6_scope_id = 0;
6728348SEric.Yu@Sun.COM 				sin6->__sin6_src_id = 0;
6738348SEric.Yu@Sun.COM 				break;
6748348SEric.Yu@Sun.COM 			}
6758348SEric.Yu@Sun.COM 			added++;
6768348SEric.Yu@Sun.COM 			if (added >= 1) {
6778348SEric.Yu@Sun.COM 				err = 0;
6788348SEric.Yu@Sun.COM 				goto done;
6798348SEric.Yu@Sun.COM 			}
6808348SEric.Yu@Sun.COM 			if (scanned >= sctp->sctp_nsaddrs)
6818348SEric.Yu@Sun.COM 				goto done;
6828348SEric.Yu@Sun.COM 
6838348SEric.Yu@Sun.COM 			/* LINTED: alignment */
6848348SEric.Yu@Sun.COM 			pnode = list_d2l(&sctp->sctp_saddrs[i].sctp_ipif_list,
6858348SEric.Yu@Sun.COM 			    pobj);
6868348SEric.Yu@Sun.COM 			if (mdb_vread(&node, sizeof (list_node_t),
6878348SEric.Yu@Sun.COM 			    (uintptr_t)pnode) == -1) {
6888348SEric.Yu@Sun.COM 				mdb_warn("failed to read list_node_t");
6898348SEric.Yu@Sun.COM 				return (err);
6908348SEric.Yu@Sun.COM 			}
6918348SEric.Yu@Sun.COM 			pobj = list_object(&sctp->sctp_saddrs[i].
6928348SEric.Yu@Sun.COM 			    sctp_ipif_list, node.list_next);
6938348SEric.Yu@Sun.COM 			if (mdb_vread(&obj, sizeof (sctp_saddr_ipif_t),
6948348SEric.Yu@Sun.COM 			    (uintptr_t)pobj) == -1) {
6958348SEric.Yu@Sun.COM 				mdb_warn("failed to read sctp_saddr_ipif_t");
6968348SEric.Yu@Sun.COM 				return (err);
6978348SEric.Yu@Sun.COM 			}
6988348SEric.Yu@Sun.COM 		}
6998348SEric.Yu@Sun.COM 	}
7008348SEric.Yu@Sun.COM done:
7018348SEric.Yu@Sun.COM 	return (err);
7028348SEric.Yu@Sun.COM }
7038348SEric.Yu@Sun.COM 
7048348SEric.Yu@Sun.COM /*
7058348SEric.Yu@Sun.COM  * SCTP interface for geting the primary peer address of a sctp_t.
7068348SEric.Yu@Sun.COM  */
7078348SEric.Yu@Sun.COM static int
sctp_getpeeraddr(sctp_t * sctp,struct sockaddr * addr)7088348SEric.Yu@Sun.COM sctp_getpeeraddr(sctp_t *sctp, struct sockaddr *addr)
7098348SEric.Yu@Sun.COM {
7108348SEric.Yu@Sun.COM 	struct sockaddr_in	*sin4;
7118348SEric.Yu@Sun.COM 	struct sockaddr_in6	*sin6;
7128348SEric.Yu@Sun.COM 	sctp_faddr_t		sctp_primary;
7138348SEric.Yu@Sun.COM 	in6_addr_t		faddr;
71411042SErik.Nordmark@Sun.COM 	conn_t			*connp = sctp->sctp_connp;
7158348SEric.Yu@Sun.COM 
7168348SEric.Yu@Sun.COM 	if (sctp->sctp_faddrs == NULL)
7178348SEric.Yu@Sun.COM 		return (-1);
7188348SEric.Yu@Sun.COM 
71911042SErik.Nordmark@Sun.COM 	addr->sa_family = connp->conn_family;
7208348SEric.Yu@Sun.COM 	if (mdb_vread(&sctp_primary, sizeof (sctp_faddr_t),
7218348SEric.Yu@Sun.COM 	    (uintptr_t)sctp->sctp_primary) == -1) {
7228348SEric.Yu@Sun.COM 		mdb_warn("failed to read sctp primary faddr");
7238348SEric.Yu@Sun.COM 		return (-1);
7248348SEric.Yu@Sun.COM 	}
725*13009SChandrasekar.Marimuthu@Sun.COM 	faddr = sctp_primary.sf_faddr;
7268348SEric.Yu@Sun.COM 
72711042SErik.Nordmark@Sun.COM 	switch (connp->conn_family) {
7288348SEric.Yu@Sun.COM 	case AF_INET:
7298348SEric.Yu@Sun.COM 		/* LINTED: alignment */
7308348SEric.Yu@Sun.COM 		sin4 = (struct sockaddr_in *)addr;
7318348SEric.Yu@Sun.COM 		IN6_V4MAPPED_TO_INADDR(&faddr, &sin4->sin_addr);
73211042SErik.Nordmark@Sun.COM 		sin4->sin_port = connp->conn_fport;
7338348SEric.Yu@Sun.COM 		sin4->sin_family = AF_INET;
7348348SEric.Yu@Sun.COM 		break;
7358348SEric.Yu@Sun.COM 
7368348SEric.Yu@Sun.COM 	case AF_INET6:
7378348SEric.Yu@Sun.COM 		/* LINTED: alignment */
7388348SEric.Yu@Sun.COM 		sin6 = (struct sockaddr_in6 *)addr;
7398348SEric.Yu@Sun.COM 		sin6->sin6_addr = faddr;
74011042SErik.Nordmark@Sun.COM 		sin6->sin6_port = connp->conn_fport;
7418348SEric.Yu@Sun.COM 		sin6->sin6_family = AF_INET6;
7428348SEric.Yu@Sun.COM 		sin6->sin6_flowinfo = 0;
7438348SEric.Yu@Sun.COM 		sin6->sin6_scope_id = 0;
7448348SEric.Yu@Sun.COM 		sin6->__sin6_src_id = 0;
7458348SEric.Yu@Sun.COM 		break;
7468348SEric.Yu@Sun.COM 	}
7478348SEric.Yu@Sun.COM 
7488348SEric.Yu@Sun.COM 	return (0);
7498348SEric.Yu@Sun.COM }
7508348SEric.Yu@Sun.COM 
7518348SEric.Yu@Sun.COM static int
tpi_sock_print(sotpi_sonode_t * sotpi_sonode)7528348SEric.Yu@Sun.COM tpi_sock_print(sotpi_sonode_t *sotpi_sonode)
7538348SEric.Yu@Sun.COM {
7548348SEric.Yu@Sun.COM 	if (sotpi_sonode->st_info.sti_laddr_valid == 1) {
7558348SEric.Yu@Sun.COM 		struct sockaddr *laddr =
7568348SEric.Yu@Sun.COM 		    mdb_alloc(sotpi_sonode->st_info.sti_laddr_len, UM_SLEEP);
7578348SEric.Yu@Sun.COM 		if (mdb_vread(laddr, sotpi_sonode->st_info.sti_laddr_len,
7588348SEric.Yu@Sun.COM 		    (uintptr_t)sotpi_sonode->st_info.sti_laddr_sa) == -1) {
7598348SEric.Yu@Sun.COM 			mdb_warn("failed to read sotpi_sonode socket addr");
7608348SEric.Yu@Sun.COM 			return (-1);
7618348SEric.Yu@Sun.COM 		}
7628348SEric.Yu@Sun.COM 
7638348SEric.Yu@Sun.COM 		mdb_printf("socket: ");
7648348SEric.Yu@Sun.COM 		pfiles_print_addr(laddr);
7658348SEric.Yu@Sun.COM 	}
7668348SEric.Yu@Sun.COM 
7678348SEric.Yu@Sun.COM 	if (sotpi_sonode->st_info.sti_faddr_valid == 1) {
7688348SEric.Yu@Sun.COM 		struct sockaddr *faddr =
7698348SEric.Yu@Sun.COM 		    mdb_alloc(sotpi_sonode->st_info.sti_faddr_len, UM_SLEEP);
7708348SEric.Yu@Sun.COM 		if (mdb_vread(faddr, sotpi_sonode->st_info.sti_faddr_len,
7718348SEric.Yu@Sun.COM 		    (uintptr_t)sotpi_sonode->st_info.sti_faddr_sa) == -1) {
7728348SEric.Yu@Sun.COM 			mdb_warn("failed to read sotpi_sonode remote addr");
7738348SEric.Yu@Sun.COM 			return (-1);
7748348SEric.Yu@Sun.COM 		}
7758348SEric.Yu@Sun.COM 
7768348SEric.Yu@Sun.COM 		mdb_printf("remote: ");
7778348SEric.Yu@Sun.COM 		pfiles_print_addr(faddr);
7788348SEric.Yu@Sun.COM 	}
7798348SEric.Yu@Sun.COM 
7808348SEric.Yu@Sun.COM 	return (0);
7818348SEric.Yu@Sun.COM }
7828348SEric.Yu@Sun.COM 
7838348SEric.Yu@Sun.COM static int
tcpip_sock_print(struct sonode * socknode)7848348SEric.Yu@Sun.COM tcpip_sock_print(struct sonode *socknode)
7858348SEric.Yu@Sun.COM {
7868348SEric.Yu@Sun.COM 	switch (socknode->so_family) {
7878348SEric.Yu@Sun.COM 	case AF_INET:
7888348SEric.Yu@Sun.COM 	{
7898348SEric.Yu@Sun.COM 		conn_t conn_t;
7908348SEric.Yu@Sun.COM 		in_port_t port;
7918348SEric.Yu@Sun.COM 
7928348SEric.Yu@Sun.COM 		if (mdb_vread(&conn_t, sizeof (conn_t),
7938348SEric.Yu@Sun.COM 		    (uintptr_t)socknode->so_proto_handle) == -1) {
7948348SEric.Yu@Sun.COM 			mdb_warn("failed to read conn_t V4");
7958348SEric.Yu@Sun.COM 			return (-1);
7968348SEric.Yu@Sun.COM 		}
7978348SEric.Yu@Sun.COM 
7988348SEric.Yu@Sun.COM 		mdb_printf("socket: ");
7998348SEric.Yu@Sun.COM 		mdb_nhconvert(&port, &conn_t.conn_lport, sizeof (port));
80011042SErik.Nordmark@Sun.COM 		mdb_printf("AF_INET %I %d ", conn_t.conn_laddr_v4, port);
8018348SEric.Yu@Sun.COM 
8028348SEric.Yu@Sun.COM 		/*
8038348SEric.Yu@Sun.COM 		 * If this is a listening socket, we don't print
8048348SEric.Yu@Sun.COM 		 * the remote address.
8058348SEric.Yu@Sun.COM 		 */
8068348SEric.Yu@Sun.COM 		if (IPCL_IS_TCP(&conn_t) && IPCL_IS_BOUND(&conn_t) == 0 ||
8078348SEric.Yu@Sun.COM 		    IPCL_IS_UDP(&conn_t) && IPCL_IS_CONNECTED(&conn_t)) {
8088348SEric.Yu@Sun.COM 			mdb_printf("remote: ");
8098348SEric.Yu@Sun.COM 			mdb_nhconvert(&port, &conn_t.conn_fport, sizeof (port));
81011042SErik.Nordmark@Sun.COM 			mdb_printf("AF_INET %I %d ", conn_t.conn_faddr_v4,
81111042SErik.Nordmark@Sun.COM 			    port);
8128348SEric.Yu@Sun.COM 		}
8138348SEric.Yu@Sun.COM 
8148348SEric.Yu@Sun.COM 		break;
8158348SEric.Yu@Sun.COM 	}
8168348SEric.Yu@Sun.COM 
8178348SEric.Yu@Sun.COM 	case AF_INET6:
8188348SEric.Yu@Sun.COM 	{
8198348SEric.Yu@Sun.COM 		conn_t conn_t;
8208348SEric.Yu@Sun.COM 		in_port_t port;
8218348SEric.Yu@Sun.COM 
8228348SEric.Yu@Sun.COM 		if (mdb_vread(&conn_t, sizeof (conn_t),
8238348SEric.Yu@Sun.COM 		    (uintptr_t)socknode->so_proto_handle) == -1) {
8248348SEric.Yu@Sun.COM 			mdb_warn("failed to read conn_t V6");
8258348SEric.Yu@Sun.COM 			return (-1);
8268348SEric.Yu@Sun.COM 		}
8278348SEric.Yu@Sun.COM 
8288348SEric.Yu@Sun.COM 		mdb_printf("socket: ");
8298348SEric.Yu@Sun.COM 		mdb_nhconvert(&port, &conn_t.conn_lport, sizeof (port));
83011042SErik.Nordmark@Sun.COM 		mdb_printf("AF_INET6 %N %d ", &conn_t.conn_laddr_v4, port);
8318348SEric.Yu@Sun.COM 
8328348SEric.Yu@Sun.COM 		/*
8338348SEric.Yu@Sun.COM 		 * If this is a listening socket, we don't print
8348348SEric.Yu@Sun.COM 		 * the remote address.
8358348SEric.Yu@Sun.COM 		 */
8368348SEric.Yu@Sun.COM 		if (IPCL_IS_TCP(&conn_t) && IPCL_IS_BOUND(&conn_t) == 0 ||
8378348SEric.Yu@Sun.COM 		    IPCL_IS_UDP(&conn_t) && IPCL_IS_CONNECTED(&conn_t)) {
8388348SEric.Yu@Sun.COM 			mdb_printf("remote: ");
8398348SEric.Yu@Sun.COM 			mdb_nhconvert(&port, &conn_t.conn_fport, sizeof (port));
84011042SErik.Nordmark@Sun.COM 			mdb_printf("AF_INET6 %N %d ", &conn_t.conn_faddr_v6,
84111042SErik.Nordmark@Sun.COM 			    port);
8428348SEric.Yu@Sun.COM 		}
8438348SEric.Yu@Sun.COM 
8448348SEric.Yu@Sun.COM 		break;
8458348SEric.Yu@Sun.COM 	}
8468348SEric.Yu@Sun.COM 
8478348SEric.Yu@Sun.COM 	default:
8488348SEric.Yu@Sun.COM 		mdb_printf("AF_?? (%d)", socknode->so_family);
8498348SEric.Yu@Sun.COM 		break;
8508348SEric.Yu@Sun.COM 	}
8518348SEric.Yu@Sun.COM 
8528348SEric.Yu@Sun.COM 	return (0);
8538348SEric.Yu@Sun.COM }
8548348SEric.Yu@Sun.COM 
8558348SEric.Yu@Sun.COM static int
sctp_sock_print(struct sonode * socknode)8568348SEric.Yu@Sun.COM sctp_sock_print(struct sonode *socknode)
8578348SEric.Yu@Sun.COM {
8588348SEric.Yu@Sun.COM 	sctp_t sctp_t;
85911042SErik.Nordmark@Sun.COM 	conn_t conns;
8608348SEric.Yu@Sun.COM 
8618348SEric.Yu@Sun.COM 	struct sockaddr *laddr = mdb_alloc(sizeof (struct sockaddr), UM_SLEEP);
8628348SEric.Yu@Sun.COM 	struct sockaddr *faddr = mdb_alloc(sizeof (struct sockaddr), UM_SLEEP);
8638348SEric.Yu@Sun.COM 
8648348SEric.Yu@Sun.COM 	if (mdb_vread(&sctp_t, sizeof (sctp_t),
8658348SEric.Yu@Sun.COM 	    (uintptr_t)socknode->so_proto_handle) == -1) {
8668348SEric.Yu@Sun.COM 		mdb_warn("failed to read sctp_t");
8678348SEric.Yu@Sun.COM 		return (-1);
8688348SEric.Yu@Sun.COM 	}
8698348SEric.Yu@Sun.COM 
87011042SErik.Nordmark@Sun.COM 	if (mdb_vread(&conns, sizeof (conn_t),
87111042SErik.Nordmark@Sun.COM 	    (uintptr_t)sctp_t.sctp_connp) == -1) {
87211042SErik.Nordmark@Sun.COM 		mdb_warn("failed to read conn_t at %p",
87311042SErik.Nordmark@Sun.COM 		    (uintptr_t)sctp_t.sctp_connp);
87411042SErik.Nordmark@Sun.COM 		return (-1);
87511042SErik.Nordmark@Sun.COM 	}
87611042SErik.Nordmark@Sun.COM 	sctp_t.sctp_connp = &conns;
87711042SErik.Nordmark@Sun.COM 
8788348SEric.Yu@Sun.COM 	if (sctp_getsockaddr(&sctp_t, laddr) == 0) {
8798348SEric.Yu@Sun.COM 		mdb_printf("socket:");
8808348SEric.Yu@Sun.COM 		pfiles_print_addr(laddr);
8818348SEric.Yu@Sun.COM 	}
8828348SEric.Yu@Sun.COM 	if (sctp_getpeeraddr(&sctp_t, faddr) == 0) {
8838348SEric.Yu@Sun.COM 		mdb_printf("remote:");
8848348SEric.Yu@Sun.COM 		pfiles_print_addr(faddr);
8858348SEric.Yu@Sun.COM 	}
8868348SEric.Yu@Sun.COM 
8878348SEric.Yu@Sun.COM 	return (0);
8888348SEric.Yu@Sun.COM }
8898348SEric.Yu@Sun.COM 
8908348SEric.Yu@Sun.COM /* ARGSUSED */
8918348SEric.Yu@Sun.COM static int
sdp_sock_print(struct sonode * socknode)8928348SEric.Yu@Sun.COM sdp_sock_print(struct sonode *socknode)
8938348SEric.Yu@Sun.COM {
8948348SEric.Yu@Sun.COM 	return (0);
8958348SEric.Yu@Sun.COM }
8968348SEric.Yu@Sun.COM 
8978348SEric.Yu@Sun.COM struct sock_print {
8988348SEric.Yu@Sun.COM 	int	family;
8998348SEric.Yu@Sun.COM 	int	type;
9008348SEric.Yu@Sun.COM 	int	pro;
9018348SEric.Yu@Sun.COM 	int	(*print)(struct sonode *socknode);
9028348SEric.Yu@Sun.COM } sock_prints[] = {
9038348SEric.Yu@Sun.COM 	{ 2,	2,	0,	tcpip_sock_print },	/* /dev/tcp	*/
9048348SEric.Yu@Sun.COM 	{ 2,	2,	6,	tcpip_sock_print },	/* /dev/tcp	*/
9058348SEric.Yu@Sun.COM 	{ 26,	2,	0,	tcpip_sock_print },	/* /dev/tcp6	*/
9068348SEric.Yu@Sun.COM 	{ 26,	2,	6,	tcpip_sock_print },	/* /dev/tcp6	*/
9078348SEric.Yu@Sun.COM 	{ 2,	1,	0,	tcpip_sock_print },	/* /dev/udp	*/
9088348SEric.Yu@Sun.COM 	{ 2,	1,	17,	tcpip_sock_print },	/* /dev/udp	*/
9098348SEric.Yu@Sun.COM 	{ 26,	1,	0,	tcpip_sock_print },	/* /dev/udp6	*/
9108348SEric.Yu@Sun.COM 	{ 26,	1,	17,	tcpip_sock_print },	/* /dev/udp6	*/
9118348SEric.Yu@Sun.COM 	{ 2,	4,	0,	tcpip_sock_print },	/* /dev/rawip	*/
9128348SEric.Yu@Sun.COM 	{ 26,	4,	0,	tcpip_sock_print },	/* /dev/rawip6	*/
9138348SEric.Yu@Sun.COM 	{ 2,	2,	132,	sctp_sock_print },	/* /dev/sctp	*/
9148348SEric.Yu@Sun.COM 	{ 26,	2,	132,	sctp_sock_print },	/* /dev/sctp6	*/
9158348SEric.Yu@Sun.COM 	{ 2,	6,	132,	sctp_sock_print },	/* /dev/sctp	*/
9168348SEric.Yu@Sun.COM 	{ 26,	6,	132,	sctp_sock_print },	/* /dev/sctp6	*/
9178348SEric.Yu@Sun.COM 	{ 24,	4,	0,	tcpip_sock_print },	/* /dev/rts	*/
9188348SEric.Yu@Sun.COM 	{ 2,	2,	257,	sdp_sock_print },	/* /dev/sdp	*/
9198348SEric.Yu@Sun.COM 	{ 26,	2,	257,	sdp_sock_print },	/* /dev/sdp	*/
9208348SEric.Yu@Sun.COM };
9218348SEric.Yu@Sun.COM 
9228348SEric.Yu@Sun.COM #define	NUM_SOCK_PRINTS                                         \
9238348SEric.Yu@Sun.COM 	(sizeof (sock_prints) / sizeof (struct sock_print))
9248348SEric.Yu@Sun.COM 
9250Sstevel@tonic-gate static int
pfile_callback(uintptr_t addr,const struct file * f,struct pfiles_cbdata * cb)9260Sstevel@tonic-gate pfile_callback(uintptr_t addr, const struct file *f, struct pfiles_cbdata *cb)
9270Sstevel@tonic-gate {
9280Sstevel@tonic-gate 	vnode_t v, layer_vn;
9290Sstevel@tonic-gate 	int myfd = cb->fd;
9300Sstevel@tonic-gate 	const char *type;
9310Sstevel@tonic-gate 	char path[MAXPATHLEN];
9320Sstevel@tonic-gate 	uintptr_t top_vnodep, realvpp;
9330Sstevel@tonic-gate 	char fsname[_ST_FSTYPSZ];
9340Sstevel@tonic-gate 	int err, i;
9350Sstevel@tonic-gate 
9360Sstevel@tonic-gate 	cb->fd++;
9370Sstevel@tonic-gate 
9380Sstevel@tonic-gate 	if (addr == NULL) {
9390Sstevel@tonic-gate 		return (WALK_NEXT);
9400Sstevel@tonic-gate 	}
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate 	top_vnodep = realvpp = (uintptr_t)f->f_vnode;
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate 	if (mdb_vread(&v, sizeof (v), realvpp) == -1) {
9450Sstevel@tonic-gate 		mdb_warn("failed to read vnode");
9460Sstevel@tonic-gate 		return (DCMD_ERR);
9470Sstevel@tonic-gate 	}
9480Sstevel@tonic-gate 
9490Sstevel@tonic-gate 	type = "?";
9500Sstevel@tonic-gate 	for (i = 0; i <= NUM_FS_TYPES; i++) {
9510Sstevel@tonic-gate 		if (fs_types[i].type == v.v_type)
9520Sstevel@tonic-gate 			type = fs_types[i].name;
9530Sstevel@tonic-gate 	}
9540Sstevel@tonic-gate 
9550Sstevel@tonic-gate 	do {
9560Sstevel@tonic-gate 		uintptr_t next_realvpp;
9570Sstevel@tonic-gate 
9580Sstevel@tonic-gate 		err = next_realvp(realvpp, &layer_vn, &next_realvpp);
9590Sstevel@tonic-gate 		if (next_realvpp != NULL)
9600Sstevel@tonic-gate 			realvpp = next_realvpp;
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate 	} while (err == REALVP_CONTINUE);
9630Sstevel@tonic-gate 
9640Sstevel@tonic-gate 	if (err == REALVP_ERR) {
9650Sstevel@tonic-gate 		mdb_warn("failed to do realvp() for %p", realvpp);
9660Sstevel@tonic-gate 		return (DCMD_ERR);
9670Sstevel@tonic-gate 	}
9680Sstevel@tonic-gate 
9690Sstevel@tonic-gate 	if (read_fsname((uintptr_t)layer_vn.v_vfsp, fsname) == -1)
9700Sstevel@tonic-gate 		return (DCMD_ERR);
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate 	mdb_printf("%4d %4s %?0p ", myfd, type, top_vnodep);
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate 	if (cb->opt_p) {
9750Sstevel@tonic-gate 		if (pfiles_dig_pathname(top_vnodep, path) == -1)
9760Sstevel@tonic-gate 			return (DCMD_ERR);
9770Sstevel@tonic-gate 
9780Sstevel@tonic-gate 		mdb_printf("%s\n", path);
9790Sstevel@tonic-gate 		return (DCMD_OK);
9800Sstevel@tonic-gate 	}
9810Sstevel@tonic-gate 
9820Sstevel@tonic-gate 	/*
9830Sstevel@tonic-gate 	 * Sockets generally don't have interesting pathnames; we only
9840Sstevel@tonic-gate 	 * show those in the '-p' view.
9850Sstevel@tonic-gate 	 */
9860Sstevel@tonic-gate 	path[0] = '\0';
9870Sstevel@tonic-gate 	if (v.v_type != VSOCK) {
9880Sstevel@tonic-gate 		if (pfiles_dig_pathname(top_vnodep, path) == -1)
9890Sstevel@tonic-gate 			return (DCMD_ERR);
9900Sstevel@tonic-gate 	}
9910Sstevel@tonic-gate 	mdb_printf("%s%s", path, path[0] == '\0' ? "" : " ");
9920Sstevel@tonic-gate 
9930Sstevel@tonic-gate 	switch (v.v_type) {
9940Sstevel@tonic-gate 	case VDOOR:
9950Sstevel@tonic-gate 	{
9960Sstevel@tonic-gate 		door_node_t doornode;
9970Sstevel@tonic-gate 		proc_t pr;
9980Sstevel@tonic-gate 
9990Sstevel@tonic-gate 		if (mdb_vread(&doornode, sizeof (doornode),
10000Sstevel@tonic-gate 		    (uintptr_t)layer_vn.v_data) == -1) {
10010Sstevel@tonic-gate 			mdb_warn("failed to read door_node");
10020Sstevel@tonic-gate 			return (DCMD_ERR);
10030Sstevel@tonic-gate 		}
10040Sstevel@tonic-gate 
10050Sstevel@tonic-gate 		if (mdb_vread(&pr, sizeof (pr),
10060Sstevel@tonic-gate 		    (uintptr_t)doornode.door_target) == -1) {
10070Sstevel@tonic-gate 			mdb_warn("failed to read door server process %p",
10080Sstevel@tonic-gate 			    doornode.door_target);
10090Sstevel@tonic-gate 			return (DCMD_ERR);
10100Sstevel@tonic-gate 		}
10110Sstevel@tonic-gate 		mdb_printf("[door to '%s' (proc=%p)]", pr.p_user.u_comm,
10120Sstevel@tonic-gate 		    doornode.door_target);
10130Sstevel@tonic-gate 		break;
10140Sstevel@tonic-gate 	}
10150Sstevel@tonic-gate 
10160Sstevel@tonic-gate 	case VSOCK:
10170Sstevel@tonic-gate 	{
10188348SEric.Yu@Sun.COM 		vnode_t v_sock;
10198348SEric.Yu@Sun.COM 		struct sonode so;
10200Sstevel@tonic-gate 
10218348SEric.Yu@Sun.COM 		if (mdb_vread(&v_sock, sizeof (v_sock), realvpp) == -1) {
10228348SEric.Yu@Sun.COM 			mdb_warn("failed to read socket vnode");
10230Sstevel@tonic-gate 			return (DCMD_ERR);
10248348SEric.Yu@Sun.COM 		}
10250Sstevel@tonic-gate 
10260Sstevel@tonic-gate 		/*
10278348SEric.Yu@Sun.COM 		 * Sockets can be non-stream or stream, they have to be dealed
10288348SEric.Yu@Sun.COM 		 * with differently.
10290Sstevel@tonic-gate 		 */
10308348SEric.Yu@Sun.COM 		if (v_sock.v_stream == NULL) {
10318348SEric.Yu@Sun.COM 			if (pfiles_get_sonode(&v_sock, &so) == -1)
10320Sstevel@tonic-gate 				return (DCMD_ERR);
10338348SEric.Yu@Sun.COM 
10348348SEric.Yu@Sun.COM 			/* Pick the proper methods. */
10358348SEric.Yu@Sun.COM 			for (i = 0; i <= NUM_SOCK_PRINTS; i++) {
10368348SEric.Yu@Sun.COM 				if ((sock_prints[i].family == so.so_family &&
10378348SEric.Yu@Sun.COM 				    sock_prints[i].type == so.so_type &&
10388348SEric.Yu@Sun.COM 				    sock_prints[i].pro == so.so_protocol) ||
10398348SEric.Yu@Sun.COM 				    (sock_prints[i].family == so.so_family &&
10408348SEric.Yu@Sun.COM 				    sock_prints[i].type == so.so_type &&
10418348SEric.Yu@Sun.COM 				    so.so_type == SOCK_RAW)) {
10428348SEric.Yu@Sun.COM 					if ((*sock_prints[i].print)(&so) == -1)
10438348SEric.Yu@Sun.COM 						return (DCMD_ERR);
10448348SEric.Yu@Sun.COM 				}
10458348SEric.Yu@Sun.COM 			}
10468348SEric.Yu@Sun.COM 		} else {
10478348SEric.Yu@Sun.COM 			sotpi_sonode_t sotpi_sonode;
10488348SEric.Yu@Sun.COM 
10498348SEric.Yu@Sun.COM 			if (pfiles_get_sonode(&v_sock, &so) == -1)
10508348SEric.Yu@Sun.COM 				return (DCMD_ERR);
10518348SEric.Yu@Sun.COM 
10528348SEric.Yu@Sun.COM 			/*
10538348SEric.Yu@Sun.COM 			 * If the socket is a fallback socket, read its related
10548348SEric.Yu@Sun.COM 			 * information separately; otherwise, read it as a whole
10558348SEric.Yu@Sun.COM 			 * tpi socket.
10568348SEric.Yu@Sun.COM 			 */
10578348SEric.Yu@Sun.COM 			if (so.so_state & SS_FALLBACK_COMP) {
10588348SEric.Yu@Sun.COM 				sotpi_sonode.st_sonode = so;
10598348SEric.Yu@Sun.COM 
10608348SEric.Yu@Sun.COM 				if (mdb_vread(&(sotpi_sonode.st_info),
10618348SEric.Yu@Sun.COM 				    sizeof (sotpi_info_t),
10628348SEric.Yu@Sun.COM 				    (uintptr_t)so.so_priv) == -1)
10638348SEric.Yu@Sun.COM 					return (DCMD_ERR);
10648348SEric.Yu@Sun.COM 			} else {
10658348SEric.Yu@Sun.COM 				if (pfiles_get_tpi_sonode(&v_sock,
10668348SEric.Yu@Sun.COM 				    &sotpi_sonode) == -1)
10678348SEric.Yu@Sun.COM 					return (DCMD_ERR);
10680Sstevel@tonic-gate 			}
10690Sstevel@tonic-gate 
10708348SEric.Yu@Sun.COM 			if (tpi_sock_print(&sotpi_sonode) == -1)
10718348SEric.Yu@Sun.COM 				return (DCMD_ERR);
10720Sstevel@tonic-gate 		}
10730Sstevel@tonic-gate 
10740Sstevel@tonic-gate 		break;
10750Sstevel@tonic-gate 	}
10760Sstevel@tonic-gate 
10770Sstevel@tonic-gate 	case VPORT:
10780Sstevel@tonic-gate 		mdb_printf("[event port (port=%p)]", v.v_data);
10790Sstevel@tonic-gate 		break;
10800Sstevel@tonic-gate 
10810Sstevel@tonic-gate 	case VPROC:
10820Sstevel@tonic-gate 	{
10830Sstevel@tonic-gate 		prnode_t prnode;
10840Sstevel@tonic-gate 		prcommon_t prcommon;
10850Sstevel@tonic-gate 
10860Sstevel@tonic-gate 		if (mdb_vread(&prnode, sizeof (prnode),
10870Sstevel@tonic-gate 		    (uintptr_t)layer_vn.v_data) == -1) {
10880Sstevel@tonic-gate 			mdb_warn("failed to read prnode");
10890Sstevel@tonic-gate 			return (DCMD_ERR);
10900Sstevel@tonic-gate 		}
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate 		if (mdb_vread(&prcommon, sizeof (prcommon),
10930Sstevel@tonic-gate 		    (uintptr_t)prnode.pr_common) == -1) {
10940Sstevel@tonic-gate 			mdb_warn("failed to read prcommon %p",
10950Sstevel@tonic-gate 			    prnode.pr_common);
10960Sstevel@tonic-gate 			return (DCMD_ERR);
10970Sstevel@tonic-gate 		}
10980Sstevel@tonic-gate 
10990Sstevel@tonic-gate 		mdb_printf("(proc=%p)", prcommon.prc_proc);
11000Sstevel@tonic-gate 		break;
11010Sstevel@tonic-gate 	}
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	default:
11040Sstevel@tonic-gate 		break;
11050Sstevel@tonic-gate 	}
11060Sstevel@tonic-gate 
11070Sstevel@tonic-gate 	mdb_printf("\n");
11080Sstevel@tonic-gate 
11090Sstevel@tonic-gate 	return (WALK_NEXT);
11100Sstevel@tonic-gate }
11110Sstevel@tonic-gate 
11120Sstevel@tonic-gate static int
file_t_callback(uintptr_t addr,const struct file * f,struct pfiles_cbdata * cb)11130Sstevel@tonic-gate file_t_callback(uintptr_t addr, const struct file *f, struct pfiles_cbdata *cb)
11140Sstevel@tonic-gate {
11150Sstevel@tonic-gate 	int myfd = cb->fd;
11160Sstevel@tonic-gate 
11170Sstevel@tonic-gate 	cb->fd++;
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 	if (addr == NULL) {
11200Sstevel@tonic-gate 		return (WALK_NEXT);
11210Sstevel@tonic-gate 	}
11220Sstevel@tonic-gate 
11230Sstevel@tonic-gate 	/*
11240Sstevel@tonic-gate 	 * We really need 20 digits to print a 64-bit offset_t, but this
11250Sstevel@tonic-gate 	 * is exceedingly rare, so we cheat and assume a column width of 10
11260Sstevel@tonic-gate 	 * digits, in order to fit everything cleanly into 80 columns.
11270Sstevel@tonic-gate 	 */
11280Sstevel@tonic-gate 	mdb_printf("%?0p %4d %8x %?0p %10lld %?0p %4d\n",
11290Sstevel@tonic-gate 	    addr, myfd, f->f_flag, f->f_vnode, f->f_offset, f->f_cred,
11300Sstevel@tonic-gate 	    f->f_count);
11310Sstevel@tonic-gate 
11320Sstevel@tonic-gate 	return (WALK_NEXT);
11330Sstevel@tonic-gate }
11340Sstevel@tonic-gate 
11350Sstevel@tonic-gate int
pfiles(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)11360Sstevel@tonic-gate pfiles(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11370Sstevel@tonic-gate {
11380Sstevel@tonic-gate 	int opt_f = 0;
11390Sstevel@tonic-gate 
11400Sstevel@tonic-gate 	struct pfiles_cbdata cb;
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate 	bzero(&cb, sizeof (cb));
11430Sstevel@tonic-gate 
11440Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
11450Sstevel@tonic-gate 		return (DCMD_USAGE);
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
11480Sstevel@tonic-gate 	    'p', MDB_OPT_SETBITS, TRUE, &cb.opt_p,
11490Sstevel@tonic-gate 	    'f', MDB_OPT_SETBITS, TRUE, &opt_f, NULL) != argc)
11500Sstevel@tonic-gate 		return (DCMD_USAGE);
11510Sstevel@tonic-gate 
11520Sstevel@tonic-gate 	if (opt_f) {
11530Sstevel@tonic-gate 		mdb_printf("%<u>%?s %4s %8s %?s %10s %?s %4s%</u>\n", "FILE",
11540Sstevel@tonic-gate 		    "FD", "FLAG", "VNODE", "OFFSET", "CRED", "CNT");
11550Sstevel@tonic-gate 		if (mdb_pwalk("allfile", (mdb_walk_cb_t)file_t_callback, &cb,
11560Sstevel@tonic-gate 		    addr) == -1) {
11570Sstevel@tonic-gate 			mdb_warn("failed to walk 'allfile'");
11580Sstevel@tonic-gate 			return (DCMD_ERR);
11590Sstevel@tonic-gate 		}
11600Sstevel@tonic-gate 	} else {
11610Sstevel@tonic-gate 		mdb_printf("%<u>%-4s %4s %?s ", "FD", "TYPE", "VNODE");
11620Sstevel@tonic-gate 		if (cb.opt_p)
11630Sstevel@tonic-gate 			mdb_printf("PATH");
11640Sstevel@tonic-gate 		else
11650Sstevel@tonic-gate 			mdb_printf("INFO");
11660Sstevel@tonic-gate 		mdb_printf("%</u>\n");
11670Sstevel@tonic-gate 
11680Sstevel@tonic-gate 		if (mdb_pwalk("allfile", (mdb_walk_cb_t)pfile_callback, &cb,
11690Sstevel@tonic-gate 		    addr) == -1) {
11700Sstevel@tonic-gate 			mdb_warn("failed to walk 'allfile'");
11710Sstevel@tonic-gate 			return (DCMD_ERR);
11720Sstevel@tonic-gate 		}
11730Sstevel@tonic-gate 	}
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate 
11760Sstevel@tonic-gate 	return (DCMD_OK);
11770Sstevel@tonic-gate }
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate void
pfiles_help(void)11800Sstevel@tonic-gate pfiles_help(void)
11810Sstevel@tonic-gate {
11820Sstevel@tonic-gate 	mdb_printf(
11830Sstevel@tonic-gate 	    "Given the address of a process, print information about files\n"
11840Sstevel@tonic-gate 	    "which the process has open.  By default, this includes decoded\n"
11850Sstevel@tonic-gate 	    "information about the file depending on file and filesystem type\n"
11860Sstevel@tonic-gate 	    "\n"
11870Sstevel@tonic-gate 	    "\t-p\tPathnames; omit decoded information.  Only display "
11880Sstevel@tonic-gate 	    "pathnames\n"
11890Sstevel@tonic-gate 	    "\t-f\tfile_t view; show the file_t structure corresponding to "
11900Sstevel@tonic-gate 	    "the fd\n");
11910Sstevel@tonic-gate }
1192