Beispiel #1
0
/*
 * Print the core fields in an NCA nca_conn_t.  With the "-t" argument, skip
 * all nca_conn_t's that are in the TIME_WAIT state.  With the "-x" argument,
 * show the xmit data.
 */
static int
nca_conn(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	unsigned int	i;
	nca_conn_t 		conn;
	unsigned int	show_timewait = TRUE;
	unsigned int	show_xmit = FALSE;

	if (!(flags & DCMD_ADDRSPEC))
		return (DCMD_USAGE);

	if (mdb_getopts(argc, argv, 'x', MDB_OPT_SETBITS, TRUE, &show_xmit,
	    't', MDB_OPT_CLRBITS, TRUE, &show_timewait, NULL) != argc)
		return (DCMD_USAGE);

	if (DCMD_HDRSPEC(flags)) {
		mdb_printf("%<u>%-*s %3s %8s %15s %15s %-*s %-10s%</u>\n",
		    NCA_ADDR_WIDTH, "ADDR", "REF", "CREATE", "LOCAL_ADDR",
		    "REMOTE_ADDR", NCA_ADDR_WIDTH,  "NODE", "STATE");
	}

	if (mdb_vread(&conn, sizeof (nca_conn_t), addr) == -1) {
		mdb_warn("cannot read nca_conn_t at %p", addr);
		return (DCMD_ERR);
	}

	if (!show_timewait && conn.tcp_state == TCPS_TIME_WAIT)
		return (DCMD_OK);

	mdb_printf("%0*p %3d %8lx %15I %15I %0*p %s\n", NCA_ADDR_WIDTH, addr,
	    conn.ref, conn.create, conn.laddr, conn.faddr, NCA_ADDR_WIDTH,
	    conn.req_np, state2name(conn.tcp_state));

	if (show_xmit) {
		mdb_inc_indent(4);

		for (i = 0; i < TCP_XMIT_MAX_IX; i++) {
			mdb_printf("xmit[%d]\n", i);
			mdb_printf("\tref pointer\t\t%p\n", conn.xmit[i].np);
			mdb_printf("\tdata pointer\t\t%p\n", conn.xmit[i].dp);
			mdb_printf("\tcksum array\t\t%p\n", conn.xmit[i].cp);
			mdb_printf("\tremaining xmit data\t%d\n",
			    conn.xmit[i].sz);
			mdb_printf("\tref to node_t\t\t%p\n",
			    conn.xmit[i].refed);
			mdb_printf("\tremaining segment data\t%d\n",
			    conn.xmit[i].dsz);
			mdb_printf("\tvirtual pointer\t\t%p\n",
			    conn.xmit[i].dvp);
		}

		mdb_dec_indent(4);
	}

	return (DCMD_OK);
}
Beispiel #2
0
int
va2pfn_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	uintptr_t addrspace;
	char *addrspace_str = NULL;
	int piped = flags & DCMD_PIPE_OUT;
	pfn_t pfn;
	pfn_t mfn;
	int rc;

	init_mmu();

	if (mmu.num_level == 0)
		return (DCMD_ERR);

	if (mdb_getopts(argc, argv,
	    'a', MDB_OPT_STR, &addrspace_str) != argc)
		return (DCMD_USAGE);

	if ((flags & DCMD_ADDRSPEC) == 0)
		return (DCMD_USAGE);

	/*
	 * parse the address space
	 */
	if (addrspace_str != NULL)
		addrspace = mdb_strtoull(addrspace_str);
	else
		addrspace = 0;

	rc = do_va2pa(addr, (struct as *)addrspace, !piped, NULL, &mfn);

	if (rc != DCMD_OK)
		return (rc);

	if ((pfn = mdb_mfn_to_pfn(mfn)) == -(pfn_t)1) {
		mdb_warn("Invalid mfn %lr\n", mfn);
		return (DCMD_ERR);
	}

	if (piped) {
		mdb_printf("0x%lr\n", pfn);
		return (DCMD_OK);
	}

	mdb_printf("Virtual address 0x%p maps pfn 0x%lr", addr, pfn);

	if (is_xpv)
		mdb_printf(" (mfn 0x%lr)", mfn);

	mdb_printf("\n");

	return (DCMD_OK);
}
Beispiel #3
0
int
cmd_nmadd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	uintptr_t opt_e = 0, opt_s = 0;
	uint_t opt_f = FALSE, opt_o = FALSE;

	GElf_Sym sym;
	int i;

	if (!(flags & DCMD_ADDRSPEC))
		return (DCMD_USAGE);

	i = mdb_getopts(argc, argv,
	    'f', MDB_OPT_SETBITS, TRUE, &opt_f,
	    'o', MDB_OPT_SETBITS, TRUE, &opt_o,
	    'e', MDB_OPT_UINTPTR, &opt_e,
	    's', MDB_OPT_UINTPTR, &opt_s, NULL);

	if (i != (argc - 1) || argv[i].a_type != MDB_TYPE_STRING ||
	    argv[i].a_un.a_str[0] == '-' || argv[i].a_un.a_str[0] == '+')
		return (DCMD_USAGE);

	if (opt_e && opt_e < addr) {
		mdb_warn("end (%p) is less than start address (%p)\n",
		    (void *)opt_e, (void *)addr);
		return (DCMD_USAGE);
	}

	if (mdb_gelf_symtab_lookup_by_name(mdb.m_prsym,
	    argv[i].a_un.a_str, &sym, NULL) == -1) {
		bzero(&sym, sizeof (sym));
		sym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
	}

	if (opt_f)
		sym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC);
	if (opt_o)
		sym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
	if (opt_e)
		sym.st_size = (GElf_Xword)(opt_e - addr);
	if (opt_s)
		sym.st_size = (GElf_Xword)(opt_s);
	sym.st_value = (GElf_Addr)addr;

	mdb_gelf_symtab_insert(mdb.m_prsym, argv[i].a_un.a_str, &sym);

	mdb_iob_printf(mdb.m_out, "added %s, value=%llr size=%llr\n",
	    argv[i].a_un.a_str, sym.st_value, sym.st_size);

	return (DCMD_OK);
}
Beispiel #4
0
int
pagelookup(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	uintptr_t vp = -(uintptr_t)1;
	uint64_t offset = -(uint64_t)1;

	uintptr_t pageaddr;
	int hasaddr = (flags & DCMD_ADDRSPEC);
	int usedaddr = 0;

	if (mdb_getopts(argc, argv,
	    'v', MDB_OPT_UINTPTR, &vp,
	    'o', MDB_OPT_UINT64, &offset,
	    0) != argc) {
		return (DCMD_USAGE);
	}

	if (vp == -(uintptr_t)1) {
		if (offset == -(uint64_t)1) {
			mdb_warn(
			    "pagelookup: at least one of -v vp or -o offset "
			    "required.\n");
			return (DCMD_USAGE);
		}
		vp = addr;
		usedaddr = 1;
	} else if (offset == -(uint64_t)1) {
		offset = mdb_get_dot();
		usedaddr = 1;
	}
	if (usedaddr && !hasaddr) {
		mdb_warn("pagelookup: address required\n");
		return (DCMD_USAGE);
	}
	if (!usedaddr && hasaddr) {
		mdb_warn(
		    "pagelookup: address specified when both -v and -o were "
		    "passed");
		return (DCMD_USAGE);
	}

	pageaddr = mdb_page_lookup(vp, offset);
	if (pageaddr == 0) {
		mdb_warn("pagelookup: no page for {vp = %p, offset = %llp)\n",
		    vp, offset);
		return (DCMD_OK);
	}
	mdb_printf("%#lr\n", pageaddr);		/* this is PIPE_OUT friendly */
	return (DCMD_OK);
}
Beispiel #5
0
static int
xhci_mdb_find(uintptr_t addr, uint_t flags, int argc,
    const mdb_arg_t *argv)
{
	uintptr_t ep, slot;
	boolean_t ep_set, slot_set;
	xhci_mdb_find_t xmf;

	if ((flags & DCMD_ADDRSPEC) == 0)
		return (DCMD_USAGE);

	ep_set = slot_set = B_FALSE;
	if (mdb_getopts(argc, argv, 'e', MDB_OPT_UINTPTR_SET, &ep_set, &ep,
	    's', MDB_OPT_UINTPTR_SET, &slot_set, &slot) != argc)
		return (DCMD_USAGE);

	if (!slot_set) {
		mdb_warn("-s is required\n");
		return (DCMD_USAGE);
	}

	xmf.xmf_slot = (int)slot;
	if (ep_set)
		xmf.xmf_ep = (int)ep;
	else
		xmf.xmf_ep = -1;
	xmf.xmf_addr = 0;

	if (mdb_pwalk("xhci`xhci_device", xhci_mdb_find_device_cb,
	    &xmf, addr) == -1) {
		mdb_warn("failed to walk xhci_device at %p", addr);
		return (DCMD_ERR);
	}

	if (xmf.xmf_addr == 0) {
		if (ep_set) {
			mdb_warn("failed to find xhci_endpoint_t for slot %d "
			    "and endpoint %d\n", slot, ep);
		} else {
			mdb_warn("failed to find xhci_device_t for slot %d\n",
			    slot);
		}
		return (DCMD_ERR);
	}

	mdb_printf("%p\n", xmf.xmf_addr);
	return (DCMD_OK);
}
Beispiel #6
0
/*
 * Map from thread pointer to tsd for given key
 */
static int
d_tsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	mdb_libc_ulwp_t u;
	uintptr_t ulwp_addr;
	uintptr_t key = NULL;
	void *element = NULL;

	if (mdb_getopts(argc, argv, 'k', MDB_OPT_UINTPTR, &key, NULL) != argc)
		return (DCMD_USAGE);

	if (!(flags & DCMD_ADDRSPEC) || key == NULL)
		return (DCMD_USAGE);

	if (tid2ulwp_impl(addr, &ulwp_addr) != DCMD_OK)
		return (DCMD_ERR);

	if (mdb_ctf_vread(&u, "ulwp_t", "mdb_libc_ulwp_t", ulwp_addr, 0) == -1)
		return (DCMD_ERR);

	if (key < TSD_NFAST) {
		element = u.ul_ftsd[key];
	} else if (u.ul_stsd != NULL) {
		uint_t nalloc;
		/* tsd_t is a union, so we can't use ctf_vread() on it. */
		if (mdb_vread(&nalloc, sizeof (nalloc),
		    (uintptr_t)&u.ul_stsd->tsd_nalloc) == -1) {
			mdb_warn("failed to read tsd_t at %p", u.ul_stsd);
			return (DCMD_ERR);
		}
		if (key < nalloc) {
			if (mdb_vread(&element, sizeof (element),
			    (uintptr_t)&u.ul_stsd->tsd_data[key]) == -1) {
				mdb_warn("failed to read tsd_t at %p",
				    u.ul_stsd);
				return (DCMD_ERR);
			}
		}
	}

	if (element == NULL && (flags & DCMD_PIPE))
		return (DCMD_OK);

	mdb_printf("%p\n", element);
	return (DCMD_OK);
}
Beispiel #7
0
/*ARGSUSED*/
int
snode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	snode_cbdata_t sd;
	struct snode snode;
	uintptr_t major = 0, dev = 0;

	sd.sd_major = -1;
	sd.sd_minor = -1;
	sd.sd_verbose = !(flags & DCMD_PIPE_OUT);

	if (mdb_getopts(argc, argv,
	    'm', MDB_OPT_UINTPTR, &major,
	    'd', MDB_OPT_UINTPTR, &dev, NULL) != argc)
		return (DCMD_USAGE);

	if (dev != 0) {
		sd.sd_major = getmajor(dev);
		sd.sd_minor = getminor(dev);
	}

	if (major != 0)
		sd.sd_major = major;

	if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) {
		mdb_printf("%<u>%?s %?s %6s %16s %-15s%</u>\n",
		    "ADDR", "VNODE", "COUNT", "DEV", "FLAG");
	}

	if (!(flags & DCMD_ADDRSPEC)) {
		if (mdb_walk("snode", (mdb_walk_cb_t)snode_cb, &sd) == -1) {
			mdb_warn("can't walk snodes");
			return (DCMD_ERR);
		}
		return (DCMD_OK);
	}

	if (mdb_vread(&snode, sizeof (snode), addr) == -1) {
		mdb_warn("failed to read snode structure at %p", addr);
		return (DCMD_ERR);
	}

	snode_cb(addr, &snode, &sd);

	return (DCMD_OK);
}
Beispiel #8
0
/*
 * dcmd ::credsid - display a credsid_t
 */
int
cmd_credsid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	credsid_t kr;
	uint_t opts = FALSE;
	int rv = DCMD_OK;

	if (mdb_getopts(argc, argv,
	    'v', MDB_OPT_SETBITS, OPT_VERBOSE, &opts, NULL) != argc)
		return (DCMD_USAGE);

	if (!(flags & DCMD_ADDRSPEC)) {
		return (DCMD_USAGE);
	}

	if (mdb_vread(&kr, sizeof (kr), addr) == -1) {
		mdb_warn("error reading credsid_t at %p", addr);
		return (DCMD_ERR);
	}

	if (opts & OPT_VERBOSE)
		mdb_printf("kr_ref = 0x%x\n", kr.kr_ref);

	mdb_printf("kr_sidx[USER]  = ");
	print_ksid(&kr.kr_sidx[KSID_USER]);

	mdb_printf("kr_sidx[GROUP] = ");
	print_ksid(&kr.kr_sidx[KSID_GROUP]);

	mdb_printf("kr_sidx[OWNER] = ");
	print_ksid(&kr.kr_sidx[KSID_OWNER]);

	mdb_printf("kr_sidlist = %p\n", kr.kr_sidlist);
	if (kr.kr_sidlist != NULL && (opts & OPT_VERBOSE) != 0) {
		mdb_printf("*kr_sidlist = {\n");
		mdb_inc_indent(4);
		rv = mdb_call_dcmd("ksidlist",
		    (uintptr_t)kr.kr_sidlist, flags, argc, argv);
		mdb_dec_indent(4);
		mdb_printf("}\n");
	}

	return (rv);
}
Beispiel #9
0
int
pfiles(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	int opt_f = 0;

	struct pfiles_cbdata cb;

	bzero(&cb, sizeof (cb));

	if (!(flags & DCMD_ADDRSPEC))
		return (DCMD_USAGE);

	if (mdb_getopts(argc, argv,
	    'p', MDB_OPT_SETBITS, TRUE, &cb.opt_p,
	    'f', MDB_OPT_SETBITS, TRUE, &opt_f, NULL) != argc)
		return (DCMD_USAGE);

	if (opt_f) {
		mdb_printf("%<u>%?s %4s %8s %?s %10s %?s %4s%</u>\n", "FILE",
		    "FD", "FLAG", "VNODE", "OFFSET", "CRED", "CNT");
		if (mdb_pwalk("allfile", (mdb_walk_cb_t)file_t_callback, &cb,
		    addr) == -1) {
			mdb_warn("failed to walk 'allfile'");
			return (DCMD_ERR);
		}
	} else {
		mdb_printf("%<u>%-4s %4s %?s ", "FD", "TYPE", "VNODE");
		if (cb.opt_p)
			mdb_printf("PATH");
		else
			mdb_printf("INFO");
		mdb_printf("%</u>\n");

		if (mdb_pwalk("allfile", (mdb_walk_cb_t)pfile_callback, &cb,
		    addr) == -1) {
			mdb_warn("failed to walk 'allfile'");
			return (DCMD_ERR);
		}
	}


	return (DCMD_OK);
}
Beispiel #10
0
/*
 * dcmd ::ksidlist - display a ksidlist_t
 */
int
cmd_ksidlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	ksidlist_t ksl;
	ksid_t ks;
	uint_t i, opts = FALSE;
	int rv = DCMD_OK;

	if (mdb_getopts(argc, argv,
	    'v', MDB_OPT_SETBITS, OPT_VERBOSE, &opts, NULL) != argc)
		return (DCMD_USAGE);

	if (!(flags & DCMD_ADDRSPEC)) {
		return (DCMD_USAGE);
	}

	if (mdb_vread(&ksl, sizeof (ksl), addr) == -1) {
		mdb_warn("error reading ksidlist_t at %p", addr);
		return (DCMD_ERR);
	}

	if (opts & OPT_VERBOSE) {
		mdb_printf("ksl_ref = 0x%x\n", ksl.ksl_ref);
		mdb_printf("ksl_nsid = 0x%x\n", ksl.ksl_nsid);
		mdb_printf("ksl_neid = 0x%x\n", ksl.ksl_neid);
	}

	mdb_printf("ksl_sids = [\n");
	addr += OFFSETOF(ksidlist_t, ksl_sids);
	mdb_inc_indent(4);
	for (i = 0; i < ksl.ksl_nsid; i++, addr += sizeof (ksid_t)) {
		if (mdb_vread(&ks, sizeof (ks), addr) == -1) {
			mdb_warn("error reading ksid_t at %p", addr);
			rv = DCMD_ERR;
			break;
		}
		print_ksid(&ks);
	}
	mdb_dec_indent(4);
	mdb_printf("]\n");

	return (rv);
}
Beispiel #11
0
int
memlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	struct memlist	ml;

	if (!(flags & DCMD_ADDRSPEC)) {
		uintptr_t ptr;
		uint_t list = 0;
		int i;
		static const char *lists[] = {
			"phys_install",
			"phys_avail",
			"virt_avail"
		};

		if (mdb_getopts(argc, argv,
		    'i', MDB_OPT_SETBITS, (1 << 0), &list,
		    'a', MDB_OPT_SETBITS, (1 << 1), &list,
		    'v', MDB_OPT_SETBITS, (1 << 2), &list, NULL) != argc)
			return (DCMD_USAGE);

		if (!list)
			list = 1;

		for (i = 0; list; i++, list >>= 1) {
			if (!(list & 1))
				continue;
			if ((mdb_readvar(&ptr, lists[i]) == -1) ||
			    (ptr == NULL)) {
				mdb_warn("%s not found or invalid", lists[i]);
				return (DCMD_ERR);
			}

			mdb_printf("%s:\n", lists[i]);
			if (mdb_pwalk_dcmd("memlist", "memlist", 0, NULL,
			    ptr) == -1) {
				mdb_warn("can't walk memlist");
				return (DCMD_ERR);
			}
		}
		return (DCMD_OK);
	}
Beispiel #12
0
/*
 * dcmd ::credgrp - display cred_t groups
 */
int
cmd_credgrp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	credgrp_t grps;
	gid_t gid;
	uint_t i, opts = FALSE;
	int rv = DCMD_OK;

	if (mdb_getopts(argc, argv,
	    'v', MDB_OPT_SETBITS, OPT_VERBOSE, &opts, NULL) != argc)
		return (DCMD_USAGE);

	if (!(flags & DCMD_ADDRSPEC)) {
		return (DCMD_USAGE);
	}

	if (mdb_vread(&grps, sizeof (grps), addr) == -1) {
		mdb_warn("error reading credgrp_t at %p", addr);
		return (DCMD_ERR);
	}

	if (opts & OPT_VERBOSE) {
		mdb_printf("crg_ref = 0x%x\n", grps.crg_ref);
		mdb_printf("crg_ngroups = 0x%x\n", grps.crg_ngroups);
	}
	mdb_printf("crg_groups = [\n");

	addr += OFFSETOF(credgrp_t, crg_groups);
	mdb_inc_indent(4);
	for (i = 0; i < grps.crg_ngroups; i++, addr += sizeof (gid_t)) {
		if (mdb_vread(&gid, sizeof (gid), addr) == -1) {
			mdb_warn("error reading gid_t at %p", addr);
			rv = DCMD_ERR;
			break;
		}
		mdb_printf("\t%u,", gid);
	}
	mdb_dec_indent(4);
	mdb_printf("\n]\n");

	return (rv);
}
Beispiel #13
0
/*ARGSUSED*/
int
pte_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	int level = 0;
	uint64_t pte = 0;
	char *level_str = NULL;
	char *pte_str = NULL;

	init_mmu();

	if (mmu.num_level == 0)
		return (DCMD_ERR);

	if (mdb_getopts(argc, argv,
	    'p', MDB_OPT_STR, &pte_str,
	    'l', MDB_OPT_STR, &level_str) != argc)
		return (DCMD_USAGE);

	/*
	 * parse the PTE to decode, if it's 0, we don't do anything
	 */
	if (pte_str != NULL) {
		pte = mdb_strtoull(pte_str);
	} else {
		if ((flags & DCMD_ADDRSPEC) == 0)
			return (DCMD_USAGE);
		pte = addr;
	}
	if (pte == 0)
		return (DCMD_OK);

	/*
	 * parse the level if supplied
	 */
	if (level_str != NULL) {
		level = mdb_strtoull(level_str);
		if (level < 0 || level > mmu.max_level)
			return (DCMD_ERR);
	}

	return (do_pte_dcmd(level, pte));
}
Beispiel #14
0
/* ARGSUSED */
int
group(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	group_t	group;
	int	opt_q = 0; /* display only address. */

	/* Should provide an address */
	if (!(flags & DCMD_ADDRSPEC))
		return (DCMD_USAGE);

	if (mdb_getopts(argc, argv,
	    'q', MDB_OPT_SETBITS, TRUE, &opt_q,
		NULL) != argc)
		return (DCMD_USAGE);

	if (flags & DCMD_PIPE_OUT)
		opt_q = B_TRUE;

	if (DCMD_HDRSPEC(flags) && !opt_q) {
		mdb_printf("%?s %6s %9s %?s\n",
		    "ADDR",
		    "SIZE",
		    "CAPACITY",
		    "SET");
	}

	if (mdb_vread(&group, sizeof (struct group), addr) == -1) {
		mdb_warn("unable to read 'group' at %p", addr);
		return (DCMD_ERR);
	}

	if (opt_q) {
		mdb_printf("%0?p\n", addr);
		return (DCMD_OK);
	}

	mdb_printf("%?p %6d %9d %?p\n",
	    addr, group.grp_size, group.grp_capacity, group.grp_set);

	return (DCMD_OK);
}
Beispiel #15
0
static int
stmf_sbd_it(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
    uint_t		verbose = FALSE;
    sbd_lu_t	slu;
    stmf_sbd_cb_t	cb_st = {0};

    if (!(flags & DCMD_ADDRSPEC))
        return (DCMD_USAGE);

    if (mdb_getopts(argc, argv,
                    'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc)
        return (DCMD_USAGE);

    if (verbose) {
        cb_st.flag |= STMF_SBD_VERBOSE;
        mdb_printf("\nLU:- %p\n", addr);
    }

    /* If address of pgr_key is given, just print that key and return */
    if (mdb_vread(&slu, sizeof (sbd_lu_t), addr) == -1) {
        mdb_warn("failed to read sbd_lu at %p\n", addr);
        return (DCMD_ERR);
    }

    /* Just a sanity check, not necessarily needed */
    if (slu.sl_it_list == NULL) {
        if (verbose)
            mdb_printf("sbd_it_list is empty\n", addr);
        return (DCMD_OK);
    }

    if (mdb_pwalk("stmf_sbd_it", (mdb_walk_cb_t)stmf_sbd_it_cb, &cb_st,
                  (uintptr_t)slu.sl_it_list) == -1) {
        mdb_warn("failed to walk sbd_lu_it_list\n");
        return (DCMD_ERR);
    }
    return (DCMD_OK);
}
Beispiel #16
0
/*ARGSUSED*/
int
print_nvlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	int verbose = B_FALSE;
	mdb_arg_t v;

	if (!(flags & DCMD_ADDRSPEC))
		return (DCMD_USAGE);

	if (mdb_getopts(argc, argv,
	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
	    NULL) != argc)
		return (DCMD_USAGE);

	v.a_type = MDB_TYPE_STRING;
	if (verbose)
		v.a_un.a_str = "-r";
	else
		v.a_un.a_str = "-rq";

	return (mdb_pwalk_dcmd("nvpair", "nvpair", 1, &v, addr));
}
Beispiel #17
0
/*ARGSUSED*/
static int
mod(
	uintptr_t	addr,
	uint_t		flags,
	int		argc,
	const mdb_arg_t	*argv)
{
	int		status;
	int		rc = DCMD_OK;
	mfdata_t	*mfp;

	mfp = mdb_zalloc(sizeof (mfdata_t), UM_SLEEP);

	if (mdb_getopts(argc, argv,
	    'v', MDB_OPT_SETBITS, MF_VERBOSE, &mfp->mf_flags,
	    NULL) != argc)
		return (DCMD_USAGE);

	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP))
		mfp->mf_banner = B_TRUE;

	if (flags & DCMD_ADDRSPEC) {
		status = mod_format(addr, NULL, mfp);
		rc = (status == WALK_NEXT) ? DCMD_OK : DCMD_ERR;
		goto cleanup;
	}

	if (mdb_pwalk("ipp_byid", mod_format, mfp,
	    ipp_mod_byid) == -1) {
		mdb_warn("failed to execute ipp_byid walk");
		rc = DCMD_ERR;
	}

cleanup:
	mdb_free(mfp, sizeof (mfdata_t));

	return (rc);
}
Beispiel #18
0
/*ARGSUSED*/
static int
py_stack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	uint_t verbose = FALSE;

	if (mdb_getopts(argc, argv,
	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
	    NULL) != argc)
		return (DCMD_USAGE);

	if (flags & DCMD_PIPE_OUT) {
		mdb_warn("py_stack cannot output into a pipe\n");
		return (DCMD_ERR);
	}

	if (flags & DCMD_ADDRSPEC) {
		mdb_arg_t nargv;
		uint_t nargc = verbose ? 1 : 0;

		nargv.a_type = MDB_TYPE_STRING;
		nargv.a_un.a_str = "-v";

		if (mdb_pwalk_dcmd("pyframe", "pyframe", nargc, &nargv, addr)
		    == -1) {
			mdb_warn("can't walk 'pyframe'");
			return (DCMD_ERR);
		}
		return (DCMD_OK);
	}

	if (mdb_walk("pyinterp", (mdb_walk_cb_t)python_thread,
	    &verbose) == -1) {
		mdb_warn("can't walk 'pyinterp'");
		return (DCMD_ERR);
	}

	return (DCMD_OK);
}
Beispiel #19
0
/*
 * Print the core TCP-related fields in an NCA nca_conn_t.  With the "-t"
 * argument, skips all nca_conn_t's that are in the TIME_WAIT state.
 */
static int
nca_tcpconn(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	nca_conn_t		conn;
	unsigned int	show_timewait = TRUE;

	if (!(flags & DCMD_ADDRSPEC))
		return (DCMD_USAGE);

	if (mdb_getopts(argc, argv, 't', MDB_OPT_CLRBITS, TRUE, &show_timewait,
	    NULL) != argc)
		return (DCMD_USAGE);

	if (DCMD_HDRSPEC(flags)) {
		mdb_printf("%<u>%-*s %21s %5s %8s %5s %8s %5s %-9s%</u>\n",
		    NCA_ADDR_WIDTH, "ADDR", "REMOTE_ADDR", "SWIND", "SUNASEQ",
		    "SNSEQ", "RACKSEQ", "RNSEQ", "STATE");
	}

	if (mdb_vread(&conn, sizeof (nca_conn_t), addr) == -1) {
		mdb_warn("cannot read nca_conn_t at %p", addr);
		return (DCMD_ERR);
	}

	if (!show_timewait && conn.tcp_state == TCPS_TIME_WAIT)
		return (DCMD_OK);

	mdb_nhconvert(&conn.conn_fport, &conn.conn_fport, sizeof (in_port_t));

	mdb_printf("%0*p %15I:%05hu %5u %08x %+5d %08x %+5d %-9s\n",
	    NCA_ADDR_WIDTH, addr, conn.faddr, conn.conn_fport, conn.tcp_swnd,
	    conn.tcp_suna, conn.tcp_snxt - conn.tcp_suna, conn.tcp_rack,
	    conn.tcp_rnxt - conn.tcp_rack, state2name(conn.tcp_state));

	return (DCMD_OK);
}
Beispiel #20
0
/*ARGSUSED*/
int
ptable_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	pfn_t pfn;
	uint_t mflag = 0;

	init_mmu();

	if (mmu.num_level == 0)
		return (DCMD_ERR);

	if ((flags & DCMD_ADDRSPEC) == 0)
		return (DCMD_USAGE);

	if (mdb_getopts(argc, argv,
	    'm', MDB_OPT_SETBITS, TRUE, &mflag, NULL) != argc)
		return (DCMD_USAGE);

	pfn = (pfn_t)addr;
	if (mflag)
		pfn = mdb_mfn_to_pfn(pfn);

	return (do_ptable_dcmd(pfn));
}
Beispiel #21
0
/*ARGSUSED*/
int
stacks(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	size_t idx;

	char *seen = NULL;

	const char *caller_str = NULL;
	const char *excl_caller_str = NULL;
	uintptr_t caller = 0, excl_caller = 0;
	const char *module_str = NULL;
	const char *excl_module_str = NULL;
	stacks_module_t module, excl_module;
	const char *sobj = NULL;
	const char *excl_sobj = NULL;
	uintptr_t sobj_ops = 0, excl_sobj_ops = 0;
	const char *tstate_str = NULL;
	const char *excl_tstate_str = NULL;
	uint_t tstate = -1U;
	uint_t excl_tstate = -1U;
	uint_t printed = 0;

	uint_t all = 0;
	uint_t force = 0;
	uint_t interesting = 0;
	uint_t verbose = 0;

	/*
	 * We have a slight behavior difference between having piped
	 * input and 'addr::stacks'.  Without a pipe, we assume the
	 * thread pointer given is a representative thread, and so
	 * we include all similar threads in the system in our output.
	 *
	 * With a pipe, we filter down to just the threads in our
	 * input.
	 */
	uint_t addrspec = (flags & DCMD_ADDRSPEC);
	uint_t only_matching = addrspec && (flags & DCMD_PIPE);

	mdb_pipe_t p;

	bzero(&module, sizeof (module));
	bzero(&excl_module, sizeof (excl_module));

	if (mdb_getopts(argc, argv,
	    'a', MDB_OPT_SETBITS, TRUE, &all,
	    'f', MDB_OPT_SETBITS, TRUE, &force,
	    'i', MDB_OPT_SETBITS, TRUE, &interesting,
	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
	    'c', MDB_OPT_STR, &caller_str,
	    'C', MDB_OPT_STR, &excl_caller_str,
	    'm', MDB_OPT_STR, &module_str,
	    'M', MDB_OPT_STR, &excl_module_str,
	    's', MDB_OPT_STR, &sobj,
	    'S', MDB_OPT_STR, &excl_sobj,
	    't', MDB_OPT_STR, &tstate_str,
	    'T', MDB_OPT_STR, &excl_tstate_str,
	    NULL) != argc)
		return (DCMD_USAGE);

	if (interesting) {
		if (sobj != NULL || excl_sobj != NULL ||
		    tstate_str != NULL || excl_tstate_str != NULL) {
			mdb_warn(
			    "stacks: -i is incompatible with -[sStT]\n");
			return (DCMD_USAGE);
		}
		excl_sobj = "CV";
		excl_tstate_str = "FREE";
	}

	if (caller_str != NULL) {
		mdb_set_dot(0);
		if (mdb_eval(caller_str) != 0) {
			mdb_warn("stacks: evaluation of \"%s\" failed",
			    caller_str);
			return (DCMD_ABORT);
		}
		caller = mdb_get_dot();
	}

	if (excl_caller_str != NULL) {
		mdb_set_dot(0);
		if (mdb_eval(excl_caller_str) != 0) {
			mdb_warn("stacks: evaluation of \"%s\" failed",
			    excl_caller_str);
			return (DCMD_ABORT);
		}
		excl_caller = mdb_get_dot();
	}
	mdb_set_dot(addr);

	if (module_str != NULL && stacks_module_find(module_str, &module) != 0)
		return (DCMD_ABORT);

	if (excl_module_str != NULL &&
	    stacks_module_find(excl_module_str, &excl_module) != 0)
		return (DCMD_ABORT);

	if (sobj != NULL && text_to_sobj(sobj, &sobj_ops) != 0)
		return (DCMD_USAGE);

	if (excl_sobj != NULL && text_to_sobj(excl_sobj, &excl_sobj_ops) != 0)
		return (DCMD_USAGE);

	if (sobj_ops != 0 && excl_sobj_ops != 0) {
		mdb_warn("stacks: only one of -s and -S can be specified\n");
		return (DCMD_USAGE);
	}

	if (tstate_str != NULL && text_to_tstate(tstate_str, &tstate) != 0)
		return (DCMD_USAGE);

	if (excl_tstate_str != NULL &&
	    text_to_tstate(excl_tstate_str, &excl_tstate) != 0)
		return (DCMD_USAGE);

	if (tstate != -1U && excl_tstate != -1U) {
		mdb_warn("stacks: only one of -t and -T can be specified\n");
		return (DCMD_USAGE);
	}

	/*
	 * If there's an address specified, we're going to further filter
	 * to only entries which have an address in the input.  To reduce
	 * overhead (and make the sorted output come out right), we
	 * use mdb_get_pipe() to grab the entire pipeline of input, then
	 * use qsort() and bsearch() to speed up the search.
	 */
	if (addrspec) {
		mdb_get_pipe(&p);
		if (p.pipe_data == NULL || p.pipe_len == 0) {
			p.pipe_data = &addr;
			p.pipe_len = 1;
		}
		qsort(p.pipe_data, p.pipe_len, sizeof (uintptr_t),
		    uintptrcomp);

		/* remove any duplicates in the data */
		idx = 0;
		while (idx < p.pipe_len - 1) {
			uintptr_t *data = &p.pipe_data[idx];
			size_t len = p.pipe_len - idx;

			if (data[0] == data[1]) {
				memmove(data, data + 1,
				    (len - 1) * sizeof (*data));
				p.pipe_len--;
				continue; /* repeat without incrementing idx */
			}
			idx++;
		}

		seen = mdb_zalloc(p.pipe_len, UM_SLEEP | UM_GC);
	}

	/*
	 * Force a cleanup if we're connected to a live system. Never
	 * do a cleanup after the first invocation around the loop.
	 */
	force |= (mdb_get_state() == MDB_STATE_RUNNING);
	if (force && (flags & (DCMD_LOOPFIRST|DCMD_LOOP)) == DCMD_LOOP)
		force = 0;

	stacks_cleanup(force);

	if (stacks_state == STACKS_STATE_CLEAN) {
		int res = stacks_run(verbose, addrspec ? &p : NULL);
		if (res != DCMD_OK)
			return (res);
	}

	for (idx = 0; idx < stacks_array_size; idx++) {
		stacks_entry_t *sep = stacks_array[idx];
		stacks_entry_t *cur = sep;
		int frame;
		size_t count = sep->se_count;

		if (addrspec) {
			stacks_entry_t *head = NULL, *tail = NULL, *sp;
			size_t foundcount = 0;
			/*
			 * We use the now-unused hash chain field se_next to
			 * link together the dups which match our list.
			 */
			for (sp = sep; sp != NULL; sp = sp->se_dup) {
				uintptr_t *entry = bsearch(&sp->se_thread,
				    p.pipe_data, p.pipe_len, sizeof (uintptr_t),
				    uintptrcomp);
				if (entry != NULL) {
					foundcount++;
					seen[entry - p.pipe_data]++;
					if (head == NULL)
						head = sp;
					else
						tail->se_next = sp;
					tail = sp;
					sp->se_next = NULL;
				}
			}
			if (head == NULL)
				continue;	/* no match, skip entry */

			if (only_matching) {
				cur = sep = head;
				count = foundcount;
			}
		}

		if (caller != 0 && !stacks_has_caller(sep, caller))
			continue;

		if (excl_caller != 0 && stacks_has_caller(sep, excl_caller))
			continue;

		if (module.sm_size != 0 && !stacks_has_module(sep, &module))
			continue;

		if (excl_module.sm_size != 0 &&
		    stacks_has_module(sep, &excl_module))
			continue;

		if (tstate != -1U) {
			if (tstate == TSTATE_PANIC) {
				if (!sep->se_panic)
					continue;
			} else if (sep->se_panic || sep->se_tstate != tstate)
				continue;
		}
		if (excl_tstate != -1U) {
			if (excl_tstate == TSTATE_PANIC) {
				if (sep->se_panic)
					continue;
			} else if (!sep->se_panic &&
			    sep->se_tstate == excl_tstate)
				continue;
		}

		if (sobj_ops == SOBJ_ALL) {
			if (sep->se_sobj_ops == 0)
				continue;
		} else if (sobj_ops != 0) {
			if (sobj_ops != sep->se_sobj_ops)
				continue;
		}

		if (!(interesting && sep->se_panic)) {
			if (excl_sobj_ops == SOBJ_ALL) {
				if (sep->se_sobj_ops != 0)
					continue;
			} else if (excl_sobj_ops != 0) {
				if (excl_sobj_ops == sep->se_sobj_ops)
					continue;
			}
		}

		if (flags & DCMD_PIPE_OUT) {
			while (sep != NULL) {
				mdb_printf("%lr\n", sep->se_thread);
				sep = only_matching ?
				    sep->se_next : sep->se_dup;
			}
			continue;
		}

		if (all || !printed) {
			mdb_printf("%<u>%-?s %-8s %-?s %8s%</u>\n",
			    "THREAD", "STATE", "SOBJ", "COUNT");
			printed = 1;
		}

		do {
			char state[20];
			char sobj[100];

			tstate_to_text(cur->se_tstate, cur->se_panic,
			    state, sizeof (state));
			sobj_to_text(cur->se_sobj_ops,
			    sobj, sizeof (sobj));

			if (cur == sep)
				mdb_printf("%-?p %-8s %-?s %8d\n",
				    cur->se_thread, state, sobj, count);
			else
				mdb_printf("%-?p %-8s %-?s %8s\n",
				    cur->se_thread, state, sobj, "-");

			cur = only_matching ? cur->se_next : cur->se_dup;
		} while (all && cur != NULL);

		if (sep->se_failed != 0) {
			char *reason;
			switch (sep->se_failed) {
			case FSI_FAIL_NOTINMEMORY:
				reason = "thread not in memory";
				break;
			case FSI_FAIL_THREADCORRUPT:
				reason = "thread structure stack info corrupt";
				break;
			case FSI_FAIL_STACKNOTFOUND:
				reason = "no consistent stack found";
				break;
			default:
				reason = "unknown failure";
				break;
			}
			mdb_printf("%?s <%s>\n", "", reason);
		}

		for (frame = 0; frame < sep->se_depth; frame++)
			mdb_printf("%?s %a\n", "", sep->se_stack[frame]);
		if (sep->se_overflow)
			mdb_printf("%?s ... truncated ...\n", "");
		mdb_printf("\n");
	}

	if (flags & DCMD_ADDRSPEC) {
		for (idx = 0; idx < p.pipe_len; idx++)
			if (seen[idx] == 0)
				mdb_warn("stacks: %p not in thread list\n",
				    p.pipe_data[idx]);
	}
	return (DCMD_OK);
}
Beispiel #22
0
/*ARGSUSED*/
int
fsinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	vfs_t vfs;
	int len;
	int opt_v = 0;
	char buf[MAXPATHLEN];
	char fsname[_ST_FSTYPSZ];
	mntopt_t *mntopts;
	size_t size;
	int i;
	int first = 1;
	char opt[MAX_MNTOPT_STR];
	uintptr_t global_zone;

	if (!(flags & DCMD_ADDRSPEC)) {
		if (mdb_walk_dcmd("vfs", "fsinfo", argc, argv) == -1) {
			mdb_warn("failed to walk file system list");
			return (DCMD_ERR);
		}
		return (DCMD_OK);
	}

	if (mdb_getopts(argc, argv,
	    'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc)
		return (DCMD_USAGE);

	if (DCMD_HDRSPEC(flags))
		mdb_printf("%<u>%?s %-15s %s%</u>\n",
		    "VFSP", "FS", "MOUNT");

	if (mdb_vread(&vfs, sizeof (vfs), addr) == -1) {
		mdb_warn("failed to read vfs_t %p", addr);
		return (DCMD_ERR);
	}

	if ((len = mdb_read_refstr((uintptr_t)vfs.vfs_mntpt, buf,
	    sizeof (buf))) <= 0)
		strcpy(buf, "??");

	else if (!opt_v && (len >= FSINFO_MNTLEN))
		/*
		 * In normal mode, we truncate the path to keep the output
		 * clean.  In -v mode, we just print the full path.
		 */
		strcpy(&buf[FSINFO_MNTLEN - 4], "...");

	if (read_fsname(addr, fsname) == -1)
		return (DCMD_ERR);

	mdb_printf("%0?p %-15s %s\n", addr, fsname, buf);

	if (!opt_v)
		return (DCMD_OK);

	/*
	 * Print 'resource' string; this shows what we're mounted upon.
	 */
	if (mdb_read_refstr((uintptr_t)vfs.vfs_resource, buf,
	    MAXPATHLEN) <= 0)
		strcpy(buf, "??");

	mdb_printf("%?s %s\n", "R:", buf);

	/*
	 * Print mount options array; it sucks to be a mimic, but we copy
	 * the same logic as in mntvnops.c for adding zone= tags, and we
	 * don't bother with the obsolete dev= option.
	 */
	size = vfs.vfs_mntopts.mo_count * sizeof (mntopt_t);
	mntopts = mdb_alloc(size, UM_SLEEP | UM_GC);

	if (mdb_vread(mntopts, size,
	    (uintptr_t)vfs.vfs_mntopts.mo_list) == -1) {
		mdb_warn("failed to read mntopts %p", vfs.vfs_mntopts.mo_list);
		return (DCMD_ERR);
	}

	for (i = 0; i < vfs.vfs_mntopts.mo_count; i++) {
		if (mntopts[i].mo_flags & MO_SET) {
			if (mdb_readstr(opt, sizeof (opt),
			    (uintptr_t)mntopts[i].mo_name) == -1) {
				mdb_warn("failed to read mntopt name %p",
				    mntopts[i].mo_name);
				return (DCMD_ERR);
			}
			if (first) {
				mdb_printf("%?s ", "O:");
				first = 0;
			} else {
				mdb_printf(",");
			}
			mdb_printf("%s", opt);
			if (mntopts[i].mo_flags & MO_HASVALUE) {
				if (mdb_readstr(opt, sizeof (opt),
				    (uintptr_t)mntopts[i].mo_arg) == -1) {
					mdb_warn("failed to read mntopt "
					    "value %p", mntopts[i].mo_arg);
					return (DCMD_ERR);
				}
				mdb_printf("=%s", opt);
			}
		}
	}

	if (mdb_readvar(&global_zone, "global_zone") == -1) {
		mdb_warn("failed to locate global_zone");
		return (DCMD_ERR);
	}

	if ((vfs.vfs_zone != NULL) &&
	    ((uintptr_t)vfs.vfs_zone != global_zone)) {
		zone_t z;

		if (mdb_vread(&z, sizeof (z), (uintptr_t)vfs.vfs_zone) == -1) {
			mdb_warn("failed to read zone");
			return (DCMD_ERR);
		}
		/*
		 * zone names are much shorter than MAX_MNTOPT_STR
		 */
		if (mdb_readstr(opt, sizeof (opt),
		    (uintptr_t)z.zone_name) == -1) {
			mdb_warn("failed to read zone name");
			return (DCMD_ERR);
		}
		if (first) {
			mdb_printf("%?s ", "O:");
		} else {
			mdb_printf(",");
		}
		mdb_printf("zone=%s", opt);
	}
	return (DCMD_OK);
}
Beispiel #23
0
int
mi(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	uint_t opts = 0;
	MI_O	mio;

	if (!(flags & DCMD_ADDRSPEC))
		return (DCMD_USAGE);

	if (mdb_getopts(argc, argv,
	    'p', MDB_OPT_SETBITS, MI_PAYLOAD, &opts,
	    'd', MDB_OPT_SETBITS, MI_DEVICE, &opts,
	    'm', MDB_OPT_SETBITS, MI_MODULE, &opts,
	    NULL) != argc)
		return (DCMD_USAGE);

	if ((opts & (MI_DEVICE | MI_MODULE)) == (MI_DEVICE | MI_MODULE)) {
		mdb_warn("at most one filter, d for devices or m "
		    "for modules, may be specified\n");
		return (DCMD_USAGE);
	}

	if ((opts == 0) && (DCMD_HDRSPEC(flags))) {
		mdb_printf("%<u>%-?s %-?s %-?s IsDev Dev%</u>\n",
		    "MI_O", "Next", "Prev");
	}

	if (mdb_vread(&mio, sizeof (mio), addr) == -1) {
		mdb_warn("failed to read mi object MI_O at %p", addr);
		return (DCMD_ERR);
	}

	if (opts != 0) {
		if (mio.mi_o_isdev == B_FALSE) {
			/* mio is a module */
			if (!(opts & MI_MODULE) && (opts & MI_DEVICE))
				return (DCMD_OK);
		} else {
			/* mio is a device */
			if (!(opts & MI_DEVICE) && (opts & MI_MODULE))
				return (DCMD_OK);
		}

		if (opts & MI_PAYLOAD)
			mdb_printf("%p\n", addr + sizeof (MI_O));
		else
			mdb_printf("%p\n", addr);
		return (DCMD_OK);
	}

	mdb_printf("%0?p %0?p %0?p ", addr, mio.mi_o_next, mio.mi_o_prev);

	if (mio.mi_o_isdev == B_FALSE)
		mdb_printf("FALSE");
	else
		mdb_printf("TRUE ");

	mdb_printf(" %0?p\n", mio.mi_o_dev);

	return (DCMD_OK);
}
Beispiel #24
0
int
sonode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	const char *optf = NULL;
	const char *optt = NULL;
	const char *optp = NULL;
	int family, type, proto;
	int filter = 0;
	struct sonode so;

	if (!(flags & DCMD_ADDRSPEC)) {
		if (mdb_walk_dcmd("genunix`sonode", "genunix`sonode", argc,
		    argv) == -1) {
			mdb_warn("failed to walk sonode");
			return (DCMD_ERR);
		}

		return (DCMD_OK);
	}

	if (mdb_getopts(argc, argv,
	    'f', MDB_OPT_STR, &optf,
	    't', MDB_OPT_STR, &optt,
	    'p', MDB_OPT_STR, &optp,
	    NULL) != argc)
		return (DCMD_USAGE);

	if (optf != NULL) {
		if (strcmp("inet", optf) == 0)
			family = AF_INET;
		else if (strcmp("inet6", optf) == 0)
			family = AF_INET6;
		else if (strcmp("unix", optf) == 0)
			family = AF_UNIX;
		else
			family = mdb_strtoull(optf);
		filter = 1;
	}

	if (optt != NULL) {
		if (strcmp("stream", optt) == 0)
			type = SOCK_STREAM;
		else if (strcmp("dgram", optt) == 0)
			type = SOCK_DGRAM;
		else if (strcmp("raw", optt) == 0)
			type = SOCK_RAW;
		else
			type = mdb_strtoull(optt);
		filter = 1;
	}

	if (optp != NULL) {
		proto = mdb_strtoull(optp);
		filter = 1;
	}

	if (DCMD_HDRSPEC(flags) && !filter) {
		mdb_printf("%<u>%-?s Family Type Proto State Mode Flag "
		    "AccessVP%</u>\n", "Sonode:");
	}

	if (mdb_vread(&so, sizeof (so), addr) == -1) {
		mdb_warn("failed to read sonode at %p", addr);
		return (DCMD_ERR);
	}

	if ((optf != NULL) && (so.so_family != family))
		return (DCMD_OK);

	if ((optt != NULL) && (so.so_type != type))
		return (DCMD_OK);

	if ((optp != NULL) && (so.so_protocol != proto))
		return (DCMD_OK);

	if (filter) {
		mdb_printf("%0?p\n", addr);
		return (DCMD_OK);
	}

	mdb_printf("%0?p ", addr);

	switch (so.so_family) {
	case AF_UNIX:
		mdb_printf("unix  ");
		break;
	case AF_INET:
		mdb_printf("inet  ");
		break;
	case AF_INET6:
		mdb_printf("inet6 ");
		break;
	default:
		mdb_printf("%6hi", so.so_family);
	}

	switch (so.so_type) {
	case SOCK_STREAM:
		mdb_printf(" strm");
		break;
	case SOCK_DGRAM:
		mdb_printf(" dgrm");
		break;
	case SOCK_RAW:
		mdb_printf(" raw ");
		break;
	default:
		mdb_printf(" %4hi", so.so_type);
	}

	mdb_printf(" %5hi %05x %04x %04hx\n",
	    so.so_protocol, so.so_state, so.so_mode,
	    so.so_flag);

	return (DCMD_OK);
}
Beispiel #25
0
static int
dladm_show_bridge(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	show_bridge_args_t *args;
	GElf_Sym sym;
	int i;

	args = mdb_zalloc(sizeof (*args), UM_SLEEP);

	i = mdb_getopts(argc, argv,
	    'l', MDB_OPT_SETBITS, 1, &args->opt_l,
	    'f', MDB_OPT_SETBITS, 1, &args->opt_f,
	    't', MDB_OPT_SETBITS, 1, &args->opt_t,
	    NULL);

	argc -= i;
	argv += i;

	if (argc > 1 || (argc == 1 && argv[0].a_type != MDB_TYPE_STRING)) {
		mdb_free(args, sizeof (*args));
		return (DCMD_USAGE);
	}
	if (argc == 1)
		args->name = argv[0].a_un.a_str;

	if ((args->lbolt = mdb_get_lbolt()) == -1) {
		mdb_warn("failed to read lbolt");
		goto err;
	}

	if (flags & DCMD_ADDRSPEC) {
		if (args->name != NULL) {
			mdb_printf("bridge name and address are mutually "
			    "exclusive\n");
			goto err;
		}
		if (!args->opt_l && !args->opt_f && !args->opt_t)
			mdb_printf("%-?s %-7s %-16s %-7s %-7s\n", "ADDR",
			    "PROTECT", "NAME", "NLINKS", "NFWD");
		if (do_show_bridge(addr, NULL, args) != WALK_NEXT)
			goto err;
		mdb_free(args, sizeof (*args));
		return (DCMD_OK);
	} else {
		if ((args->opt_l || args->opt_f || args->opt_t) &&
		    args->name == NULL) {
			mdb_printf("need bridge name or address with -[lft]\n");
			goto err;
		}
		if (mdb_lookup_by_obj("bridge", "inst_list", &sym) == -1) {
			mdb_warn("failed to find 'bridge`inst_list'");
			goto err;
		}
		if (!args->opt_l && !args->opt_f && !args->opt_t)
			mdb_printf("%-?s %-7s %-16s %-7s %-7s %-7s %s\n",
			    "ADDR", "PROTECT", "NAME", "NLINKS", "NFWD",
			    "NNICKS", "NICK");
		if (mdb_pwalk("list", do_show_bridge, args,
		    (uintptr_t)sym.st_value) != DCMD_OK)
			goto err;
		if (!args->found && args->name != NULL) {
			mdb_printf("bridge instance %s not found\n",
			    args->name);
			goto err;
		}
		mdb_free(args, sizeof (*args));
		return (DCMD_OK);
	}

err:
	mdb_free(args, sizeof (*args));
	return (DCMD_ERR);
}
Beispiel #26
0
/*
 * Dump a UHCI QH (queue head).
 * -b walk/dump the chian of QHs starting with the one specified.
 * -d also dump the chain of TDs starting with the one specified.
 */
int
uhci_qh(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	uint_t		breadth_flag = FALSE, depth_flag = FALSE;
	uhci_state_t	uhci_state, *uhcip = &uhci_state;
	queue_head_t	qh;


	if (!(flags & DCMD_ADDRSPEC))
		return (DCMD_USAGE);

	if (addr & ~QH_LINK_PTR_MASK) {
		mdb_warn("address must be on a 16-byte boundary.\n");
		return (DCMD_ERR);
	}

	if (mdb_getopts(argc, argv,
	    'b', MDB_OPT_SETBITS, TRUE, &breadth_flag,
	    'd', MDB_OPT_SETBITS, TRUE, &depth_flag,
	    NULL) != argc) {
		return (DCMD_USAGE);
	}


	if (breadth_flag) {
		uint_t		new_argc = 0;
		mdb_arg_t	new_argv[1];


		if (depth_flag) {
			new_argc = 1;
			new_argv[0].a_type = MDB_TYPE_STRING;
			new_argv[0].a_un.a_str = "-d";
		}

		if ((mdb_pwalk_dcmd("uhci_qh", "uhci_qh", new_argc, new_argv,
		    addr)) != 0)  {
			mdb_warn("failed to walk 'uhci_qh'");
			return (DCMD_ERR);
		}
		return (DCMD_OK);
	}


	if (find_uhci_statep((void *)addr, UHCI_QH, uhcip) != 1) {
		mdb_warn("failed to find uhci_statep");
		return (DCMD_ERR);
	}


	if (mdb_vread(&qh, sizeof (qh), addr) != sizeof (qh))  {
		mdb_warn("failed to read qh at vaddr %p", addr);
		return (DCMD_ERR);
	}

	mdb_printf("\n  UHCI qh struct at (vaddr) %08x:\n", addr);

	if (!(qh.link_ptr & HC_END_OF_LIST) && qh.link_ptr != NULL) {
		mdb_printf("        link_ptr (paddr)    : %08x        "
		    "(vaddr)      : %p\n",
		    qh.link_ptr,
		    /* Note: uhcip needed by QH_VADDR macro */
		    QH_VADDR(qh.link_ptr & QH_LINK_PTR_MASK));
	} else {
		mdb_printf(
		    "        link_ptr (paddr)    : %08x\n",
		    qh.link_ptr);
	}

	if (!(qh.element_ptr & HC_END_OF_LIST) && qh.element_ptr != NULL) {
		mdb_printf("        element_ptr (paddr) : %08x        "
		    "(vaddr)      : %p\n",
		    qh.element_ptr,
		    /* Note: uhcip needed by TD_VADDR macro */
		    TD_VADDR(qh.element_ptr & QH_LINK_PTR_MASK));
	} else {
		mdb_printf(
		    "        element_ptr (paddr) : %08x\n", qh.element_ptr);
	}

	mdb_printf("        node                : %04x            "
	    "flag         : %04x\n",
	    qh.node, qh.qh_flag);
	mdb_printf("        prev_qh             : %?p        "
	    "td_tailp     : %?p\n",
	    qh.prev_qh, qh.td_tailp);
	mdb_printf("        bulk_xfer_isoc_info : %?p\n", qh.bulk_xfer_info);


	if (qh.link_ptr == NULL)  {
		mdb_printf("        --> Link pointer = NULL\n");
		return (DCMD_ERR);
	} else {

		/* Inform user if next link is a TD or QH.  */
		if (qh.link_ptr & HC_END_OF_LIST)  {
			mdb_printf("        "
			    "--> Link pointer invalid (terminate bit set).\n");
		} else {
			if ((qh.link_ptr & HC_QUEUE_HEAD) == HC_QUEUE_HEAD)  {
				mdb_printf("        "
				    "--> Link pointer points to a QH.\n");
			} else {
				/* Should never happen. */
				mdb_warn("        "
				    "--> Link pointer points to a TD.\n");
				return (DCMD_ERR);
			}
		}
	}


	if (qh.element_ptr == NULL)  {
		mdb_printf("        element_ptr = NULL\n");
		return (DCMD_ERR);
	} else {

		/* Inform user if next element is a TD or QH.  */
		if (qh.element_ptr & HC_END_OF_LIST)  {
			mdb_printf("        "
			    "-->Element pointer invalid (terminate bit set)."
			    "\n");
			return (DCMD_OK);
		} else {
			if ((qh.element_ptr & HC_QUEUE_HEAD) == HC_QUEUE_HEAD) {
				mdb_printf("        "
				    "--> Element pointer points to a QH.\n");
				/* Should never happen in UHCI implementation */
				return (DCMD_ERR);
			} else {
				mdb_printf("        "
				    "--> Element pointer points to a TD.\n");
			}
		}
	}

	/*
	 * If the user specified the -d (depth) option,
	 * dump all TDs linked to this TD via the element_ptr.
	 */
	if (depth_flag) {

		/* Traverse and display all the TDs in the chain */
		if (mdb_pwalk_dcmd("uhci_td", "uhci_td", argc, argv,
		    (uintptr_t)(TD_VADDR(qh.element_ptr &
		    QH_LINK_PTR_MASK))) == -1) {
			mdb_warn("failed to walk 'uhci_td'");
			return (DCMD_ERR);
		}
	}

	return (DCMD_OK);
}
Beispiel #27
0
/*
 * Dump a UHCI TD (transaction descriptor);
 * or (-d) the chain of TDs starting with the one specified.
 */
int
uhci_td(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	uint_t		depth_flag = FALSE;
	uhci_state_t	uhci_state, *uhcip = &uhci_state;
	uhci_td_t	td;


	if (!(flags & DCMD_ADDRSPEC))
		return (DCMD_USAGE);

	if (addr & ~QH_LINK_PTR_MASK) {
		mdb_warn("address must be on a 16-byte boundary.\n");
		return (DCMD_ERR);
	}

	if (mdb_getopts(argc, argv,
	    'd', MDB_OPT_SETBITS, TRUE, &depth_flag,
	    NULL) != argc) {
		return (DCMD_USAGE);
	}


	if (depth_flag) {
		if (mdb_pwalk_dcmd("uhci_td", "uhci_td", 0, NULL, addr) == -1) {
			mdb_warn("failed to walk 'uhci_td'");
			return (DCMD_ERR);
		}
		return (DCMD_OK);
	}


	if (find_uhci_statep((void *)addr, UHCI_TD, uhcip) != 1) {
		mdb_warn("failed to find uhci_statep");
		return (DCMD_ERR);
	}

	if (mdb_vread(&td, sizeof (td), addr) != sizeof (td))  {
		mdb_warn("failed to read td at vaddr %p", addr);
		return (DCMD_ERR);
	}

	mdb_printf("\n  UHCI td struct at (vaddr) %08x:\n", addr);

	if (!(td.link_ptr & HC_END_OF_LIST) && td.link_ptr != NULL) {
		mdb_printf("        link_ptr (paddr)    : %-8x        "
		    "(vaddr)      : %p\n",
		    td.link_ptr,
		    /* Note: uhcip needed by TD_VADDR macro */
		    TD_VADDR(td.link_ptr & QH_LINK_PTR_MASK));
	} else {
		mdb_printf("        link_ptr (paddr)    : %-8x\n",
		    td.link_ptr);
	}
	mdb_printf("        td_dword2           : %08x\n", td.dw2);
	mdb_printf("        td_dword3           : %08x\n", td.dw3);
	mdb_printf("        buffer_address      : %08x\n", td.buffer_address);
	mdb_printf("        qh_td_prev          : %?p        "
	    "tw_td_next   : %?p\n",
	    td.qh_td_prev, td.tw_td_next);
	mdb_printf("        outst_td_prev        : %?p        "
	    "outst_td_next : %?p\n",
	    td.outst_td_prev, td.outst_td_next);
	mdb_printf("        tw                  : %?p        "
	    "flag         : %02x\n", td.tw, td.flag);
	mdb_printf("        isoc_next           : %?p        "
	    "isoc_prev    : %0x\n", td.isoc_next, td.isoc_prev);
	mdb_printf("        isoc_pkt_index      : %0x        "
	    "startingframe: %0x\n", td.isoc_pkt_index, td.starting_frame);


	if (td.link_ptr == NULL)  {
		mdb_printf("        --> Link pointer = NULL\n");
		return (DCMD_ERR);
	} else {

		/* Inform user if link is to a TD or QH.  */
		if (td.link_ptr & HC_END_OF_LIST)  {
			mdb_printf("        "
			    "--> Link pointer invalid (terminate bit set).\n");
		} else {
			if ((td.link_ptr & HC_QUEUE_HEAD) == HC_QUEUE_HEAD)  {
				mdb_printf("        "
				    "--> Link pointer points to a QH.\n");
			} else {
				mdb_printf("        "
				    "--> Link pointer points to a TD.\n");
			}
		}
	}

	return (DCMD_OK);
}
Beispiel #28
0
static int
fmd_xprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	uint_t opt_s = FALSE, opt_l = FALSE, opt_r = FALSE, opt_u = FALSE;
	fmd_xprt_impl_t xi;

	if (mdb_getopts(argc, argv,
	    'l', MDB_OPT_SETBITS, TRUE, &opt_l,
	    'r', MDB_OPT_SETBITS, TRUE, &opt_r,
	    's', MDB_OPT_SETBITS, TRUE, &opt_s,
	    'u', MDB_OPT_SETBITS, TRUE, &opt_u, NULL) != argc)
		return (DCMD_USAGE);

	if (!(flags & DCMD_ADDRSPEC)) {
		if (mdb_walk_dcmd("fmd_xprt", "fmd_xprt", argc, argv) != 0) {
			mdb_warn("failed to walk fmd_xprt");
			return (DCMD_ERR);
		}
		return (DCMD_OK);
	}

	if (mdb_vread(&xi, sizeof (xi), addr) != sizeof (xi)) {
		mdb_warn("failed to read fmd_xprt at %p", addr);
		return (DCMD_ERR);
	}

	if (DCMD_HDRSPEC(flags)) {
		mdb_printf("%<u>%-8s %-4s %-4s %-5s %s%</u>\n",
		    "ADDR", "ID", "VERS", "FLAGS", "STATE");
	}

	mdb_printf("%-8p %-4d %-4u %-5x %a\n",
	    addr, xi.xi_id, xi.xi_version, xi.xi_flags, xi.xi_state);

	if (opt_l | opt_s) {
		(void) mdb_inc_indent(4);
		mdb_printf("Local subscriptions requested by peer:\n");
		mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS");
		(void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi,
		    addr + OFFSETOF(fmd_xprt_impl_t, xi_lsub));
		(void) mdb_dec_indent(4);
	}

	if (opt_r | opt_s) {
		(void) mdb_inc_indent(4);
		mdb_printf("Remote subscriptions requested of peer:\n");
		mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS");
		(void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi,
		    addr + OFFSETOF(fmd_xprt_impl_t, xi_rsub));
		(void) mdb_dec_indent(4);
	}

	if (opt_u | opt_s) {
		(void) mdb_inc_indent(4);
		mdb_printf("Pending unsubscription acknowledgements:\n");
		mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS");
		(void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi,
		    addr + OFFSETOF(fmd_xprt_impl_t, xi_usub));
		(void) mdb_dec_indent(4);
	}

	return (DCMD_OK);
}
Beispiel #29
0
static int
request_log(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	request_log_entry_t cur;
	hrtime_t dur;
	hrtime_t dursec;
	hrtime_t durnsec;
	char durstr[20];
	char stampstr[20];
	char requstr[30];
	char respstr[30];
	char typestr[30];
	uintptr_t node = 0;
	uintptr_t client = 0;
	uint64_t clientid = 0;

	int idx;
	int opt_v = FALSE;			/* verbose */

	if (!(flags & DCMD_ADDRSPEC)) {
		if (mdb_walk_dcmd("configd_log", "configd_log", argc,
		    argv) == -1) {
			mdb_warn("can't walk 'configd_log'");
			return (DCMD_ERR);
		}
		return (DCMD_OK);
	}

	if (mdb_getopts(argc, argv,
	    'c', MDB_OPT_UINTPTR, &client,
	    'i', MDB_OPT_UINT64, &clientid,
	    'n', MDB_OPT_UINTPTR, &node,
	    'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc)
		return (DCMD_USAGE);

	if (DCMD_HDRSPEC(flags)) {
		mdb_printf("%<u>%-?s %-4s %-14s %9s %-22s %-17s\n%</u>",
		    "ADDR", "THRD", "START", "DURATION", "REQUEST",
		    "RESPONSE");
	}

	if (mdb_vread(&cur, sizeof (cur), addr) == -1) {
		mdb_warn("couldn't read log entry at %p", addr);
		return (DCMD_ERR);
	}

	/*
	 * apply filters, if any.
	 */
	if (clientid != 0 && clientid != cur.rl_clientid)
		return (DCMD_OK);

	if (client != 0 && client != (uintptr_t)cur.rl_client)
		return (DCMD_OK);

	if (node != 0) {
		for (idx = 0; idx < MIN(MAX_PTRS, cur.rl_num_ptrs); idx++) {
			if ((uintptr_t)cur.rl_ptrs[idx].rlp_data == node) {
				node = 0;		/* found it */
				break;
			}
		}
		if (node != 0)
			return (DCMD_OK);
	}

	enum_lookup(requstr, sizeof (requstr), request_enum, cur.rl_request,
	    "REP_PROTOCOL_", "");

	if (cur.rl_end != 0) {
		enum_lookup(respstr, sizeof (respstr), response_enum,
		    cur.rl_response, "REP_PROTOCOL_", "FAIL_");

		dur = cur.rl_end - cur.rl_start;
		dursec = dur / NANOSEC;
		durnsec = dur % NANOSEC;

		if (dursec <= 9)
			mdb_snprintf(durstr, sizeof (durstr),
			    "%lld.%06lld",
			    dursec, durnsec / (NANOSEC / MICROSEC));
		else if (dursec <= 9999)
			mdb_snprintf(durstr, sizeof (durstr),
			    "%lld.%03lld",
			    dursec, NSEC2MSEC(durnsec));
		else
			mdb_snprintf(durstr, sizeof (durstr),
			    "%lld", dursec);
	} else {
		(void) strcpy(durstr, "-");
		(void) strcpy(respstr, "-");
	}

	if (max_time_seen != 0 && max_time_seen >= cur.rl_start) {
		dur = max_time_seen - cur.rl_start;
		dursec = dur / NANOSEC;
		durnsec = dur % NANOSEC;

		if (dursec <= 99ULL)
			mdb_snprintf(stampstr, sizeof (stampstr),
			    "-%lld.%09lld", dursec, durnsec);
		else if (dursec <= 99999ULL)
			mdb_snprintf(stampstr, sizeof (stampstr),
			    "-%lld.%06lld",
			    dursec, durnsec / (NANOSEC / MICROSEC));
		else if (dursec <= 99999999ULL)
			mdb_snprintf(stampstr, sizeof (stampstr),
			    "-%lld.%03lld",
			    dursec, NSEC2MSEC(durnsec));
		else
			mdb_snprintf(stampstr, sizeof (stampstr),
			    "-%lld", dursec);
	} else {
		(void) strcpy(stampstr, "-");
	}

	mdb_printf("%0?x %4d T%13s %9s %-22s %-17s\n",
	    addr, cur.rl_tid, stampstr, durstr, requstr, respstr);

	if (opt_v) {
		mdb_printf("\tclient: %?p (%d)\tptrs: %d\tstamp: %llx\n",
		    cur.rl_client, cur.rl_clientid, cur.rl_num_ptrs,
		    cur.rl_start);
		for (idx = 0; idx < MIN(MAX_PTRS, cur.rl_num_ptrs); idx++) {
			enum_lookup(typestr, sizeof (typestr), ptr_type_enum,
			    cur.rl_ptrs[idx].rlp_type, "RC_PTR_TYPE_", "");
			mdb_printf("\t\t%-7s %5d %?p %?p\n", typestr,
			    cur.rl_ptrs[idx].rlp_id, cur.rl_ptrs[idx].rlp_ptr,
			    cur.rl_ptrs[idx].rlp_data);
		}
		mdb_printf("\n");
	}
	return (DCMD_OK);
}
Beispiel #30
0
/*ARGSUSED*/
int
netstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	uint_t opts = 0;
	const char *optf = NULL;
	const char *optP = NULL;
	netstat_cb_data_t *cbdata;
	int status;
	int af = 0;

	if (mdb_getopts(argc, argv,
	    'a', MDB_OPT_SETBITS, NETSTAT_ALL, &opts,
	    'f', MDB_OPT_STR, &optf,
	    'P', MDB_OPT_STR, &optP,
	    'r', MDB_OPT_SETBITS, NETSTAT_ROUTE, &opts,
	    'v', MDB_OPT_SETBITS, NETSTAT_VERBOSE, &opts,
	    NULL) != argc)
		return (DCMD_USAGE);

	if (optP != NULL) {
		if ((strcmp("tcp", optP) != 0) && (strcmp("udp", optP) != 0) &&
		    (strcmp("icmp", optP) != 0))
			return (DCMD_USAGE);
		if (opts & NETSTAT_ROUTE)
			return (DCMD_USAGE);
	}

	if (optf == NULL)
		opts |= NETSTAT_V4 | NETSTAT_V6 | NETSTAT_UNIX;
	else if (strcmp("inet", optf) == 0)
		opts |= NETSTAT_V4;
	else if (strcmp("inet6", optf) == 0)
		opts |= NETSTAT_V6;
	else if (strcmp("unix", optf) == 0)
		opts |= NETSTAT_UNIX;
	else
		return (DCMD_USAGE);

	if (opts & NETSTAT_ROUTE) {
		if (!(opts & (NETSTAT_V4|NETSTAT_V6)))
			return (DCMD_USAGE);
		if (opts & NETSTAT_V4) {
			opts |= NETSTAT_FIRST;
			if (mdb_walk("ip`ire", netstat_irev4_cb, &opts) == -1) {
				mdb_warn("failed to walk ip`ire");
				return (DCMD_ERR);
			}
		}
		if (opts & NETSTAT_V6) {
			opts |= NETSTAT_FIRST;
			if (mdb_walk("ip`ire", netstat_irev6_cb, &opts) == -1) {
				mdb_warn("failed to walk ip`ire");
				return (DCMD_ERR);
			}
		}
		return (DCMD_OK);
	}

	if ((opts & NETSTAT_UNIX) && (optP == NULL)) {
		/* Print Unix Domain Sockets */
		mdb_printf("%<u>%-?s %-10s %-?s %-?s %-14s %-14s %s%</u>\n",
		    "AF_UNIX", "Type", "Vnode", "Conn", "Local Addr",
		    "Remote Addr", "Zone");

		if (mdb_walk("genunix`sonode", netstat_unix_cb, NULL) == -1) {
			mdb_warn("failed to walk genunix`sonode");
			return (DCMD_ERR);
		}
		if (!(opts & (NETSTAT_V4 | NETSTAT_V6)))
			return (DCMD_OK);
	}

	cbdata = mdb_alloc(sizeof (netstat_cb_data_t), UM_SLEEP);
	cbdata->opts = opts;
	if ((optf != NULL) && (opts & NETSTAT_V4))
		af = AF_INET;
	else if ((optf != NULL) && (opts & NETSTAT_V6))
		af = AF_INET6;

	cbdata->af = af;
	if ((optP == NULL) || (strcmp("tcp", optP) == 0)) {
		status = netstat_print_common("tcp_conn_cache", IPPROTO_TCP,
		    netstat_tcp_cb, cbdata);
		if (status != DCMD_OK)
			goto out;
	}

	if ((optP == NULL) || (strcmp("udp", optP) == 0)) {
		status = netstat_print_common("udp_conn_cache", IPPROTO_UDP,
		    netstat_udp_cb, cbdata);
		if (status != DCMD_OK)
			goto out;
	}

	if ((optP == NULL) || (strcmp("icmp", optP) == 0)) {
		status = netstat_print_common("rawip_conn_cache", IPPROTO_ICMP,
		    netstat_icmp_cb, cbdata);
		if (status != DCMD_OK)
			goto out;
	}
out:
	mdb_free(cbdata, sizeof (netstat_cb_data_t));
	return (status);
}