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*8348SEric.Yu@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 270Sstevel@tonic-gate #include <mdb/mdb_ks.h> 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <sys/types.h> 300Sstevel@tonic-gate #include <sys/systm.h> 310Sstevel@tonic-gate #include <sys/door.h> 320Sstevel@tonic-gate #include <sys/file.h> 330Sstevel@tonic-gate #include <sys/mount.h> 340Sstevel@tonic-gate #include <sys/proc.h> 350Sstevel@tonic-gate #include <sys/procfs.h> 360Sstevel@tonic-gate #include <sys/proc/prdata.h> 370Sstevel@tonic-gate #include <sys/stat.h> 380Sstevel@tonic-gate #include <sys/vfs.h> 390Sstevel@tonic-gate #include <sys/vnode.h> 400Sstevel@tonic-gate #include <sys/fs/snode.h> 410Sstevel@tonic-gate #include <sys/fs/fifonode.h> 420Sstevel@tonic-gate #include <sys/fs/namenode.h> 430Sstevel@tonic-gate #include <sys/socket.h> 440Sstevel@tonic-gate #include <sys/stropts.h> 450Sstevel@tonic-gate #include <sys/socketvar.h> 460Sstevel@tonic-gate #include <sys/strsubr.h> 470Sstevel@tonic-gate #include <sys/un.h> 48*8348SEric.Yu@Sun.COM #include <fs/sockfs/socktpi_impl.h> 49*8348SEric.Yu@Sun.COM #include <inet/ipclassifier.h> 50*8348SEric.Yu@Sun.COM #include <inet/ip_if.h> 51*8348SEric.Yu@Sun.COM #include <inet/sctp/sctp_impl.h> 52*8348SEric.Yu@Sun.COM #include <inet/sctp/sctp_addr.h> 530Sstevel@tonic-gate 540Sstevel@tonic-gate int 550Sstevel@tonic-gate vfs_walk_init(mdb_walk_state_t *wsp) 560Sstevel@tonic-gate { 570Sstevel@tonic-gate if (wsp->walk_addr == NULL && 580Sstevel@tonic-gate mdb_readvar(&wsp->walk_addr, "rootvfs") == -1) { 590Sstevel@tonic-gate mdb_warn("failed to read 'rootvfs'"); 600Sstevel@tonic-gate return (WALK_ERR); 610Sstevel@tonic-gate } 620Sstevel@tonic-gate 630Sstevel@tonic-gate wsp->walk_data = (void *)wsp->walk_addr; 640Sstevel@tonic-gate return (WALK_NEXT); 650Sstevel@tonic-gate } 660Sstevel@tonic-gate 670Sstevel@tonic-gate int 680Sstevel@tonic-gate vfs_walk_step(mdb_walk_state_t *wsp) 690Sstevel@tonic-gate { 700Sstevel@tonic-gate vfs_t vfs; 710Sstevel@tonic-gate int status; 720Sstevel@tonic-gate 730Sstevel@tonic-gate if (mdb_vread(&vfs, sizeof (vfs), wsp->walk_addr) == -1) { 740Sstevel@tonic-gate mdb_warn("failed to read vfs_t at %p", wsp->walk_addr); 750Sstevel@tonic-gate return (WALK_DONE); 760Sstevel@tonic-gate } 770Sstevel@tonic-gate 780Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, &vfs, wsp->walk_cbdata); 790Sstevel@tonic-gate 800Sstevel@tonic-gate if (vfs.vfs_next == wsp->walk_data) 810Sstevel@tonic-gate return (WALK_DONE); 820Sstevel@tonic-gate 830Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)vfs.vfs_next; 840Sstevel@tonic-gate 850Sstevel@tonic-gate return (status); 860Sstevel@tonic-gate } 870Sstevel@tonic-gate 880Sstevel@tonic-gate /* 890Sstevel@tonic-gate * Utility routine to read in a filesystem name given a vfs pointer. If 900Sstevel@tonic-gate * no vfssw entry for the vfs is available (as is the case with some pseudo- 910Sstevel@tonic-gate * filesystems), we check against some known problem fs's: doorfs and 920Sstevel@tonic-gate * portfs. If that fails, we try to guess the filesystem name using 930Sstevel@tonic-gate * symbol names. fsname should be a buffer of size _ST_FSTYPSZ. 940Sstevel@tonic-gate */ 950Sstevel@tonic-gate static int 960Sstevel@tonic-gate read_fsname(uintptr_t vfsp, char *fsname) 970Sstevel@tonic-gate { 980Sstevel@tonic-gate vfs_t vfs; 990Sstevel@tonic-gate struct vfssw vfssw_entry; 1000Sstevel@tonic-gate GElf_Sym vfssw_sym, test_sym; 1010Sstevel@tonic-gate char testname[MDB_SYM_NAMLEN]; 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate if (mdb_vread(&vfs, sizeof (vfs), vfsp) == -1) { 1040Sstevel@tonic-gate mdb_warn("failed to read vfs %p", vfsp); 1050Sstevel@tonic-gate return (-1); 1060Sstevel@tonic-gate } 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate if (mdb_lookup_by_name("vfssw", &vfssw_sym) == -1) { 1090Sstevel@tonic-gate mdb_warn("failed to find vfssw"); 1100Sstevel@tonic-gate return (-1); 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate /* 1140Sstevel@tonic-gate * vfssw is an array; we need vfssw[vfs.vfs_fstype]. 1150Sstevel@tonic-gate */ 1160Sstevel@tonic-gate if (mdb_vread(&vfssw_entry, sizeof (vfssw_entry), 1170Sstevel@tonic-gate vfssw_sym.st_value + (sizeof (struct vfssw) * vfs.vfs_fstype)) 1180Sstevel@tonic-gate == -1) { 1190Sstevel@tonic-gate mdb_warn("failed to read vfssw index %d", vfs.vfs_fstype); 1200Sstevel@tonic-gate return (-1); 1210Sstevel@tonic-gate } 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate if (vfs.vfs_fstype != 0) { 1240Sstevel@tonic-gate if (mdb_readstr(fsname, _ST_FSTYPSZ, 1250Sstevel@tonic-gate (uintptr_t)vfssw_entry.vsw_name) == -1) { 1260Sstevel@tonic-gate mdb_warn("failed to find fs name %p", 1270Sstevel@tonic-gate vfssw_entry.vsw_name); 1280Sstevel@tonic-gate return (-1); 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate return (0); 1310Sstevel@tonic-gate } 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /* 1340Sstevel@tonic-gate * Do precise detection for certain filesystem types that we 1350Sstevel@tonic-gate * know do not appear in vfssw[], and that we depend upon in other 1360Sstevel@tonic-gate * parts of the code: doorfs and portfs. 1370Sstevel@tonic-gate */ 1380Sstevel@tonic-gate if (mdb_lookup_by_name("door_vfs", &test_sym) != -1) { 1390Sstevel@tonic-gate if (test_sym.st_value == vfsp) { 1400Sstevel@tonic-gate strcpy(fsname, "doorfs"); 1410Sstevel@tonic-gate return (0); 1420Sstevel@tonic-gate } 1430Sstevel@tonic-gate } 1440Sstevel@tonic-gate if (mdb_lookup_by_name("port_vfs", &test_sym) != -1) { 1450Sstevel@tonic-gate if (test_sym.st_value == vfsp) { 1460Sstevel@tonic-gate strcpy(fsname, "portfs"); 1470Sstevel@tonic-gate return (0); 1480Sstevel@tonic-gate } 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate /* 1520Sstevel@tonic-gate * Heuristic detection for other filesystems that don't have a 1530Sstevel@tonic-gate * vfssw[] entry. These tend to be named <fsname>_vfs, so we do a 1540Sstevel@tonic-gate * lookup_by_addr and see if we find a symbol of that name. 1550Sstevel@tonic-gate */ 1560Sstevel@tonic-gate if (mdb_lookup_by_addr(vfsp, MDB_SYM_EXACT, testname, sizeof (testname), 1570Sstevel@tonic-gate &test_sym) != -1) { 1580Sstevel@tonic-gate if ((strlen(testname) > 4) && 1590Sstevel@tonic-gate (strcmp(testname + strlen(testname) - 4, "_vfs") == 0)) { 1600Sstevel@tonic-gate testname[strlen(testname) - 4] = '\0'; 1610Sstevel@tonic-gate strncpy(fsname, testname, _ST_FSTYPSZ); 1620Sstevel@tonic-gate return (0); 1630Sstevel@tonic-gate } 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate mdb_warn("unknown filesystem type for vfs %p", vfsp); 1670Sstevel@tonic-gate return (-1); 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate /* 1710Sstevel@tonic-gate * Column widths for mount point display in ::fsinfo output. 1720Sstevel@tonic-gate */ 1730Sstevel@tonic-gate #ifdef _LP64 1740Sstevel@tonic-gate #define FSINFO_MNTLEN 48 1750Sstevel@tonic-gate #else 1760Sstevel@tonic-gate #define FSINFO_MNTLEN 56 1770Sstevel@tonic-gate #endif 1780Sstevel@tonic-gate 179*8348SEric.Yu@Sun.COM /* ARGSUSED */ 1800Sstevel@tonic-gate int 1810Sstevel@tonic-gate fsinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1820Sstevel@tonic-gate { 1830Sstevel@tonic-gate vfs_t vfs; 1840Sstevel@tonic-gate int len; 1850Sstevel@tonic-gate int opt_v = 0; 1860Sstevel@tonic-gate char buf[MAXPATHLEN]; 1870Sstevel@tonic-gate char fsname[_ST_FSTYPSZ]; 1880Sstevel@tonic-gate mntopt_t *mntopts; 1890Sstevel@tonic-gate size_t size; 1900Sstevel@tonic-gate int i; 1910Sstevel@tonic-gate int first = 1; 1920Sstevel@tonic-gate char opt[MAX_MNTOPT_STR]; 1930Sstevel@tonic-gate uintptr_t global_zone; 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 1960Sstevel@tonic-gate if (mdb_walk_dcmd("vfs", "fsinfo", argc, argv) == -1) { 1970Sstevel@tonic-gate mdb_warn("failed to walk file system list"); 1980Sstevel@tonic-gate return (DCMD_ERR); 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate return (DCMD_OK); 2010Sstevel@tonic-gate } 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate if (mdb_getopts(argc, argv, 2040Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc) 2050Sstevel@tonic-gate return (DCMD_USAGE); 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) 2080Sstevel@tonic-gate mdb_printf("%<u>%?s %-15s %s%</u>\n", 2090Sstevel@tonic-gate "VFSP", "FS", "MOUNT"); 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate if (mdb_vread(&vfs, sizeof (vfs), addr) == -1) { 2120Sstevel@tonic-gate mdb_warn("failed to read vfs_t %p", addr); 2130Sstevel@tonic-gate return (DCMD_ERR); 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate if ((len = mdb_read_refstr((uintptr_t)vfs.vfs_mntpt, buf, 2170Sstevel@tonic-gate sizeof (buf))) <= 0) 2180Sstevel@tonic-gate strcpy(buf, "??"); 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate else if (!opt_v && (len >= FSINFO_MNTLEN)) 2210Sstevel@tonic-gate /* 2220Sstevel@tonic-gate * In normal mode, we truncate the path to keep the output 2230Sstevel@tonic-gate * clean. In -v mode, we just print the full path. 2240Sstevel@tonic-gate */ 2250Sstevel@tonic-gate strcpy(&buf[FSINFO_MNTLEN - 4], "..."); 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate if (read_fsname(addr, fsname) == -1) 2280Sstevel@tonic-gate return (DCMD_ERR); 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate mdb_printf("%0?p %-15s %s\n", addr, fsname, buf); 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate if (!opt_v) 2330Sstevel@tonic-gate return (DCMD_OK); 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate /* 2360Sstevel@tonic-gate * Print 'resource' string; this shows what we're mounted upon. 2370Sstevel@tonic-gate */ 2380Sstevel@tonic-gate if (mdb_read_refstr((uintptr_t)vfs.vfs_resource, buf, 2390Sstevel@tonic-gate MAXPATHLEN) <= 0) 2400Sstevel@tonic-gate strcpy(buf, "??"); 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate mdb_printf("%?s %s\n", "R:", buf); 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate /* 2450Sstevel@tonic-gate * Print mount options array; it sucks to be a mimic, but we copy 2460Sstevel@tonic-gate * the same logic as in mntvnops.c for adding zone= tags, and we 2470Sstevel@tonic-gate * don't bother with the obsolete dev= option. 2480Sstevel@tonic-gate */ 2490Sstevel@tonic-gate size = vfs.vfs_mntopts.mo_count * sizeof (mntopt_t); 2500Sstevel@tonic-gate mntopts = mdb_alloc(size, UM_SLEEP | UM_GC); 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate if (mdb_vread(mntopts, size, 2530Sstevel@tonic-gate (uintptr_t)vfs.vfs_mntopts.mo_list) == -1) { 2540Sstevel@tonic-gate mdb_warn("failed to read mntopts %p", vfs.vfs_mntopts.mo_list); 2550Sstevel@tonic-gate return (DCMD_ERR); 2560Sstevel@tonic-gate } 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate for (i = 0; i < vfs.vfs_mntopts.mo_count; i++) { 2590Sstevel@tonic-gate if (mntopts[i].mo_flags & MO_SET) { 2600Sstevel@tonic-gate if (mdb_readstr(opt, sizeof (opt), 2610Sstevel@tonic-gate (uintptr_t)mntopts[i].mo_name) == -1) { 2620Sstevel@tonic-gate mdb_warn("failed to read mntopt name %p", 2630Sstevel@tonic-gate mntopts[i].mo_name); 2640Sstevel@tonic-gate return (DCMD_ERR); 2650Sstevel@tonic-gate } 2660Sstevel@tonic-gate if (first) { 2670Sstevel@tonic-gate mdb_printf("%?s ", "O:"); 2680Sstevel@tonic-gate first = 0; 2690Sstevel@tonic-gate } else { 2700Sstevel@tonic-gate mdb_printf(","); 2710Sstevel@tonic-gate } 2720Sstevel@tonic-gate mdb_printf("%s", opt); 2730Sstevel@tonic-gate if (mntopts[i].mo_flags & MO_HASVALUE) { 2740Sstevel@tonic-gate if (mdb_readstr(opt, sizeof (opt), 2750Sstevel@tonic-gate (uintptr_t)mntopts[i].mo_arg) == -1) { 2760Sstevel@tonic-gate mdb_warn("failed to read mntopt " 2770Sstevel@tonic-gate "value %p", mntopts[i].mo_arg); 2780Sstevel@tonic-gate return (DCMD_ERR); 2790Sstevel@tonic-gate } 2800Sstevel@tonic-gate mdb_printf("=%s", opt); 2810Sstevel@tonic-gate } 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate } 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate if (mdb_readvar(&global_zone, "global_zone") == -1) { 2860Sstevel@tonic-gate mdb_warn("failed to locate global_zone"); 2870Sstevel@tonic-gate return (DCMD_ERR); 2880Sstevel@tonic-gate } 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate if ((vfs.vfs_zone != NULL) && 2910Sstevel@tonic-gate ((uintptr_t)vfs.vfs_zone != global_zone)) { 2920Sstevel@tonic-gate zone_t z; 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate if (mdb_vread(&z, sizeof (z), (uintptr_t)vfs.vfs_zone) == -1) { 2950Sstevel@tonic-gate mdb_warn("failed to read zone"); 2960Sstevel@tonic-gate return (DCMD_ERR); 2970Sstevel@tonic-gate } 2980Sstevel@tonic-gate /* 2990Sstevel@tonic-gate * zone names are much shorter than MAX_MNTOPT_STR 3000Sstevel@tonic-gate */ 3010Sstevel@tonic-gate if (mdb_readstr(opt, sizeof (opt), 3020Sstevel@tonic-gate (uintptr_t)z.zone_name) == -1) { 3030Sstevel@tonic-gate mdb_warn("failed to read zone name"); 3040Sstevel@tonic-gate return (DCMD_ERR); 3050Sstevel@tonic-gate } 3060Sstevel@tonic-gate if (first) { 3070Sstevel@tonic-gate mdb_printf("%?s ", "O:"); 3080Sstevel@tonic-gate } else { 3090Sstevel@tonic-gate mdb_printf(","); 3100Sstevel@tonic-gate } 3110Sstevel@tonic-gate mdb_printf("zone=%s", opt); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate return (DCMD_OK); 3140Sstevel@tonic-gate } 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate #define REALVP_DONE 0 3180Sstevel@tonic-gate #define REALVP_ERR 1 3190Sstevel@tonic-gate #define REALVP_CONTINUE 2 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate static int 3220Sstevel@tonic-gate next_realvp(uintptr_t invp, struct vnode *outvn, uintptr_t *outvp) 3230Sstevel@tonic-gate { 3240Sstevel@tonic-gate char fsname[_ST_FSTYPSZ]; 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate *outvp = invp; 3270Sstevel@tonic-gate if (mdb_vread(outvn, sizeof (struct vnode), invp) == -1) { 3280Sstevel@tonic-gate mdb_warn("failed to read vnode at %p", invp); 3290Sstevel@tonic-gate return (REALVP_ERR); 3300Sstevel@tonic-gate } 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate if (read_fsname((uintptr_t)outvn->v_vfsp, fsname) == -1) 3330Sstevel@tonic-gate return (REALVP_ERR); 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate /* 3360Sstevel@tonic-gate * We know how to do 'realvp' for as many filesystems as possible; 3370Sstevel@tonic-gate * for all other filesystems, we assume that the vp we are given 3380Sstevel@tonic-gate * is the realvp. In the kernel, a realvp operation will sometimes 3390Sstevel@tonic-gate * dig through multiple layers. Here, we only fetch the pointer 3400Sstevel@tonic-gate * to the next layer down. This allows dcmds to print out the 3410Sstevel@tonic-gate * various layers. 3420Sstevel@tonic-gate */ 3430Sstevel@tonic-gate if (strcmp(fsname, "fifofs") == 0) { 3440Sstevel@tonic-gate fifonode_t fn; 3450Sstevel@tonic-gate if (mdb_vread(&fn, sizeof (fn), 3460Sstevel@tonic-gate (uintptr_t)outvn->v_data) == -1) { 3470Sstevel@tonic-gate mdb_warn("failed to read fifonode"); 3480Sstevel@tonic-gate return (REALVP_ERR); 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate *outvp = (uintptr_t)fn.fn_realvp; 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate } else if (strcmp(fsname, "namefs") == 0) { 3530Sstevel@tonic-gate struct namenode nn; 3540Sstevel@tonic-gate if (mdb_vread(&nn, sizeof (nn), 3550Sstevel@tonic-gate (uintptr_t)outvn->v_data) == -1) { 3560Sstevel@tonic-gate mdb_warn("failed to read namenode"); 3570Sstevel@tonic-gate return (REALVP_ERR); 3580Sstevel@tonic-gate } 3590Sstevel@tonic-gate *outvp = (uintptr_t)nn.nm_filevp; 3600Sstevel@tonic-gate 3610Sstevel@tonic-gate } else if (outvn->v_type == VSOCK && outvn->v_stream != NULL) { 3620Sstevel@tonic-gate struct stdata stream; 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate /* 3650Sstevel@tonic-gate * Sockets have a strange and different layering scheme; we 3660Sstevel@tonic-gate * hop over into the sockfs vnode (accessible via the stream 3670Sstevel@tonic-gate * head) if possible. 3680Sstevel@tonic-gate */ 3690Sstevel@tonic-gate if (mdb_vread(&stream, sizeof (stream), 3700Sstevel@tonic-gate (uintptr_t)outvn->v_stream) == -1) { 3710Sstevel@tonic-gate mdb_warn("failed to read stream data"); 3720Sstevel@tonic-gate return (REALVP_ERR); 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate *outvp = (uintptr_t)stream.sd_vnode; 3750Sstevel@tonic-gate } 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate if (*outvp == invp || *outvp == NULL) 3780Sstevel@tonic-gate return (REALVP_DONE); 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate return (REALVP_CONTINUE); 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate static void 3840Sstevel@tonic-gate pfiles_print_addr(struct sockaddr *addr) 3850Sstevel@tonic-gate { 3860Sstevel@tonic-gate struct sockaddr_in *s_in; 3870Sstevel@tonic-gate struct sockaddr_un *s_un; 3880Sstevel@tonic-gate struct sockaddr_in6 *s_in6; 3893507Svb160487 in_port_t port; 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate switch (addr->sa_family) { 3920Sstevel@tonic-gate case AF_INET: 393*8348SEric.Yu@Sun.COM /* LINTED: alignment */ 3940Sstevel@tonic-gate s_in = (struct sockaddr_in *)addr; 3953507Svb160487 mdb_nhconvert(&port, &s_in->sin_port, sizeof (port)); 3963507Svb160487 mdb_printf("AF_INET %I %d ", s_in->sin_addr.s_addr, port); 3970Sstevel@tonic-gate break; 3980Sstevel@tonic-gate 3990Sstevel@tonic-gate case AF_INET6: 400*8348SEric.Yu@Sun.COM /* LINTED: alignment */ 4010Sstevel@tonic-gate s_in6 = (struct sockaddr_in6 *)addr; 4023507Svb160487 mdb_nhconvert(&port, &s_in6->sin6_port, sizeof (port)); 4033507Svb160487 mdb_printf("AF_INET6 %N %d ", &(s_in6->sin6_addr), port); 4040Sstevel@tonic-gate break; 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate case AF_UNIX: 4070Sstevel@tonic-gate s_un = (struct sockaddr_un *)addr; 4080Sstevel@tonic-gate mdb_printf("AF_UNIX %s ", s_un->sun_path); 4090Sstevel@tonic-gate break; 4100Sstevel@tonic-gate default: 4110Sstevel@tonic-gate mdb_printf("AF_?? (%d) ", addr->sa_family); 4120Sstevel@tonic-gate break; 4130Sstevel@tonic-gate } 4140Sstevel@tonic-gate } 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate static int 417*8348SEric.Yu@Sun.COM pfiles_get_sonode(vnode_t *v_sock, struct sonode *sonode) 4180Sstevel@tonic-gate { 419*8348SEric.Yu@Sun.COM if (mdb_vread(sonode, sizeof (struct sonode), 420*8348SEric.Yu@Sun.COM (uintptr_t)v_sock->v_data) == -1) { 421*8348SEric.Yu@Sun.COM mdb_warn("failed to read sonode"); 4220Sstevel@tonic-gate return (-1); 4230Sstevel@tonic-gate } 4240Sstevel@tonic-gate 425*8348SEric.Yu@Sun.COM return (0); 426*8348SEric.Yu@Sun.COM } 427*8348SEric.Yu@Sun.COM 428*8348SEric.Yu@Sun.COM static int 429*8348SEric.Yu@Sun.COM pfiles_get_tpi_sonode(vnode_t *v_sock, sotpi_sonode_t *sotpi_sonode) 430*8348SEric.Yu@Sun.COM { 431*8348SEric.Yu@Sun.COM 432*8348SEric.Yu@Sun.COM struct stdata stream; 433*8348SEric.Yu@Sun.COM 434*8348SEric.Yu@Sun.COM if (mdb_vread(&stream, sizeof (stream), 435*8348SEric.Yu@Sun.COM (uintptr_t)v_sock->v_stream) == -1) { 4360Sstevel@tonic-gate mdb_warn("failed to read stream data"); 4370Sstevel@tonic-gate return (-1); 4380Sstevel@tonic-gate } 4390Sstevel@tonic-gate 440*8348SEric.Yu@Sun.COM if (mdb_vread(v_sock, sizeof (vnode_t), 441*8348SEric.Yu@Sun.COM (uintptr_t)stream.sd_vnode) == -1) { 4420Sstevel@tonic-gate mdb_warn("failed to read stream vnode"); 4430Sstevel@tonic-gate return (-1); 4440Sstevel@tonic-gate } 4450Sstevel@tonic-gate 446*8348SEric.Yu@Sun.COM if (mdb_vread(sotpi_sonode, sizeof (sotpi_sonode_t), 447*8348SEric.Yu@Sun.COM (uintptr_t)v_sock->v_data) == -1) { 448*8348SEric.Yu@Sun.COM mdb_warn("failed to read sotpi_sonode"); 4490Sstevel@tonic-gate return (-1); 4500Sstevel@tonic-gate } 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate return (0); 4530Sstevel@tonic-gate } 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate /* 4560Sstevel@tonic-gate * Do some digging to get a reasonable pathname for this vnode. 'path' 4570Sstevel@tonic-gate * should point at a buffer of MAXPATHLEN in size. 4580Sstevel@tonic-gate */ 4590Sstevel@tonic-gate static int 4600Sstevel@tonic-gate pfiles_dig_pathname(uintptr_t vp, char *path) 4610Sstevel@tonic-gate { 4620Sstevel@tonic-gate vnode_t v; 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate bzero(path, MAXPATHLEN); 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate if (mdb_vread(&v, sizeof (v), vp) == -1) { 4670Sstevel@tonic-gate mdb_warn("failed to read vnode"); 4680Sstevel@tonic-gate return (-1); 4690Sstevel@tonic-gate } 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate if (v.v_path == NULL) { 4720Sstevel@tonic-gate /* 4730Sstevel@tonic-gate * fifo's and doors are special. Some have pathnames, and 4740Sstevel@tonic-gate * some do not. And for these, it is pointless to go off to 4750Sstevel@tonic-gate * mdb_vnode2path, which is very slow. 4760Sstevel@tonic-gate * 4770Sstevel@tonic-gate * Event ports never have a pathname. 4780Sstevel@tonic-gate */ 4790Sstevel@tonic-gate if (v.v_type == VFIFO || v.v_type == VDOOR || v.v_type == VPORT) 4800Sstevel@tonic-gate return (0); 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate /* 4830Sstevel@tonic-gate * For sockets, we won't find a path unless we print the path 484*8348SEric.Yu@Sun.COM * associated with transport's STREAM device. 4850Sstevel@tonic-gate */ 4860Sstevel@tonic-gate if (v.v_type == VSOCK) { 4870Sstevel@tonic-gate struct sonode sonode; 4880Sstevel@tonic-gate 489*8348SEric.Yu@Sun.COM if (pfiles_get_sonode(&v, &sonode) == -1) { 4900Sstevel@tonic-gate return (-1); 4910Sstevel@tonic-gate } 492*8348SEric.Yu@Sun.COM if (!SOCK_IS_NONSTR(&sonode)) { 493*8348SEric.Yu@Sun.COM struct sockparams *sp = sonode.so_sockparams; 494*8348SEric.Yu@Sun.COM vp = (uintptr_t)sp->sp_sdev_info.sd_vnode; 495*8348SEric.Yu@Sun.COM } else { 496*8348SEric.Yu@Sun.COM vp = NULL; 497*8348SEric.Yu@Sun.COM } 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate } 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate /* 5030Sstevel@tonic-gate * mdb_vnode2path will print an error for us as needed, but not 5040Sstevel@tonic-gate * finding a pathname is not really an error, so we plow on. 5050Sstevel@tonic-gate */ 5060Sstevel@tonic-gate (void) mdb_vnode2path(vp, path, MAXPATHLEN); 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate /* 5090Sstevel@tonic-gate * A common problem is that device pathnames are prefixed with 5100Sstevel@tonic-gate * /dev/../devices/. We just clean those up slightly: 5110Sstevel@tonic-gate * /dev/../devices/<mumble> --> /devices/<mumble> 5120Sstevel@tonic-gate * /dev/pts/../../devices/<mumble> --> /devices/<mumble> 5130Sstevel@tonic-gate */ 5140Sstevel@tonic-gate if (strncmp("/dev/../devices/", path, strlen("/dev/../devices/")) == 0) 5150Sstevel@tonic-gate strcpy(path, path + 7); 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate if (strncmp("/dev/pts/../../devices/", path, 5180Sstevel@tonic-gate strlen("/dev/pts/../../devices/")) == 0) 5190Sstevel@tonic-gate strcpy(path, path + 14); 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate return (0); 5220Sstevel@tonic-gate } 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate const struct fs_type { 5250Sstevel@tonic-gate int type; 5260Sstevel@tonic-gate const char *name; 5270Sstevel@tonic-gate } fs_types[] = { 5280Sstevel@tonic-gate { VNON, "NON" }, 5290Sstevel@tonic-gate { VREG, "REG" }, 5300Sstevel@tonic-gate { VDIR, "DIR" }, 5310Sstevel@tonic-gate { VBLK, "BLK" }, 5320Sstevel@tonic-gate { VCHR, "CHR" }, 5330Sstevel@tonic-gate { VLNK, "LNK" }, 5340Sstevel@tonic-gate { VFIFO, "FIFO" }, 5350Sstevel@tonic-gate { VDOOR, "DOOR" }, 5360Sstevel@tonic-gate { VPROC, "PROC" }, 5370Sstevel@tonic-gate { VSOCK, "SOCK" }, 5380Sstevel@tonic-gate { VPORT, "PORT" }, 5390Sstevel@tonic-gate { VBAD, "BAD" } 5400Sstevel@tonic-gate }; 5410Sstevel@tonic-gate 5420Sstevel@tonic-gate #define NUM_FS_TYPES (sizeof (fs_types) / sizeof (struct fs_type)) 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate struct pfiles_cbdata { 5450Sstevel@tonic-gate int opt_p; 5460Sstevel@tonic-gate int fd; 5470Sstevel@tonic-gate }; 5480Sstevel@tonic-gate 549*8348SEric.Yu@Sun.COM #define list_d2l(a, obj) ((list_node_t *)(((char *)obj) + (a)->list_offset)) 550*8348SEric.Yu@Sun.COM #define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset)) 551*8348SEric.Yu@Sun.COM 552*8348SEric.Yu@Sun.COM /* 553*8348SEric.Yu@Sun.COM * SCTP interface for geting the first source address of a sctp_t. 554*8348SEric.Yu@Sun.COM */ 555*8348SEric.Yu@Sun.COM int 556*8348SEric.Yu@Sun.COM sctp_getsockaddr(sctp_t *sctp, struct sockaddr *addr) 557*8348SEric.Yu@Sun.COM { 558*8348SEric.Yu@Sun.COM int err = -1; 559*8348SEric.Yu@Sun.COM int i; 560*8348SEric.Yu@Sun.COM int l; 561*8348SEric.Yu@Sun.COM sctp_saddr_ipif_t *pobj; 562*8348SEric.Yu@Sun.COM sctp_saddr_ipif_t obj; 563*8348SEric.Yu@Sun.COM size_t added = 0; 564*8348SEric.Yu@Sun.COM sin6_t *sin6; 565*8348SEric.Yu@Sun.COM sin_t *sin4; 566*8348SEric.Yu@Sun.COM int scanned = 0; 567*8348SEric.Yu@Sun.COM boolean_t skip_lback = B_FALSE; 568*8348SEric.Yu@Sun.COM 569*8348SEric.Yu@Sun.COM addr->sa_family = sctp->sctp_family; 570*8348SEric.Yu@Sun.COM if (sctp->sctp_nsaddrs == 0) 571*8348SEric.Yu@Sun.COM goto done; 572*8348SEric.Yu@Sun.COM 573*8348SEric.Yu@Sun.COM /* 574*8348SEric.Yu@Sun.COM * Skip loopback addresses for non-loopback assoc. 575*8348SEric.Yu@Sun.COM */ 576*8348SEric.Yu@Sun.COM if (sctp->sctp_state >= SCTPS_ESTABLISHED && !sctp->sctp_loopback) { 577*8348SEric.Yu@Sun.COM skip_lback = B_TRUE; 578*8348SEric.Yu@Sun.COM } 579*8348SEric.Yu@Sun.COM 580*8348SEric.Yu@Sun.COM for (i = 0; i < SCTP_IPIF_HASH; i++) { 581*8348SEric.Yu@Sun.COM if (sctp->sctp_saddrs[i].ipif_count == 0) 582*8348SEric.Yu@Sun.COM continue; 583*8348SEric.Yu@Sun.COM 584*8348SEric.Yu@Sun.COM pobj = list_object(&sctp->sctp_saddrs[i].sctp_ipif_list, 585*8348SEric.Yu@Sun.COM sctp->sctp_saddrs[i].sctp_ipif_list.list_head.list_next); 586*8348SEric.Yu@Sun.COM if (mdb_vread(&obj, sizeof (sctp_saddr_ipif_t), 587*8348SEric.Yu@Sun.COM (uintptr_t)pobj) == -1) { 588*8348SEric.Yu@Sun.COM mdb_warn("failed to read sctp_saddr_ipif_t"); 589*8348SEric.Yu@Sun.COM return (err); 590*8348SEric.Yu@Sun.COM } 591*8348SEric.Yu@Sun.COM 592*8348SEric.Yu@Sun.COM for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) { 593*8348SEric.Yu@Sun.COM sctp_ipif_t ipif; 594*8348SEric.Yu@Sun.COM in6_addr_t laddr; 595*8348SEric.Yu@Sun.COM list_node_t *pnode; 596*8348SEric.Yu@Sun.COM list_node_t node; 597*8348SEric.Yu@Sun.COM 598*8348SEric.Yu@Sun.COM if (mdb_vread(&ipif, sizeof (sctp_ipif_t), 599*8348SEric.Yu@Sun.COM (uintptr_t)obj.saddr_ipifp) == -1) { 600*8348SEric.Yu@Sun.COM mdb_warn("failed to read sctp_ipif_t"); 601*8348SEric.Yu@Sun.COM return (err); 602*8348SEric.Yu@Sun.COM } 603*8348SEric.Yu@Sun.COM laddr = ipif.sctp_ipif_saddr; 604*8348SEric.Yu@Sun.COM 605*8348SEric.Yu@Sun.COM scanned++; 606*8348SEric.Yu@Sun.COM if ((ipif.sctp_ipif_state == SCTP_IPIFS_CONDEMNED) || 607*8348SEric.Yu@Sun.COM SCTP_DONT_SRC(&obj) || 608*8348SEric.Yu@Sun.COM (ipif.sctp_ipif_ill->sctp_ill_flags & 609*8348SEric.Yu@Sun.COM PHYI_LOOPBACK) && skip_lback) { 610*8348SEric.Yu@Sun.COM if (scanned >= sctp->sctp_nsaddrs) 611*8348SEric.Yu@Sun.COM goto done; 612*8348SEric.Yu@Sun.COM 613*8348SEric.Yu@Sun.COM /* LINTED: alignment */ 614*8348SEric.Yu@Sun.COM pnode = list_d2l(&sctp->sctp_saddrs[i]. 615*8348SEric.Yu@Sun.COM sctp_ipif_list, pobj); 616*8348SEric.Yu@Sun.COM if (mdb_vread(&node, sizeof (list_node_t), 617*8348SEric.Yu@Sun.COM (uintptr_t)pnode) == -1) { 618*8348SEric.Yu@Sun.COM mdb_warn("failed to read list_node_t"); 619*8348SEric.Yu@Sun.COM return (err); 620*8348SEric.Yu@Sun.COM } 621*8348SEric.Yu@Sun.COM pobj = list_object(&sctp->sctp_saddrs[i]. 622*8348SEric.Yu@Sun.COM sctp_ipif_list, node.list_next); 623*8348SEric.Yu@Sun.COM if (mdb_vread(&obj, sizeof (sctp_saddr_ipif_t), 624*8348SEric.Yu@Sun.COM (uintptr_t)pobj) == -1) { 625*8348SEric.Yu@Sun.COM mdb_warn("failed to read " 626*8348SEric.Yu@Sun.COM "sctp_saddr_ipif_t"); 627*8348SEric.Yu@Sun.COM return (err); 628*8348SEric.Yu@Sun.COM } 629*8348SEric.Yu@Sun.COM continue; 630*8348SEric.Yu@Sun.COM } 631*8348SEric.Yu@Sun.COM 632*8348SEric.Yu@Sun.COM switch (sctp->sctp_family) { 633*8348SEric.Yu@Sun.COM case AF_INET: 634*8348SEric.Yu@Sun.COM /* LINTED: alignment */ 635*8348SEric.Yu@Sun.COM sin4 = (sin_t *)addr; 636*8348SEric.Yu@Sun.COM if ((sctp->sctp_state <= SCTPS_LISTEN) && 637*8348SEric.Yu@Sun.COM sctp->sctp_bound_to_all) { 638*8348SEric.Yu@Sun.COM sin4->sin_addr.s_addr = INADDR_ANY; 639*8348SEric.Yu@Sun.COM sin4->sin_port = sctp->sctp_lport; 640*8348SEric.Yu@Sun.COM } else { 641*8348SEric.Yu@Sun.COM sin4 += added; 642*8348SEric.Yu@Sun.COM sin4->sin_family = AF_INET; 643*8348SEric.Yu@Sun.COM sin4->sin_port = sctp->sctp_lport; 644*8348SEric.Yu@Sun.COM IN6_V4MAPPED_TO_INADDR(&laddr, 645*8348SEric.Yu@Sun.COM &sin4->sin_addr); 646*8348SEric.Yu@Sun.COM } 647*8348SEric.Yu@Sun.COM break; 648*8348SEric.Yu@Sun.COM 649*8348SEric.Yu@Sun.COM case AF_INET6: 650*8348SEric.Yu@Sun.COM /* LINTED: alignment */ 651*8348SEric.Yu@Sun.COM sin6 = (sin6_t *)addr; 652*8348SEric.Yu@Sun.COM if ((sctp->sctp_state <= SCTPS_LISTEN) && 653*8348SEric.Yu@Sun.COM sctp->sctp_bound_to_all) { 654*8348SEric.Yu@Sun.COM bzero(&sin6->sin6_addr, 655*8348SEric.Yu@Sun.COM sizeof (sin6->sin6_addr)); 656*8348SEric.Yu@Sun.COM sin6->sin6_port = sctp->sctp_lport; 657*8348SEric.Yu@Sun.COM } else { 658*8348SEric.Yu@Sun.COM sin6 += added; 659*8348SEric.Yu@Sun.COM sin6->sin6_family = AF_INET6; 660*8348SEric.Yu@Sun.COM sin6->sin6_port = sctp->sctp_lport; 661*8348SEric.Yu@Sun.COM sin6->sin6_addr = laddr; 662*8348SEric.Yu@Sun.COM } 663*8348SEric.Yu@Sun.COM sin6->sin6_flowinfo = sctp->sctp_ip6h->ip6_vcf & 664*8348SEric.Yu@Sun.COM ~IPV6_VERS_AND_FLOW_MASK; 665*8348SEric.Yu@Sun.COM sin6->sin6_scope_id = 0; 666*8348SEric.Yu@Sun.COM sin6->__sin6_src_id = 0; 667*8348SEric.Yu@Sun.COM break; 668*8348SEric.Yu@Sun.COM } 669*8348SEric.Yu@Sun.COM added++; 670*8348SEric.Yu@Sun.COM if (added >= 1) { 671*8348SEric.Yu@Sun.COM err = 0; 672*8348SEric.Yu@Sun.COM goto done; 673*8348SEric.Yu@Sun.COM } 674*8348SEric.Yu@Sun.COM if (scanned >= sctp->sctp_nsaddrs) 675*8348SEric.Yu@Sun.COM goto done; 676*8348SEric.Yu@Sun.COM 677*8348SEric.Yu@Sun.COM /* LINTED: alignment */ 678*8348SEric.Yu@Sun.COM pnode = list_d2l(&sctp->sctp_saddrs[i].sctp_ipif_list, 679*8348SEric.Yu@Sun.COM pobj); 680*8348SEric.Yu@Sun.COM if (mdb_vread(&node, sizeof (list_node_t), 681*8348SEric.Yu@Sun.COM (uintptr_t)pnode) == -1) { 682*8348SEric.Yu@Sun.COM mdb_warn("failed to read list_node_t"); 683*8348SEric.Yu@Sun.COM return (err); 684*8348SEric.Yu@Sun.COM } 685*8348SEric.Yu@Sun.COM pobj = list_object(&sctp->sctp_saddrs[i]. 686*8348SEric.Yu@Sun.COM sctp_ipif_list, node.list_next); 687*8348SEric.Yu@Sun.COM if (mdb_vread(&obj, sizeof (sctp_saddr_ipif_t), 688*8348SEric.Yu@Sun.COM (uintptr_t)pobj) == -1) { 689*8348SEric.Yu@Sun.COM mdb_warn("failed to read sctp_saddr_ipif_t"); 690*8348SEric.Yu@Sun.COM return (err); 691*8348SEric.Yu@Sun.COM } 692*8348SEric.Yu@Sun.COM } 693*8348SEric.Yu@Sun.COM } 694*8348SEric.Yu@Sun.COM done: 695*8348SEric.Yu@Sun.COM return (err); 696*8348SEric.Yu@Sun.COM } 697*8348SEric.Yu@Sun.COM 698*8348SEric.Yu@Sun.COM /* 699*8348SEric.Yu@Sun.COM * SCTP interface for geting the primary peer address of a sctp_t. 700*8348SEric.Yu@Sun.COM */ 701*8348SEric.Yu@Sun.COM static int 702*8348SEric.Yu@Sun.COM sctp_getpeeraddr(sctp_t *sctp, struct sockaddr *addr) 703*8348SEric.Yu@Sun.COM { 704*8348SEric.Yu@Sun.COM struct sockaddr_in *sin4; 705*8348SEric.Yu@Sun.COM struct sockaddr_in6 *sin6; 706*8348SEric.Yu@Sun.COM sctp_faddr_t sctp_primary; 707*8348SEric.Yu@Sun.COM in6_addr_t faddr; 708*8348SEric.Yu@Sun.COM 709*8348SEric.Yu@Sun.COM if (sctp->sctp_faddrs == NULL) 710*8348SEric.Yu@Sun.COM return (-1); 711*8348SEric.Yu@Sun.COM 712*8348SEric.Yu@Sun.COM addr->sa_family = sctp->sctp_family; 713*8348SEric.Yu@Sun.COM if (mdb_vread(&sctp_primary, sizeof (sctp_faddr_t), 714*8348SEric.Yu@Sun.COM (uintptr_t)sctp->sctp_primary) == -1) { 715*8348SEric.Yu@Sun.COM mdb_warn("failed to read sctp primary faddr"); 716*8348SEric.Yu@Sun.COM return (-1); 717*8348SEric.Yu@Sun.COM } 718*8348SEric.Yu@Sun.COM faddr = sctp_primary.faddr; 719*8348SEric.Yu@Sun.COM 720*8348SEric.Yu@Sun.COM switch (sctp->sctp_family) { 721*8348SEric.Yu@Sun.COM case AF_INET: 722*8348SEric.Yu@Sun.COM /* LINTED: alignment */ 723*8348SEric.Yu@Sun.COM sin4 = (struct sockaddr_in *)addr; 724*8348SEric.Yu@Sun.COM IN6_V4MAPPED_TO_INADDR(&faddr, &sin4->sin_addr); 725*8348SEric.Yu@Sun.COM sin4->sin_port = sctp->sctp_fport; 726*8348SEric.Yu@Sun.COM sin4->sin_family = AF_INET; 727*8348SEric.Yu@Sun.COM break; 728*8348SEric.Yu@Sun.COM 729*8348SEric.Yu@Sun.COM case AF_INET6: 730*8348SEric.Yu@Sun.COM /* LINTED: alignment */ 731*8348SEric.Yu@Sun.COM sin6 = (struct sockaddr_in6 *)addr; 732*8348SEric.Yu@Sun.COM sin6->sin6_addr = faddr; 733*8348SEric.Yu@Sun.COM sin6->sin6_port = sctp->sctp_fport; 734*8348SEric.Yu@Sun.COM sin6->sin6_family = AF_INET6; 735*8348SEric.Yu@Sun.COM sin6->sin6_flowinfo = 0; 736*8348SEric.Yu@Sun.COM sin6->sin6_scope_id = 0; 737*8348SEric.Yu@Sun.COM sin6->__sin6_src_id = 0; 738*8348SEric.Yu@Sun.COM break; 739*8348SEric.Yu@Sun.COM } 740*8348SEric.Yu@Sun.COM 741*8348SEric.Yu@Sun.COM return (0); 742*8348SEric.Yu@Sun.COM } 743*8348SEric.Yu@Sun.COM 744*8348SEric.Yu@Sun.COM static int 745*8348SEric.Yu@Sun.COM tpi_sock_print(sotpi_sonode_t *sotpi_sonode) 746*8348SEric.Yu@Sun.COM { 747*8348SEric.Yu@Sun.COM if (sotpi_sonode->st_info.sti_laddr_valid == 1) { 748*8348SEric.Yu@Sun.COM struct sockaddr *laddr = 749*8348SEric.Yu@Sun.COM mdb_alloc(sotpi_sonode->st_info.sti_laddr_len, UM_SLEEP); 750*8348SEric.Yu@Sun.COM if (mdb_vread(laddr, sotpi_sonode->st_info.sti_laddr_len, 751*8348SEric.Yu@Sun.COM (uintptr_t)sotpi_sonode->st_info.sti_laddr_sa) == -1) { 752*8348SEric.Yu@Sun.COM mdb_warn("failed to read sotpi_sonode socket addr"); 753*8348SEric.Yu@Sun.COM return (-1); 754*8348SEric.Yu@Sun.COM } 755*8348SEric.Yu@Sun.COM 756*8348SEric.Yu@Sun.COM mdb_printf("socket: "); 757*8348SEric.Yu@Sun.COM pfiles_print_addr(laddr); 758*8348SEric.Yu@Sun.COM } 759*8348SEric.Yu@Sun.COM 760*8348SEric.Yu@Sun.COM if (sotpi_sonode->st_info.sti_faddr_valid == 1) { 761*8348SEric.Yu@Sun.COM struct sockaddr *faddr = 762*8348SEric.Yu@Sun.COM mdb_alloc(sotpi_sonode->st_info.sti_faddr_len, UM_SLEEP); 763*8348SEric.Yu@Sun.COM if (mdb_vread(faddr, sotpi_sonode->st_info.sti_faddr_len, 764*8348SEric.Yu@Sun.COM (uintptr_t)sotpi_sonode->st_info.sti_faddr_sa) == -1) { 765*8348SEric.Yu@Sun.COM mdb_warn("failed to read sotpi_sonode remote addr"); 766*8348SEric.Yu@Sun.COM return (-1); 767*8348SEric.Yu@Sun.COM } 768*8348SEric.Yu@Sun.COM 769*8348SEric.Yu@Sun.COM mdb_printf("remote: "); 770*8348SEric.Yu@Sun.COM pfiles_print_addr(faddr); 771*8348SEric.Yu@Sun.COM } 772*8348SEric.Yu@Sun.COM 773*8348SEric.Yu@Sun.COM return (0); 774*8348SEric.Yu@Sun.COM } 775*8348SEric.Yu@Sun.COM 776*8348SEric.Yu@Sun.COM static int 777*8348SEric.Yu@Sun.COM tcpip_sock_print(struct sonode *socknode) 778*8348SEric.Yu@Sun.COM { 779*8348SEric.Yu@Sun.COM switch (socknode->so_family) { 780*8348SEric.Yu@Sun.COM case AF_INET: 781*8348SEric.Yu@Sun.COM { 782*8348SEric.Yu@Sun.COM conn_t conn_t; 783*8348SEric.Yu@Sun.COM in_port_t port; 784*8348SEric.Yu@Sun.COM 785*8348SEric.Yu@Sun.COM if (mdb_vread(&conn_t, sizeof (conn_t), 786*8348SEric.Yu@Sun.COM (uintptr_t)socknode->so_proto_handle) == -1) { 787*8348SEric.Yu@Sun.COM mdb_warn("failed to read conn_t V4"); 788*8348SEric.Yu@Sun.COM return (-1); 789*8348SEric.Yu@Sun.COM } 790*8348SEric.Yu@Sun.COM 791*8348SEric.Yu@Sun.COM mdb_printf("socket: "); 792*8348SEric.Yu@Sun.COM mdb_nhconvert(&port, &conn_t.conn_lport, sizeof (port)); 793*8348SEric.Yu@Sun.COM mdb_printf("AF_INET %I %d ", conn_t.conn_src, port); 794*8348SEric.Yu@Sun.COM 795*8348SEric.Yu@Sun.COM /* 796*8348SEric.Yu@Sun.COM * If this is a listening socket, we don't print 797*8348SEric.Yu@Sun.COM * the remote address. 798*8348SEric.Yu@Sun.COM */ 799*8348SEric.Yu@Sun.COM if (IPCL_IS_TCP(&conn_t) && IPCL_IS_BOUND(&conn_t) == 0 || 800*8348SEric.Yu@Sun.COM IPCL_IS_UDP(&conn_t) && IPCL_IS_CONNECTED(&conn_t)) { 801*8348SEric.Yu@Sun.COM mdb_printf("remote: "); 802*8348SEric.Yu@Sun.COM mdb_nhconvert(&port, &conn_t.conn_fport, sizeof (port)); 803*8348SEric.Yu@Sun.COM mdb_printf("AF_INET %I %d ", conn_t.conn_rem, port); 804*8348SEric.Yu@Sun.COM } 805*8348SEric.Yu@Sun.COM 806*8348SEric.Yu@Sun.COM break; 807*8348SEric.Yu@Sun.COM } 808*8348SEric.Yu@Sun.COM 809*8348SEric.Yu@Sun.COM case AF_INET6: 810*8348SEric.Yu@Sun.COM { 811*8348SEric.Yu@Sun.COM conn_t conn_t; 812*8348SEric.Yu@Sun.COM in_port_t port; 813*8348SEric.Yu@Sun.COM 814*8348SEric.Yu@Sun.COM if (mdb_vread(&conn_t, sizeof (conn_t), 815*8348SEric.Yu@Sun.COM (uintptr_t)socknode->so_proto_handle) == -1) { 816*8348SEric.Yu@Sun.COM mdb_warn("failed to read conn_t V6"); 817*8348SEric.Yu@Sun.COM return (-1); 818*8348SEric.Yu@Sun.COM } 819*8348SEric.Yu@Sun.COM 820*8348SEric.Yu@Sun.COM mdb_printf("socket: "); 821*8348SEric.Yu@Sun.COM mdb_nhconvert(&port, &conn_t.conn_lport, sizeof (port)); 822*8348SEric.Yu@Sun.COM mdb_printf("AF_INET6 %N %d ", &conn_t.conn_srcv6, port); 823*8348SEric.Yu@Sun.COM 824*8348SEric.Yu@Sun.COM /* 825*8348SEric.Yu@Sun.COM * If this is a listening socket, we don't print 826*8348SEric.Yu@Sun.COM * the remote address. 827*8348SEric.Yu@Sun.COM */ 828*8348SEric.Yu@Sun.COM if (IPCL_IS_TCP(&conn_t) && IPCL_IS_BOUND(&conn_t) == 0 || 829*8348SEric.Yu@Sun.COM IPCL_IS_UDP(&conn_t) && IPCL_IS_CONNECTED(&conn_t)) { 830*8348SEric.Yu@Sun.COM mdb_printf("remote: "); 831*8348SEric.Yu@Sun.COM mdb_nhconvert(&port, &conn_t.conn_fport, sizeof (port)); 832*8348SEric.Yu@Sun.COM mdb_printf("AF_INET6 %N %d ", &conn_t.conn_remv6, port); 833*8348SEric.Yu@Sun.COM } 834*8348SEric.Yu@Sun.COM 835*8348SEric.Yu@Sun.COM break; 836*8348SEric.Yu@Sun.COM } 837*8348SEric.Yu@Sun.COM 838*8348SEric.Yu@Sun.COM default: 839*8348SEric.Yu@Sun.COM mdb_printf("AF_?? (%d)", socknode->so_family); 840*8348SEric.Yu@Sun.COM break; 841*8348SEric.Yu@Sun.COM } 842*8348SEric.Yu@Sun.COM 843*8348SEric.Yu@Sun.COM return (0); 844*8348SEric.Yu@Sun.COM } 845*8348SEric.Yu@Sun.COM 846*8348SEric.Yu@Sun.COM static int 847*8348SEric.Yu@Sun.COM sctp_sock_print(struct sonode *socknode) 848*8348SEric.Yu@Sun.COM { 849*8348SEric.Yu@Sun.COM sctp_t sctp_t; 850*8348SEric.Yu@Sun.COM 851*8348SEric.Yu@Sun.COM struct sockaddr *laddr = mdb_alloc(sizeof (struct sockaddr), UM_SLEEP); 852*8348SEric.Yu@Sun.COM struct sockaddr *faddr = mdb_alloc(sizeof (struct sockaddr), UM_SLEEP); 853*8348SEric.Yu@Sun.COM 854*8348SEric.Yu@Sun.COM if (mdb_vread(&sctp_t, sizeof (sctp_t), 855*8348SEric.Yu@Sun.COM (uintptr_t)socknode->so_proto_handle) == -1) { 856*8348SEric.Yu@Sun.COM mdb_warn("failed to read sctp_t"); 857*8348SEric.Yu@Sun.COM return (-1); 858*8348SEric.Yu@Sun.COM } 859*8348SEric.Yu@Sun.COM 860*8348SEric.Yu@Sun.COM if (sctp_getsockaddr(&sctp_t, laddr) == 0) { 861*8348SEric.Yu@Sun.COM mdb_printf("socket:"); 862*8348SEric.Yu@Sun.COM pfiles_print_addr(laddr); 863*8348SEric.Yu@Sun.COM } 864*8348SEric.Yu@Sun.COM if (sctp_getpeeraddr(&sctp_t, faddr) == 0) { 865*8348SEric.Yu@Sun.COM mdb_printf("remote:"); 866*8348SEric.Yu@Sun.COM pfiles_print_addr(faddr); 867*8348SEric.Yu@Sun.COM } 868*8348SEric.Yu@Sun.COM 869*8348SEric.Yu@Sun.COM return (0); 870*8348SEric.Yu@Sun.COM } 871*8348SEric.Yu@Sun.COM 872*8348SEric.Yu@Sun.COM /* ARGSUSED */ 873*8348SEric.Yu@Sun.COM static int 874*8348SEric.Yu@Sun.COM sdp_sock_print(struct sonode *socknode) 875*8348SEric.Yu@Sun.COM { 876*8348SEric.Yu@Sun.COM return (0); 877*8348SEric.Yu@Sun.COM } 878*8348SEric.Yu@Sun.COM 879*8348SEric.Yu@Sun.COM struct sock_print { 880*8348SEric.Yu@Sun.COM int family; 881*8348SEric.Yu@Sun.COM int type; 882*8348SEric.Yu@Sun.COM int pro; 883*8348SEric.Yu@Sun.COM int (*print)(struct sonode *socknode); 884*8348SEric.Yu@Sun.COM } sock_prints[] = { 885*8348SEric.Yu@Sun.COM { 2, 2, 0, tcpip_sock_print }, /* /dev/tcp */ 886*8348SEric.Yu@Sun.COM { 2, 2, 6, tcpip_sock_print }, /* /dev/tcp */ 887*8348SEric.Yu@Sun.COM { 26, 2, 0, tcpip_sock_print }, /* /dev/tcp6 */ 888*8348SEric.Yu@Sun.COM { 26, 2, 6, tcpip_sock_print }, /* /dev/tcp6 */ 889*8348SEric.Yu@Sun.COM { 2, 1, 0, tcpip_sock_print }, /* /dev/udp */ 890*8348SEric.Yu@Sun.COM { 2, 1, 17, tcpip_sock_print }, /* /dev/udp */ 891*8348SEric.Yu@Sun.COM { 26, 1, 0, tcpip_sock_print }, /* /dev/udp6 */ 892*8348SEric.Yu@Sun.COM { 26, 1, 17, tcpip_sock_print }, /* /dev/udp6 */ 893*8348SEric.Yu@Sun.COM { 2, 4, 0, tcpip_sock_print }, /* /dev/rawip */ 894*8348SEric.Yu@Sun.COM { 26, 4, 0, tcpip_sock_print }, /* /dev/rawip6 */ 895*8348SEric.Yu@Sun.COM { 2, 2, 132, sctp_sock_print }, /* /dev/sctp */ 896*8348SEric.Yu@Sun.COM { 26, 2, 132, sctp_sock_print }, /* /dev/sctp6 */ 897*8348SEric.Yu@Sun.COM { 2, 6, 132, sctp_sock_print }, /* /dev/sctp */ 898*8348SEric.Yu@Sun.COM { 26, 6, 132, sctp_sock_print }, /* /dev/sctp6 */ 899*8348SEric.Yu@Sun.COM { 24, 4, 0, tcpip_sock_print }, /* /dev/rts */ 900*8348SEric.Yu@Sun.COM { 2, 2, 257, sdp_sock_print }, /* /dev/sdp */ 901*8348SEric.Yu@Sun.COM { 26, 2, 257, sdp_sock_print }, /* /dev/sdp */ 902*8348SEric.Yu@Sun.COM }; 903*8348SEric.Yu@Sun.COM 904*8348SEric.Yu@Sun.COM #define NUM_SOCK_PRINTS \ 905*8348SEric.Yu@Sun.COM (sizeof (sock_prints) / sizeof (struct sock_print)) 906*8348SEric.Yu@Sun.COM 9070Sstevel@tonic-gate static int 9080Sstevel@tonic-gate pfile_callback(uintptr_t addr, const struct file *f, struct pfiles_cbdata *cb) 9090Sstevel@tonic-gate { 9100Sstevel@tonic-gate vnode_t v, layer_vn; 9110Sstevel@tonic-gate int myfd = cb->fd; 9120Sstevel@tonic-gate const char *type; 9130Sstevel@tonic-gate char path[MAXPATHLEN]; 9140Sstevel@tonic-gate uintptr_t top_vnodep, realvpp; 9150Sstevel@tonic-gate char fsname[_ST_FSTYPSZ]; 9160Sstevel@tonic-gate int err, i; 9170Sstevel@tonic-gate 9180Sstevel@tonic-gate cb->fd++; 9190Sstevel@tonic-gate 9200Sstevel@tonic-gate if (addr == NULL) { 9210Sstevel@tonic-gate return (WALK_NEXT); 9220Sstevel@tonic-gate } 9230Sstevel@tonic-gate 9240Sstevel@tonic-gate top_vnodep = realvpp = (uintptr_t)f->f_vnode; 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate if (mdb_vread(&v, sizeof (v), realvpp) == -1) { 9270Sstevel@tonic-gate mdb_warn("failed to read vnode"); 9280Sstevel@tonic-gate return (DCMD_ERR); 9290Sstevel@tonic-gate } 9300Sstevel@tonic-gate 9310Sstevel@tonic-gate type = "?"; 9320Sstevel@tonic-gate for (i = 0; i <= NUM_FS_TYPES; i++) { 9330Sstevel@tonic-gate if (fs_types[i].type == v.v_type) 9340Sstevel@tonic-gate type = fs_types[i].name; 9350Sstevel@tonic-gate } 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate do { 9380Sstevel@tonic-gate uintptr_t next_realvpp; 9390Sstevel@tonic-gate 9400Sstevel@tonic-gate err = next_realvp(realvpp, &layer_vn, &next_realvpp); 9410Sstevel@tonic-gate if (next_realvpp != NULL) 9420Sstevel@tonic-gate realvpp = next_realvpp; 9430Sstevel@tonic-gate 9440Sstevel@tonic-gate } while (err == REALVP_CONTINUE); 9450Sstevel@tonic-gate 9460Sstevel@tonic-gate if (err == REALVP_ERR) { 9470Sstevel@tonic-gate mdb_warn("failed to do realvp() for %p", realvpp); 9480Sstevel@tonic-gate return (DCMD_ERR); 9490Sstevel@tonic-gate } 9500Sstevel@tonic-gate 9510Sstevel@tonic-gate if (read_fsname((uintptr_t)layer_vn.v_vfsp, fsname) == -1) 9520Sstevel@tonic-gate return (DCMD_ERR); 9530Sstevel@tonic-gate 9540Sstevel@tonic-gate mdb_printf("%4d %4s %?0p ", myfd, type, top_vnodep); 9550Sstevel@tonic-gate 9560Sstevel@tonic-gate if (cb->opt_p) { 9570Sstevel@tonic-gate if (pfiles_dig_pathname(top_vnodep, path) == -1) 9580Sstevel@tonic-gate return (DCMD_ERR); 9590Sstevel@tonic-gate 9600Sstevel@tonic-gate mdb_printf("%s\n", path); 9610Sstevel@tonic-gate return (DCMD_OK); 9620Sstevel@tonic-gate } 9630Sstevel@tonic-gate 9640Sstevel@tonic-gate /* 9650Sstevel@tonic-gate * Sockets generally don't have interesting pathnames; we only 9660Sstevel@tonic-gate * show those in the '-p' view. 9670Sstevel@tonic-gate */ 9680Sstevel@tonic-gate path[0] = '\0'; 9690Sstevel@tonic-gate if (v.v_type != VSOCK) { 9700Sstevel@tonic-gate if (pfiles_dig_pathname(top_vnodep, path) == -1) 9710Sstevel@tonic-gate return (DCMD_ERR); 9720Sstevel@tonic-gate } 9730Sstevel@tonic-gate mdb_printf("%s%s", path, path[0] == '\0' ? "" : " "); 9740Sstevel@tonic-gate 9750Sstevel@tonic-gate switch (v.v_type) { 9760Sstevel@tonic-gate case VDOOR: 9770Sstevel@tonic-gate { 9780Sstevel@tonic-gate door_node_t doornode; 9790Sstevel@tonic-gate proc_t pr; 9800Sstevel@tonic-gate 9810Sstevel@tonic-gate if (mdb_vread(&doornode, sizeof (doornode), 9820Sstevel@tonic-gate (uintptr_t)layer_vn.v_data) == -1) { 9830Sstevel@tonic-gate mdb_warn("failed to read door_node"); 9840Sstevel@tonic-gate return (DCMD_ERR); 9850Sstevel@tonic-gate } 9860Sstevel@tonic-gate 9870Sstevel@tonic-gate if (mdb_vread(&pr, sizeof (pr), 9880Sstevel@tonic-gate (uintptr_t)doornode.door_target) == -1) { 9890Sstevel@tonic-gate mdb_warn("failed to read door server process %p", 9900Sstevel@tonic-gate doornode.door_target); 9910Sstevel@tonic-gate return (DCMD_ERR); 9920Sstevel@tonic-gate } 9930Sstevel@tonic-gate mdb_printf("[door to '%s' (proc=%p)]", pr.p_user.u_comm, 9940Sstevel@tonic-gate doornode.door_target); 9950Sstevel@tonic-gate break; 9960Sstevel@tonic-gate } 9970Sstevel@tonic-gate 9980Sstevel@tonic-gate case VSOCK: 9990Sstevel@tonic-gate { 1000*8348SEric.Yu@Sun.COM vnode_t v_sock; 1001*8348SEric.Yu@Sun.COM struct sonode so; 10020Sstevel@tonic-gate 1003*8348SEric.Yu@Sun.COM if (mdb_vread(&v_sock, sizeof (v_sock), realvpp) == -1) { 1004*8348SEric.Yu@Sun.COM mdb_warn("failed to read socket vnode"); 10050Sstevel@tonic-gate return (DCMD_ERR); 1006*8348SEric.Yu@Sun.COM } 10070Sstevel@tonic-gate 10080Sstevel@tonic-gate /* 1009*8348SEric.Yu@Sun.COM * Sockets can be non-stream or stream, they have to be dealed 1010*8348SEric.Yu@Sun.COM * with differently. 10110Sstevel@tonic-gate */ 1012*8348SEric.Yu@Sun.COM if (v_sock.v_stream == NULL) { 1013*8348SEric.Yu@Sun.COM if (pfiles_get_sonode(&v_sock, &so) == -1) 10140Sstevel@tonic-gate return (DCMD_ERR); 1015*8348SEric.Yu@Sun.COM 1016*8348SEric.Yu@Sun.COM /* Pick the proper methods. */ 1017*8348SEric.Yu@Sun.COM for (i = 0; i <= NUM_SOCK_PRINTS; i++) { 1018*8348SEric.Yu@Sun.COM if ((sock_prints[i].family == so.so_family && 1019*8348SEric.Yu@Sun.COM sock_prints[i].type == so.so_type && 1020*8348SEric.Yu@Sun.COM sock_prints[i].pro == so.so_protocol) || 1021*8348SEric.Yu@Sun.COM (sock_prints[i].family == so.so_family && 1022*8348SEric.Yu@Sun.COM sock_prints[i].type == so.so_type && 1023*8348SEric.Yu@Sun.COM so.so_type == SOCK_RAW)) { 1024*8348SEric.Yu@Sun.COM if ((*sock_prints[i].print)(&so) == -1) 1025*8348SEric.Yu@Sun.COM return (DCMD_ERR); 1026*8348SEric.Yu@Sun.COM } 1027*8348SEric.Yu@Sun.COM } 1028*8348SEric.Yu@Sun.COM } else { 1029*8348SEric.Yu@Sun.COM sotpi_sonode_t sotpi_sonode; 1030*8348SEric.Yu@Sun.COM 1031*8348SEric.Yu@Sun.COM if (pfiles_get_sonode(&v_sock, &so) == -1) 1032*8348SEric.Yu@Sun.COM return (DCMD_ERR); 1033*8348SEric.Yu@Sun.COM 1034*8348SEric.Yu@Sun.COM /* 1035*8348SEric.Yu@Sun.COM * If the socket is a fallback socket, read its related 1036*8348SEric.Yu@Sun.COM * information separately; otherwise, read it as a whole 1037*8348SEric.Yu@Sun.COM * tpi socket. 1038*8348SEric.Yu@Sun.COM */ 1039*8348SEric.Yu@Sun.COM if (so.so_state & SS_FALLBACK_COMP) { 1040*8348SEric.Yu@Sun.COM sotpi_sonode.st_sonode = so; 1041*8348SEric.Yu@Sun.COM 1042*8348SEric.Yu@Sun.COM if (mdb_vread(&(sotpi_sonode.st_info), 1043*8348SEric.Yu@Sun.COM sizeof (sotpi_info_t), 1044*8348SEric.Yu@Sun.COM (uintptr_t)so.so_priv) == -1) 1045*8348SEric.Yu@Sun.COM return (DCMD_ERR); 1046*8348SEric.Yu@Sun.COM } else { 1047*8348SEric.Yu@Sun.COM if (pfiles_get_tpi_sonode(&v_sock, 1048*8348SEric.Yu@Sun.COM &sotpi_sonode) == -1) 1049*8348SEric.Yu@Sun.COM return (DCMD_ERR); 10500Sstevel@tonic-gate } 10510Sstevel@tonic-gate 1052*8348SEric.Yu@Sun.COM if (tpi_sock_print(&sotpi_sonode) == -1) 1053*8348SEric.Yu@Sun.COM return (DCMD_ERR); 10540Sstevel@tonic-gate } 10550Sstevel@tonic-gate 10560Sstevel@tonic-gate break; 10570Sstevel@tonic-gate } 10580Sstevel@tonic-gate 10590Sstevel@tonic-gate case VPORT: 10600Sstevel@tonic-gate mdb_printf("[event port (port=%p)]", v.v_data); 10610Sstevel@tonic-gate break; 10620Sstevel@tonic-gate 10630Sstevel@tonic-gate case VPROC: 10640Sstevel@tonic-gate { 10650Sstevel@tonic-gate prnode_t prnode; 10660Sstevel@tonic-gate prcommon_t prcommon; 10670Sstevel@tonic-gate 10680Sstevel@tonic-gate if (mdb_vread(&prnode, sizeof (prnode), 10690Sstevel@tonic-gate (uintptr_t)layer_vn.v_data) == -1) { 10700Sstevel@tonic-gate mdb_warn("failed to read prnode"); 10710Sstevel@tonic-gate return (DCMD_ERR); 10720Sstevel@tonic-gate } 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate if (mdb_vread(&prcommon, sizeof (prcommon), 10750Sstevel@tonic-gate (uintptr_t)prnode.pr_common) == -1) { 10760Sstevel@tonic-gate mdb_warn("failed to read prcommon %p", 10770Sstevel@tonic-gate prnode.pr_common); 10780Sstevel@tonic-gate return (DCMD_ERR); 10790Sstevel@tonic-gate } 10800Sstevel@tonic-gate 10810Sstevel@tonic-gate mdb_printf("(proc=%p)", prcommon.prc_proc); 10820Sstevel@tonic-gate break; 10830Sstevel@tonic-gate } 10840Sstevel@tonic-gate 10850Sstevel@tonic-gate default: 10860Sstevel@tonic-gate break; 10870Sstevel@tonic-gate } 10880Sstevel@tonic-gate 10890Sstevel@tonic-gate mdb_printf("\n"); 10900Sstevel@tonic-gate 10910Sstevel@tonic-gate return (WALK_NEXT); 10920Sstevel@tonic-gate } 10930Sstevel@tonic-gate 10940Sstevel@tonic-gate static int 10950Sstevel@tonic-gate file_t_callback(uintptr_t addr, const struct file *f, struct pfiles_cbdata *cb) 10960Sstevel@tonic-gate { 10970Sstevel@tonic-gate int myfd = cb->fd; 10980Sstevel@tonic-gate 10990Sstevel@tonic-gate cb->fd++; 11000Sstevel@tonic-gate 11010Sstevel@tonic-gate if (addr == NULL) { 11020Sstevel@tonic-gate return (WALK_NEXT); 11030Sstevel@tonic-gate } 11040Sstevel@tonic-gate 11050Sstevel@tonic-gate /* 11060Sstevel@tonic-gate * We really need 20 digits to print a 64-bit offset_t, but this 11070Sstevel@tonic-gate * is exceedingly rare, so we cheat and assume a column width of 10 11080Sstevel@tonic-gate * digits, in order to fit everything cleanly into 80 columns. 11090Sstevel@tonic-gate */ 11100Sstevel@tonic-gate mdb_printf("%?0p %4d %8x %?0p %10lld %?0p %4d\n", 11110Sstevel@tonic-gate addr, myfd, f->f_flag, f->f_vnode, f->f_offset, f->f_cred, 11120Sstevel@tonic-gate f->f_count); 11130Sstevel@tonic-gate 11140Sstevel@tonic-gate return (WALK_NEXT); 11150Sstevel@tonic-gate } 11160Sstevel@tonic-gate 11170Sstevel@tonic-gate int 11180Sstevel@tonic-gate pfiles(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 11190Sstevel@tonic-gate { 11200Sstevel@tonic-gate int opt_f = 0; 11210Sstevel@tonic-gate 11220Sstevel@tonic-gate struct pfiles_cbdata cb; 11230Sstevel@tonic-gate 11240Sstevel@tonic-gate bzero(&cb, sizeof (cb)); 11250Sstevel@tonic-gate 11260Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 11270Sstevel@tonic-gate return (DCMD_USAGE); 11280Sstevel@tonic-gate 11290Sstevel@tonic-gate if (mdb_getopts(argc, argv, 11300Sstevel@tonic-gate 'p', MDB_OPT_SETBITS, TRUE, &cb.opt_p, 11310Sstevel@tonic-gate 'f', MDB_OPT_SETBITS, TRUE, &opt_f, NULL) != argc) 11320Sstevel@tonic-gate return (DCMD_USAGE); 11330Sstevel@tonic-gate 11340Sstevel@tonic-gate if (opt_f) { 11350Sstevel@tonic-gate mdb_printf("%<u>%?s %4s %8s %?s %10s %?s %4s%</u>\n", "FILE", 11360Sstevel@tonic-gate "FD", "FLAG", "VNODE", "OFFSET", "CRED", "CNT"); 11370Sstevel@tonic-gate if (mdb_pwalk("allfile", (mdb_walk_cb_t)file_t_callback, &cb, 11380Sstevel@tonic-gate addr) == -1) { 11390Sstevel@tonic-gate mdb_warn("failed to walk 'allfile'"); 11400Sstevel@tonic-gate return (DCMD_ERR); 11410Sstevel@tonic-gate } 11420Sstevel@tonic-gate } else { 11430Sstevel@tonic-gate mdb_printf("%<u>%-4s %4s %?s ", "FD", "TYPE", "VNODE"); 11440Sstevel@tonic-gate if (cb.opt_p) 11450Sstevel@tonic-gate mdb_printf("PATH"); 11460Sstevel@tonic-gate else 11470Sstevel@tonic-gate mdb_printf("INFO"); 11480Sstevel@tonic-gate mdb_printf("%</u>\n"); 11490Sstevel@tonic-gate 11500Sstevel@tonic-gate if (mdb_pwalk("allfile", (mdb_walk_cb_t)pfile_callback, &cb, 11510Sstevel@tonic-gate addr) == -1) { 11520Sstevel@tonic-gate mdb_warn("failed to walk 'allfile'"); 11530Sstevel@tonic-gate return (DCMD_ERR); 11540Sstevel@tonic-gate } 11550Sstevel@tonic-gate } 11560Sstevel@tonic-gate 11570Sstevel@tonic-gate 11580Sstevel@tonic-gate return (DCMD_OK); 11590Sstevel@tonic-gate } 11600Sstevel@tonic-gate 11610Sstevel@tonic-gate void 11620Sstevel@tonic-gate pfiles_help(void) 11630Sstevel@tonic-gate { 11640Sstevel@tonic-gate mdb_printf( 11650Sstevel@tonic-gate "Given the address of a process, print information about files\n" 11660Sstevel@tonic-gate "which the process has open. By default, this includes decoded\n" 11670Sstevel@tonic-gate "information about the file depending on file and filesystem type\n" 11680Sstevel@tonic-gate "\n" 11690Sstevel@tonic-gate "\t-p\tPathnames; omit decoded information. Only display " 11700Sstevel@tonic-gate "pathnames\n" 11710Sstevel@tonic-gate "\t-f\tfile_t view; show the file_t structure corresponding to " 11720Sstevel@tonic-gate "the fd\n"); 11730Sstevel@tonic-gate } 1174