xref: /illumos-gate/usr/src/cmd/mdb/common/modules/nsmb/nsmb.c (revision adee678425979226b2b55d1a0b39ce4c989382e9)
14bff34e3Sthurlow /*
24bff34e3Sthurlow  * CDDL HEADER START
34bff34e3Sthurlow  *
44bff34e3Sthurlow  * The contents of this file are subject to the terms of the
54bff34e3Sthurlow  * Common Development and Distribution License (the "License").
64bff34e3Sthurlow  * You may not use this file except in compliance with the License.
74bff34e3Sthurlow  *
84bff34e3Sthurlow  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94bff34e3Sthurlow  * or http://www.opensolaris.org/os/licensing.
104bff34e3Sthurlow  * See the License for the specific language governing permissions
114bff34e3Sthurlow  * and limitations under the License.
124bff34e3Sthurlow  *
134bff34e3Sthurlow  * When distributing Covered Code, include this CDDL HEADER in each
144bff34e3Sthurlow  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154bff34e3Sthurlow  * If applicable, add the following below this CDDL HEADER, with the
164bff34e3Sthurlow  * fields enclosed by brackets "[]" replaced with your own identifying
174bff34e3Sthurlow  * information: Portions Copyright [yyyy] [name of copyright owner]
184bff34e3Sthurlow  *
194bff34e3Sthurlow  * CDDL HEADER END
204bff34e3Sthurlow  */
214bff34e3Sthurlow 
224bff34e3Sthurlow /*
23613a2f6bSGordon Ross  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
244bff34e3Sthurlow  * Use is subject to license terms.
25*adee6784SGordon Ross  *
26*adee6784SGordon Ross  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
274bff34e3Sthurlow  */
284bff34e3Sthurlow 
294bff34e3Sthurlow 
304bff34e3Sthurlow #include <sys/mdb_modapi.h>
31613a2f6bSGordon Ross #include <mdb/mdb_ctf.h>
324bff34e3Sthurlow #include <sys/types.h>
33613a2f6bSGordon Ross #include <sys/socket.h>
344bff34e3Sthurlow 
35430b4c46SGordon Ross #include <netsmb/smb_conn.h>
36430b4c46SGordon Ross #include <netsmb/smb_rq.h>
37430b4c46SGordon Ross #include <netsmb/smb_pass.h>
384bff34e3Sthurlow 
398329232eSGordon Ross #ifdef _KERNEL
408329232eSGordon Ross #define	NSMB_OBJNAME	"nsmb"
418329232eSGordon Ross #else
428329232eSGordon Ross #define	NSMB_OBJNAME	"libfknsmb.so.1"
438329232eSGordon Ross #endif
448329232eSGordon Ross 
454bff34e3Sthurlow #define	OPT_VERBOSE	0x0001	/* Be [-v]erbose in dcmd's */
464bff34e3Sthurlow #define	OPT_RECURSE	0x0002	/* recursive display */
474bff34e3Sthurlow 
484bff34e3Sthurlow /*
494bff34e3Sthurlow  * We need to read in a private copy
504bff34e3Sthurlow  * of every string we want to print out.
514bff34e3Sthurlow  */
524bff34e3Sthurlow void
print_str(uintptr_t addr)534bff34e3Sthurlow print_str(uintptr_t addr)
544bff34e3Sthurlow {
554bff34e3Sthurlow 	char buf[32];
564bff34e3Sthurlow 	int len, mx = sizeof (buf) - 4;
574bff34e3Sthurlow 
584bff34e3Sthurlow 	if ((len = mdb_readstr(buf, sizeof (buf), addr)) <= 0) {
594bff34e3Sthurlow 		mdb_printf(" (%p)", addr);
604bff34e3Sthurlow 	} else {
614bff34e3Sthurlow 		if (len > mx)
624bff34e3Sthurlow 			strcpy(&buf[mx], "...");
634bff34e3Sthurlow 		mdb_printf(" %s", buf);
644bff34e3Sthurlow 	}
654bff34e3Sthurlow }
664bff34e3Sthurlow 
674bff34e3Sthurlow 
684bff34e3Sthurlow /*
694bff34e3Sthurlow  * Walker for smb_connobj_t structures, including
704bff34e3Sthurlow  * smb_vc_t and smb_share_t which "inherit" from it.
714bff34e3Sthurlow  * Tricky: Exploit the "inheritance" of smb_connobj_t
724bff34e3Sthurlow  * with common functions for walk_init, walk_next.
734bff34e3Sthurlow  */
744bff34e3Sthurlow typedef struct smb_co_walk_data {
754bff34e3Sthurlow 	uintptr_t	pp;
76*adee6784SGordon Ross 	int level;		/* SMBL_SM, SMBL_VC, SMBL_SHARE, ...  */
774bff34e3Sthurlow 	int size;		/* sizeof (union member) */
784bff34e3Sthurlow 	union co_u {
794bff34e3Sthurlow 		smb_connobj_t	co;	/* copy of the list element */
804bff34e3Sthurlow 		smb_vc_t	vc;
814bff34e3Sthurlow 		smb_share_t	ss;
82*adee6784SGordon Ross 		smb_fh_t	fh;
834bff34e3Sthurlow 	} u;
844bff34e3Sthurlow } smb_co_walk_data_t;
854bff34e3Sthurlow 
864bff34e3Sthurlow /*
874bff34e3Sthurlow  * Common walk_init for walking structs inherited
884bff34e3Sthurlow  * from smb_connobj_t (smb_vc_t, smb_share_t)
894bff34e3Sthurlow  */
904bff34e3Sthurlow int
smb_co_walk_init(mdb_walk_state_t * wsp,int level)914bff34e3Sthurlow smb_co_walk_init(mdb_walk_state_t *wsp, int level)
924bff34e3Sthurlow {
934bff34e3Sthurlow 	smb_co_walk_data_t *smbw;
944bff34e3Sthurlow 	size_t psz;
954bff34e3Sthurlow 
96892ad162SToomas Soome 	if (wsp->walk_addr == 0)
974bff34e3Sthurlow 		return (WALK_ERR);
984bff34e3Sthurlow 
994bff34e3Sthurlow 	smbw = mdb_alloc(sizeof (*smbw), UM_SLEEP | UM_GC);
1004bff34e3Sthurlow 	wsp->walk_data = smbw;
1014bff34e3Sthurlow 
1024bff34e3Sthurlow 	/*
1034bff34e3Sthurlow 	 * Save the parent pointer for later checks, and
1044bff34e3Sthurlow 	 * the level so we know which union member it is.
1054bff34e3Sthurlow 	 * Also the size of this union member.
1064bff34e3Sthurlow 	 */
1074bff34e3Sthurlow 	smbw->pp = wsp->walk_addr;
1084bff34e3Sthurlow 	smbw->level = level;
1094bff34e3Sthurlow 	switch (level) {
1104bff34e3Sthurlow 	case SMBL_SM:
1114bff34e3Sthurlow 		smbw->size = sizeof (smbw->u.co);
1124bff34e3Sthurlow 		break;
1134bff34e3Sthurlow 	case SMBL_VC:
1144bff34e3Sthurlow 		smbw->size = sizeof (smbw->u.vc);
1154bff34e3Sthurlow 		break;
1164bff34e3Sthurlow 	case SMBL_SHARE:
1174bff34e3Sthurlow 		smbw->size = sizeof (smbw->u.ss);
1184bff34e3Sthurlow 		break;
119*adee6784SGordon Ross 	case SMBL_FH:
120*adee6784SGordon Ross 		smbw->size = sizeof (smbw->u.fh);
121*adee6784SGordon Ross 		break;
1224bff34e3Sthurlow 	default:
1234bff34e3Sthurlow 		smbw->size = sizeof (smbw->u);
1244bff34e3Sthurlow 		break;
1254bff34e3Sthurlow 	}
1264bff34e3Sthurlow 
1274bff34e3Sthurlow 	/*
1284bff34e3Sthurlow 	 * Read in the parent object.  Just need the
1294bff34e3Sthurlow 	 * invariant part (smb_connobj_t) so we can
1304bff34e3Sthurlow 	 * get the list of children below it.
1314bff34e3Sthurlow 	 */
1324bff34e3Sthurlow 	psz = sizeof (smbw->u.co);
1334bff34e3Sthurlow 	if (mdb_vread(&smbw->u.co, psz, smbw->pp) != psz) {
1344bff34e3Sthurlow 		mdb_warn("cannot read connobj from %p", smbw->pp);
1354bff34e3Sthurlow 		return (WALK_ERR);
1364bff34e3Sthurlow 	}
1374bff34e3Sthurlow 
1384bff34e3Sthurlow 	/*
1394bff34e3Sthurlow 	 * Finally, setup to walk the list of children.
1404bff34e3Sthurlow 	 */
1414bff34e3Sthurlow 	wsp->walk_addr = (uintptr_t)smbw->u.co.co_children.slh_first;
1424bff34e3Sthurlow 
1434bff34e3Sthurlow 	return (WALK_NEXT);
1444bff34e3Sthurlow }
1454bff34e3Sthurlow 
1464bff34e3Sthurlow /*
1474bff34e3Sthurlow  * Walk the (global) VC list.
1484bff34e3Sthurlow  */
1494bff34e3Sthurlow int
smb_vc_walk_init(mdb_walk_state_t * wsp)1504bff34e3Sthurlow smb_vc_walk_init(mdb_walk_state_t *wsp)
1514bff34e3Sthurlow {
1524bff34e3Sthurlow 	GElf_Sym sym;
1534bff34e3Sthurlow 
154892ad162SToomas Soome 	if (wsp->walk_addr != 0) {
1554bff34e3Sthurlow 		mdb_warn("::walk smb_vc only supports global walks\n");
1564bff34e3Sthurlow 		return (WALK_ERR);
1574bff34e3Sthurlow 	}
1584bff34e3Sthurlow 
1594bff34e3Sthurlow 	/* Locate the VC list head. */
1608329232eSGordon Ross 	if (mdb_lookup_by_obj(NSMB_OBJNAME, "smb_vclist", &sym)) {
1614bff34e3Sthurlow 		mdb_warn("failed to lookup `smb_vclist'\n");
1624bff34e3Sthurlow 		return (WALK_ERR);
1634bff34e3Sthurlow 	}
1644bff34e3Sthurlow 	wsp->walk_addr = sym.st_value;
1654bff34e3Sthurlow 
1664bff34e3Sthurlow 	return (smb_co_walk_init(wsp, SMBL_VC));
1674bff34e3Sthurlow }
1684bff34e3Sthurlow 
1694bff34e3Sthurlow /*
1704bff34e3Sthurlow  * Walk the share list below some VC.
1714bff34e3Sthurlow  */
1724bff34e3Sthurlow int
smb_ss_walk_init(mdb_walk_state_t * wsp)1734bff34e3Sthurlow smb_ss_walk_init(mdb_walk_state_t *wsp)
1744bff34e3Sthurlow {
1754bff34e3Sthurlow 
1764bff34e3Sthurlow 	/*
1774bff34e3Sthurlow 	 * Initial walk_addr is address of parent (VC)
1784bff34e3Sthurlow 	 */
1794bff34e3Sthurlow 	if (wsp->walk_addr == 0) {
1804bff34e3Sthurlow 		mdb_warn("::walk smb_ss does not support global walks\n");
1814bff34e3Sthurlow 		return (WALK_ERR);
1824bff34e3Sthurlow 	}
1834bff34e3Sthurlow 
1844bff34e3Sthurlow 	return (smb_co_walk_init(wsp, SMBL_SHARE));
1854bff34e3Sthurlow }
1864bff34e3Sthurlow 
1874bff34e3Sthurlow /*
188*adee6784SGordon Ross  * Walk the file hande list below some share.
189*adee6784SGordon Ross  */
190*adee6784SGordon Ross int
smb_fh_walk_init(mdb_walk_state_t * wsp)191*adee6784SGordon Ross smb_fh_walk_init(mdb_walk_state_t *wsp)
192*adee6784SGordon Ross {
193*adee6784SGordon Ross 
194*adee6784SGordon Ross 	/*
195*adee6784SGordon Ross 	 * Initial walk_addr is address of parent (share)
196*adee6784SGordon Ross 	 */
197*adee6784SGordon Ross 	if (wsp->walk_addr == 0) {
198*adee6784SGordon Ross 		mdb_warn("::walk smb_fh does not support global walks\n");
199*adee6784SGordon Ross 		return (WALK_ERR);
200*adee6784SGordon Ross 	}
201*adee6784SGordon Ross 
202*adee6784SGordon Ross 	return (smb_co_walk_init(wsp, SMBL_FH));
203*adee6784SGordon Ross }
204*adee6784SGordon Ross 
205*adee6784SGordon Ross /*
2064bff34e3Sthurlow  * Common walk_step for walking structs inherited
2074bff34e3Sthurlow  * from smb_connobj_t (smb_vc_t, smb_share_t)
2084bff34e3Sthurlow  */
2094bff34e3Sthurlow int
smb_co_walk_step(mdb_walk_state_t * wsp)2104bff34e3Sthurlow smb_co_walk_step(mdb_walk_state_t *wsp)
2114bff34e3Sthurlow {
2124bff34e3Sthurlow 	smb_co_walk_data_t *smbw = wsp->walk_data;
2134bff34e3Sthurlow 	int status;
2144bff34e3Sthurlow 
215892ad162SToomas Soome 	if (wsp->walk_addr == 0)
2164bff34e3Sthurlow 		return (WALK_DONE);
2174bff34e3Sthurlow 
2184bff34e3Sthurlow 	if (mdb_vread(&smbw->u, smbw->size, wsp->walk_addr)
2194bff34e3Sthurlow 	    != smbw->size) {
2204bff34e3Sthurlow 		mdb_warn("cannot read connobj from %p", wsp->walk_addr);
2214bff34e3Sthurlow 		return (WALK_ERR);
2224bff34e3Sthurlow 	}
2234bff34e3Sthurlow 
2244bff34e3Sthurlow 	/* XXX: Sanity check level? parent pointer? */
2254bff34e3Sthurlow 
2264bff34e3Sthurlow 	status = wsp->walk_callback(wsp->walk_addr, &smbw->u,
2274bff34e3Sthurlow 	    wsp->walk_cbdata);
2284bff34e3Sthurlow 
2294bff34e3Sthurlow 	wsp->walk_addr = (uintptr_t)smbw->u.co.co_next.sle_next;
2304bff34e3Sthurlow 
2314bff34e3Sthurlow 	return (status);
2324bff34e3Sthurlow }
2334bff34e3Sthurlow 
2344bff34e3Sthurlow 
2354bff34e3Sthurlow /*
2364bff34e3Sthurlow  * Dcmd (and callback function) to print a summary of
2374bff34e3Sthurlow  * all VCs, and optionally all shares under each VC.
2384bff34e3Sthurlow  */
2394bff34e3Sthurlow 
2404bff34e3Sthurlow typedef struct smb_co_cbdata {
2414bff34e3Sthurlow 	int flags;		/* OPT_...  */
2424bff34e3Sthurlow 	int printed_header;
243613a2f6bSGordon Ross 	mdb_ctf_id_t ctf_id;
2444bff34e3Sthurlow } smb_co_cbdata_t;
2454bff34e3Sthurlow 
2464bff34e3Sthurlow /*
247*adee6784SGordon Ross  * Call-back function for walking a file handle list.
248*adee6784SGordon Ross  */
249*adee6784SGordon Ross /* ARGSUSED */
250*adee6784SGordon Ross int
smb_fh_cb(uintptr_t addr,const void * data,void * arg)251*adee6784SGordon Ross smb_fh_cb(uintptr_t addr, const void *data, void *arg)
252*adee6784SGordon Ross {
253*adee6784SGordon Ross 	const smb_fh_t *fhp = data;
254*adee6784SGordon Ross 	// smb_co_cbdata_t *cbd = arg;
255*adee6784SGordon Ross 
256*adee6784SGordon Ross 	mdb_inc_indent(2);
257*adee6784SGordon Ross 	mdb_printf(" %-p", addr);
258*adee6784SGordon Ross 	if (fhp->fh_fid2.fid_volatile != 0) {
259*adee6784SGordon Ross 		mdb_printf("\t0x%llx\n",
260*adee6784SGordon Ross 		    (long long) fhp->fh_fid2.fid_volatile);
261*adee6784SGordon Ross 	} else {
262*adee6784SGordon Ross 		mdb_printf("\t0x%x\n", fhp->fh_fid1);
263*adee6784SGordon Ross 	}
264*adee6784SGordon Ross 
265*adee6784SGordon Ross 	mdb_dec_indent(2);
266*adee6784SGordon Ross 
267*adee6784SGordon Ross 	return (WALK_NEXT);
268*adee6784SGordon Ross }
269*adee6784SGordon Ross 
270*adee6784SGordon Ross /*
2714bff34e3Sthurlow  * Call-back function for walking a share list.
2724bff34e3Sthurlow  */
2734bff34e3Sthurlow int
smb_ss_cb(uintptr_t addr,const void * data,void * arg)2744bff34e3Sthurlow smb_ss_cb(uintptr_t addr, const void *data, void *arg)
2754bff34e3Sthurlow {
2764bff34e3Sthurlow 	const smb_share_t *ssp = data;
2774bff34e3Sthurlow 	smb_co_cbdata_t *cbd = arg;
278*adee6784SGordon Ross 	uint32_t tid;
2794bff34e3Sthurlow 
280*adee6784SGordon Ross 	tid = ssp->ss2_tree_id;
281*adee6784SGordon Ross 	if (tid == 0)
282*adee6784SGordon Ross 		tid = ssp->ss_tid;
2834bff34e3Sthurlow 
284*adee6784SGordon Ross 	mdb_printf(" %-p\t0x%x\t%s\n", addr, tid, ssp->ss_name);
285*adee6784SGordon Ross 
286*adee6784SGordon Ross 	if (cbd->flags & OPT_RECURSE) {
2874bff34e3Sthurlow 		mdb_inc_indent(2);
288*adee6784SGordon Ross 		if (mdb_pwalk("nsmb_fh", smb_fh_cb, cbd, addr) < 0) {
289*adee6784SGordon Ross 			mdb_warn("failed to walk 'nsmb_fh'");
290*adee6784SGordon Ross 			/* Don't: return (WALK_ERR); */
291*adee6784SGordon Ross 		}
2924bff34e3Sthurlow 		mdb_dec_indent(2);
2934bff34e3Sthurlow 	}
2944bff34e3Sthurlow 
2954bff34e3Sthurlow 	return (WALK_NEXT);
2964bff34e3Sthurlow }
2974bff34e3Sthurlow 
298613a2f6bSGordon Ross static const char *
vcstate_str(smb_co_cbdata_t * cbd,int stval)299613a2f6bSGordon Ross vcstate_str(smb_co_cbdata_t *cbd, int stval)
300613a2f6bSGordon Ross {
301613a2f6bSGordon Ross 	static const char prefix[] = "SMBIOD_ST_";
302613a2f6bSGordon Ross 	int prefix_len = sizeof (prefix) - 1;
303613a2f6bSGordon Ross 	mdb_ctf_id_t vcst_enum;
304613a2f6bSGordon Ross 	const char *cp;
305613a2f6bSGordon Ross 
306613a2f6bSGordon Ross 	/* Got this in smb_vc_dcmd. */
307613a2f6bSGordon Ross 	vcst_enum = cbd->ctf_id;
308613a2f6bSGordon Ross 
309613a2f6bSGordon Ross 	/* Get the name for the enum value. */
310613a2f6bSGordon Ross 	if ((cp = mdb_ctf_enum_name(vcst_enum, stval)) == NULL)
311613a2f6bSGordon Ross 		return ("?");
312613a2f6bSGordon Ross 
313613a2f6bSGordon Ross 	/* Skip the prefix part. */
314613a2f6bSGordon Ross 	if (strncmp(cp, prefix, prefix_len) == 0)
315613a2f6bSGordon Ross 		cp += prefix_len;
316613a2f6bSGordon Ross 
317613a2f6bSGordon Ross 	return (cp);
318613a2f6bSGordon Ross }
319613a2f6bSGordon Ross 
3204bff34e3Sthurlow /*
3214bff34e3Sthurlow  * Call-back function for walking the VC list.
3224bff34e3Sthurlow  */
3234bff34e3Sthurlow int
smb_vc_cb(uintptr_t addr,const void * data,void * arg)3244bff34e3Sthurlow smb_vc_cb(uintptr_t addr, const void *data, void *arg)
3254bff34e3Sthurlow {
3264bff34e3Sthurlow 	const smb_vc_t *vcp = data;
3274bff34e3Sthurlow 	smb_co_cbdata_t *cbd = arg;
3284bff34e3Sthurlow 
3294bff34e3Sthurlow 	if (cbd->printed_header == 0) {
3304bff34e3Sthurlow 		cbd->printed_header = 1;
331613a2f6bSGordon Ross 		mdb_printf("// smb_vc_t  uid  server  \tuser\t\tstate\n");
3324bff34e3Sthurlow 	}
3334bff34e3Sthurlow 
3344bff34e3Sthurlow 	mdb_printf("%-p", addr);
335613a2f6bSGordon Ross 	mdb_printf(" %7d", vcp->vc_owner);
336613a2f6bSGordon Ross 
337613a2f6bSGordon Ross 	switch (vcp->vc_srvaddr.sa.sa_family) {
338613a2f6bSGordon Ross 	case AF_INET:
339613a2f6bSGordon Ross 		mdb_printf(" %I", vcp->vc_srvaddr.sin.sin_addr);
340613a2f6bSGordon Ross 		break;
341613a2f6bSGordon Ross 	case AF_INET6:
342613a2f6bSGordon Ross 		mdb_printf(" %N", &vcp->vc_srvaddr.sin6.sin6_addr);
343613a2f6bSGordon Ross 		break;
344613a2f6bSGordon Ross 	default:
345613a2f6bSGordon Ross 		mdb_printf(" %15s", "(bad af)");
346613a2f6bSGordon Ross 		break;
347613a2f6bSGordon Ross 	}
348613a2f6bSGordon Ross 
349613a2f6bSGordon Ross 	if (vcp->vc_username[0] != '\0')
350613a2f6bSGordon Ross 		mdb_printf("\t%s", vcp->vc_username);
351613a2f6bSGordon Ross 	else
352613a2f6bSGordon Ross 		mdb_printf("\t%s", "(?)");
353613a2f6bSGordon Ross 
354613a2f6bSGordon Ross 	if (vcp->vc_domain[0] != '\0')
355613a2f6bSGordon Ross 		mdb_printf("@%s", vcp->vc_domain);
356613a2f6bSGordon Ross 
357613a2f6bSGordon Ross 	mdb_printf("\t%s\n", vcstate_str(cbd, vcp->vc_state));
3584bff34e3Sthurlow 
3594bff34e3Sthurlow 	if (cbd->flags & OPT_RECURSE) {
3604bff34e3Sthurlow 		mdb_inc_indent(2);
3614bff34e3Sthurlow 		if (mdb_pwalk("nsmb_ss", smb_ss_cb, cbd, addr) < 0) {
3624bff34e3Sthurlow 			mdb_warn("failed to walk 'nsmb_ss'");
3634bff34e3Sthurlow 			/* Don't: return (WALK_ERR); */
3644bff34e3Sthurlow 		}
3654bff34e3Sthurlow 		mdb_dec_indent(2);
3664bff34e3Sthurlow 	}
3674bff34e3Sthurlow 
3684bff34e3Sthurlow 	return (WALK_NEXT);
3694bff34e3Sthurlow }
3704bff34e3Sthurlow 
3714bff34e3Sthurlow int
smb_vc_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3724bff34e3Sthurlow smb_vc_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3734bff34e3Sthurlow {
3744bff34e3Sthurlow 	smb_co_cbdata_t cbd;
3754bff34e3Sthurlow 	smb_vc_t *vcp;
3764bff34e3Sthurlow 	size_t vcsz;
3774bff34e3Sthurlow 
3784bff34e3Sthurlow 	memset(&cbd, 0, sizeof (cbd));
3794bff34e3Sthurlow 
3804bff34e3Sthurlow 	if (mdb_getopts(argc, argv,
3814bff34e3Sthurlow 	    'r', MDB_OPT_SETBITS, OPT_RECURSE, &cbd.flags,
3824bff34e3Sthurlow 	    'v', MDB_OPT_SETBITS, OPT_VERBOSE, &cbd.flags,
3834bff34e3Sthurlow 	    NULL) != argc) {
3844bff34e3Sthurlow 		return (DCMD_USAGE);
3854bff34e3Sthurlow 	}
3864bff34e3Sthurlow 
387613a2f6bSGordon Ross 	if (mdb_ctf_lookup_by_name("enum smbiod_state", &cbd.ctf_id) == -1) {
388613a2f6bSGordon Ross 		mdb_warn("Could not find enum smbiod_state");
389613a2f6bSGordon Ross 	}
390613a2f6bSGordon Ross 
3914bff34e3Sthurlow 	if (!(flags & DCMD_ADDRSPEC)) {
3924bff34e3Sthurlow 		if (mdb_walk("nsmb_vc", smb_vc_cb, &cbd) == -1) {
3934bff34e3Sthurlow 			mdb_warn("failed to walk 'nsmb_vc'");
3944bff34e3Sthurlow 			return (DCMD_ERR);
3954bff34e3Sthurlow 		}
3964bff34e3Sthurlow 		return (DCMD_OK);
3974bff34e3Sthurlow 	}
3984bff34e3Sthurlow 
3994bff34e3Sthurlow 	vcsz = sizeof (*vcp);
4004bff34e3Sthurlow 	vcp = mdb_alloc(vcsz, UM_SLEEP | UM_GC);
4014bff34e3Sthurlow 	if (mdb_vread(vcp, vcsz, addr) != vcsz) {
4024bff34e3Sthurlow 		mdb_warn("cannot read VC from %p", addr);
4034bff34e3Sthurlow 		return (DCMD_ERR);
4044bff34e3Sthurlow 	}
4054bff34e3Sthurlow 	smb_vc_cb(addr, vcp, &cbd);
4064bff34e3Sthurlow 
4074bff34e3Sthurlow 	return (DCMD_OK);
4084bff34e3Sthurlow }
4094bff34e3Sthurlow 
4104bff34e3Sthurlow void
smb_vc_help(void)4114bff34e3Sthurlow smb_vc_help(void)
4124bff34e3Sthurlow {
4134bff34e3Sthurlow 	mdb_printf("Options:\n"
4144bff34e3Sthurlow 	    "  -r           recursive display of share lists\n"
4154bff34e3Sthurlow 	    "  -v           be verbose when displaying smb_vc\n");
4164bff34e3Sthurlow }
4174bff34e3Sthurlow 
4184bff34e3Sthurlow /*
4194bff34e3Sthurlow  * Walker for the request list on a VC,
4204bff34e3Sthurlow  * and dcmd to show a summary.
4214bff34e3Sthurlow  */
4224bff34e3Sthurlow int
rqlist_walk_init(mdb_walk_state_t * wsp)4234bff34e3Sthurlow rqlist_walk_init(mdb_walk_state_t *wsp)
4244bff34e3Sthurlow {
4254bff34e3Sthurlow 	struct smb_rqhead rqh;
4264bff34e3Sthurlow 	uintptr_t addr;
4274bff34e3Sthurlow 
4284bff34e3Sthurlow 	/*
4294bff34e3Sthurlow 	 * Initial walk_addr is the address of the VC.
4304bff34e3Sthurlow 	 * Add offsetof(iod_rqlist) to get the rqhead.
4314bff34e3Sthurlow 	 */
4324bff34e3Sthurlow 	if (wsp->walk_addr == 0) {
4334bff34e3Sthurlow 		mdb_warn("::walk smb_ss does not support global walks\n");
4344bff34e3Sthurlow 		return (WALK_ERR);
4354bff34e3Sthurlow 	}
4364bff34e3Sthurlow 	addr = wsp->walk_addr;
4374bff34e3Sthurlow 	addr += OFFSETOF(smb_vc_t, iod_rqlist);
4384bff34e3Sthurlow 
4394bff34e3Sthurlow 	if (mdb_vread(&rqh, sizeof (rqh), addr) == -1) {
4404bff34e3Sthurlow 		mdb_warn("failed to read smb_rqhead at %p", addr);
4414bff34e3Sthurlow 		return (WALK_ERR);
4424bff34e3Sthurlow 	}
4434bff34e3Sthurlow 	wsp->walk_addr = (uintptr_t)rqh.tqh_first;
4444bff34e3Sthurlow 
4454bff34e3Sthurlow 	return (WALK_NEXT);
4464bff34e3Sthurlow }
4474bff34e3Sthurlow 
4484bff34e3Sthurlow int
rqlist_walk_step(mdb_walk_state_t * wsp)4494bff34e3Sthurlow rqlist_walk_step(mdb_walk_state_t *wsp)
4504bff34e3Sthurlow {
4514bff34e3Sthurlow 	smb_rq_t rq;
4524bff34e3Sthurlow 	int status;
4534bff34e3Sthurlow 
454892ad162SToomas Soome 	if (wsp->walk_addr == 0)
4554bff34e3Sthurlow 		return (WALK_DONE);
4564bff34e3Sthurlow 
4574bff34e3Sthurlow 	if (mdb_vread(&rq, sizeof (rq), wsp->walk_addr) == -1) {
4584bff34e3Sthurlow 		mdb_warn("cannot read smb_rq from %p", wsp->walk_addr);
4594bff34e3Sthurlow 		return (WALK_ERR);
4604bff34e3Sthurlow 	}
4614bff34e3Sthurlow 
4624bff34e3Sthurlow 	status = wsp->walk_callback(wsp->walk_addr, &rq,
4634bff34e3Sthurlow 	    wsp->walk_cbdata);
4644bff34e3Sthurlow 
4654bff34e3Sthurlow 	wsp->walk_addr = (uintptr_t)rq.sr_link.tqe_next;
4664bff34e3Sthurlow 
4674bff34e3Sthurlow 	return (status);
4684bff34e3Sthurlow }
4694bff34e3Sthurlow 
4704bff34e3Sthurlow typedef struct rqlist_cbdata {
4714bff34e3Sthurlow 	int printed_header;
472*adee6784SGordon Ross 	int vcflags;
4734bff34e3Sthurlow 	uintptr_t uid;		/* optional filtering by UID */
4744bff34e3Sthurlow } rqlist_cbdata_t;
4754bff34e3Sthurlow 
4764bff34e3Sthurlow int
rqlist_cb(uintptr_t addr,const void * data,void * arg)4774bff34e3Sthurlow rqlist_cb(uintptr_t addr, const void *data, void *arg)
4784bff34e3Sthurlow {
4794bff34e3Sthurlow 	const smb_rq_t *rq = data;
4804bff34e3Sthurlow 	rqlist_cbdata_t *cbd = arg;
4814bff34e3Sthurlow 
4824bff34e3Sthurlow 	if (cbd->printed_header == 0) {
4834bff34e3Sthurlow 		cbd->printed_header = 1;
4844bff34e3Sthurlow 		mdb_printf("// smb_rq_t MID cmd sr_state sr_flags\n");
4854bff34e3Sthurlow 	}
4864bff34e3Sthurlow 
4874bff34e3Sthurlow 	mdb_printf(" %-p", addr);	/* smb_rq_t */
488*adee6784SGordon Ross 	if ((cbd->vcflags & SMBV_SMB2) != 0) {
489*adee6784SGordon Ross 		mdb_printf(" x%04llx", (long long)rq->sr2_messageid);
490*adee6784SGordon Ross 		mdb_printf(" x%02x", rq->sr2_command);
491*adee6784SGordon Ross 	} else {
4924bff34e3Sthurlow 		mdb_printf(" x%04x", rq->sr_mid);
4934bff34e3Sthurlow 		mdb_printf(" x%02x", rq->sr_cmd);
494*adee6784SGordon Ross 	}
4954bff34e3Sthurlow 	mdb_printf(" %d", rq->sr_state);
4964bff34e3Sthurlow 	mdb_printf(" x%x", rq->sr_flags);
4974bff34e3Sthurlow 	mdb_printf("\n");
4984bff34e3Sthurlow 
4994bff34e3Sthurlow 	return (WALK_NEXT);
5004bff34e3Sthurlow }
5014bff34e3Sthurlow 
5024bff34e3Sthurlow /*ARGSUSED*/
5034bff34e3Sthurlow int
rqlist_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5044bff34e3Sthurlow rqlist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5054bff34e3Sthurlow {
5064bff34e3Sthurlow 	rqlist_cbdata_t cbd;
507*adee6784SGordon Ross 	smb_vc_t *vcp;
508*adee6784SGordon Ross 	size_t vcsz;
5094bff34e3Sthurlow 
5104bff34e3Sthurlow 	memset(&cbd, 0, sizeof (cbd));
5114bff34e3Sthurlow 
512*adee6784SGordon Ross 	/* Need the VC again to get  */
513*adee6784SGordon Ross 	vcsz = sizeof (*vcp);
514*adee6784SGordon Ross 	vcp = mdb_alloc(vcsz, UM_SLEEP | UM_GC);
515*adee6784SGordon Ross 	if (mdb_vread(vcp, vcsz, addr) != vcsz) {
516*adee6784SGordon Ross 		mdb_warn("cannot read VC from %p", addr);
517*adee6784SGordon Ross 		return (DCMD_ERR);
518*adee6784SGordon Ross 	}
519*adee6784SGordon Ross 	cbd.vcflags = vcp->vc_flags;
520*adee6784SGordon Ross 
5214bff34e3Sthurlow 	/*
5224bff34e3Sthurlow 	 * Initial walk_addr is address of parent (VC)
5234bff34e3Sthurlow 	 */
5244bff34e3Sthurlow 	if (!(flags & DCMD_ADDRSPEC)) {
5254bff34e3Sthurlow 		mdb_warn("address required\n");
5264bff34e3Sthurlow 		return (DCMD_ERR);
5274bff34e3Sthurlow 	}
5284bff34e3Sthurlow 
5294bff34e3Sthurlow 	if (mdb_pwalk("nsmb_rqlist", rqlist_cb, &cbd, addr) == -1) {
5304bff34e3Sthurlow 		mdb_warn("failed to walk 'nsmb_rqlist'");
5314bff34e3Sthurlow 		return (DCMD_ERR);
5324bff34e3Sthurlow 	}
5334bff34e3Sthurlow 
5344bff34e3Sthurlow 	return (DCMD_OK);
5354bff34e3Sthurlow }
5364bff34e3Sthurlow 
5374bff34e3Sthurlow 
5384bff34e3Sthurlow /*
5394bff34e3Sthurlow  * AVL walker for the passwords AVL tree,
5404bff34e3Sthurlow  * and dcmd to show a summary.
5414bff34e3Sthurlow  */
5424bff34e3Sthurlow static int
pwtree_walk_init(mdb_walk_state_t * wsp)5434bff34e3Sthurlow pwtree_walk_init(mdb_walk_state_t *wsp)
5444bff34e3Sthurlow {
5454bff34e3Sthurlow 	GElf_Sym sym;
5464bff34e3Sthurlow 
547892ad162SToomas Soome 	if (wsp->walk_addr != 0) {
5484bff34e3Sthurlow 		mdb_warn("pwtree walk only supports global walks\n");
5494bff34e3Sthurlow 		return (WALK_ERR);
5504bff34e3Sthurlow 	}
5514bff34e3Sthurlow 
5528329232eSGordon Ross 	if (mdb_lookup_by_obj(NSMB_OBJNAME, "smb_ptd", &sym) == -1) {
5534bff34e3Sthurlow 		mdb_warn("failed to find symbol 'smb_ptd'");
5544bff34e3Sthurlow 		return (WALK_ERR);
5554bff34e3Sthurlow 	}
5564bff34e3Sthurlow 
5574bff34e3Sthurlow 	wsp->walk_addr = (uintptr_t)sym.st_value;
5584bff34e3Sthurlow 
5594bff34e3Sthurlow 	if (mdb_layered_walk("avl", wsp) == -1) {
5604bff34e3Sthurlow 		mdb_warn("failed to walk 'avl'\n");
5614bff34e3Sthurlow 		return (WALK_ERR);
5624bff34e3Sthurlow 	}
5634bff34e3Sthurlow 
5644bff34e3Sthurlow 	return (WALK_NEXT);
5654bff34e3Sthurlow }
5664bff34e3Sthurlow 
5674bff34e3Sthurlow static int
pwtree_walk_step(mdb_walk_state_t * wsp)5684bff34e3Sthurlow pwtree_walk_step(mdb_walk_state_t *wsp)
5694bff34e3Sthurlow {
5704bff34e3Sthurlow 	smb_passid_t	ptnode;
5714bff34e3Sthurlow 
5724bff34e3Sthurlow 	if (mdb_vread(&ptnode, sizeof (ptnode), wsp->walk_addr) == -1) {
5734bff34e3Sthurlow 		mdb_warn("failed to read smb_passid_t at %p", wsp->walk_addr);
5744bff34e3Sthurlow 		return (WALK_ERR);
5754bff34e3Sthurlow 	}
5764bff34e3Sthurlow 
5774bff34e3Sthurlow 	return (wsp->walk_callback(wsp->walk_addr, &ptnode, wsp->walk_cbdata));
5784bff34e3Sthurlow }
5794bff34e3Sthurlow 
5804bff34e3Sthurlow typedef struct pwtree_cbdata {
5814bff34e3Sthurlow 	int printed_header;
5824bff34e3Sthurlow 	uid_t uid;		/* optional filtering by UID */
5834bff34e3Sthurlow } pwtree_cbdata_t;
5844bff34e3Sthurlow 
5854bff34e3Sthurlow int
pwtree_cb(uintptr_t addr,const void * data,void * arg)5864bff34e3Sthurlow pwtree_cb(uintptr_t addr, const void *data, void *arg)
5874bff34e3Sthurlow {
5884bff34e3Sthurlow 	const smb_passid_t *ptn = data;
5894bff34e3Sthurlow 	pwtree_cbdata_t *cbd = arg;
5904bff34e3Sthurlow 
5914bff34e3Sthurlow 	/* Optional filtering by UID. */
5924bff34e3Sthurlow 	if (cbd->uid != (uid_t)-1 && cbd->uid != ptn->uid) {
5934bff34e3Sthurlow 		return (WALK_NEXT);
5944bff34e3Sthurlow 	}
5954bff34e3Sthurlow 
5964bff34e3Sthurlow 	if (cbd->printed_header == 0) {
5974bff34e3Sthurlow 		cbd->printed_header = 1;
5984bff34e3Sthurlow 		mdb_printf("// smb_passid_t UID domain user\n");
5994bff34e3Sthurlow 	}
6004bff34e3Sthurlow 
6014bff34e3Sthurlow 	mdb_printf(" %-p", addr);	/* smb_passid_t */
6024bff34e3Sthurlow 	mdb_printf(" %d", (uintptr_t)ptn->uid);
6034bff34e3Sthurlow 	print_str((uintptr_t)ptn->srvdom);
6044bff34e3Sthurlow 	print_str((uintptr_t)ptn->username);
6054bff34e3Sthurlow 	mdb_printf("\n");
6064bff34e3Sthurlow 
6074bff34e3Sthurlow 	return (WALK_NEXT);
6084bff34e3Sthurlow }
6094bff34e3Sthurlow 
6104bff34e3Sthurlow /*ARGSUSED*/
6114bff34e3Sthurlow int
pwtree_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)6124bff34e3Sthurlow pwtree_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
6134bff34e3Sthurlow {
6144bff34e3Sthurlow 	pwtree_cbdata_t cbd;
6154bff34e3Sthurlow 	char *uid_str = NULL;
6164bff34e3Sthurlow 	char buf[32];
6174bff34e3Sthurlow 
6184bff34e3Sthurlow 	memset(&cbd, 0, sizeof (cbd));
6194bff34e3Sthurlow 
6204bff34e3Sthurlow 	if (mdb_getopts(argc, argv,
6214bff34e3Sthurlow 	    'u', MDB_OPT_STR, &uid_str, NULL) != argc) {
6224bff34e3Sthurlow 		return (DCMD_USAGE);
6234bff34e3Sthurlow 	}
6244bff34e3Sthurlow 	if (uid_str) {
6254bff34e3Sthurlow 		/*
6264bff34e3Sthurlow 		 * Want the the default radix to be 10 here.
6274bff34e3Sthurlow 		 * If the string has some kind of radix prefix,
6284bff34e3Sthurlow 		 * just use that as-is, otherwise prepend "0t".
6294bff34e3Sthurlow 		 * Cheating on the "not a digit" test, but
6304bff34e3Sthurlow 		 * mdb_strtoull will do a real syntax check.
6314bff34e3Sthurlow 		 */
6324bff34e3Sthurlow 		if (uid_str[0] == '0' && uid_str[1] > '9') {
6334bff34e3Sthurlow 			cbd.uid = (uid_t)mdb_strtoull(uid_str);
6344bff34e3Sthurlow 		} else {
6354bff34e3Sthurlow 			strcpy(buf, "0t");
6364bff34e3Sthurlow 			strlcat(buf, uid_str, sizeof (buf));
6374bff34e3Sthurlow 			cbd.uid = (uid_t)mdb_strtoull(buf);
6384bff34e3Sthurlow 		}
6394bff34e3Sthurlow 	} else
6404bff34e3Sthurlow 		cbd.uid = (uid_t)-1;
6414bff34e3Sthurlow 
6424bff34e3Sthurlow 	if (flags & DCMD_ADDRSPEC) {
6434bff34e3Sthurlow 		mdb_warn("address not allowed\n");
6444bff34e3Sthurlow 		return (DCMD_ERR);
6454bff34e3Sthurlow 	}
6464bff34e3Sthurlow 
6474bff34e3Sthurlow 	if (mdb_pwalk("nsmb_pwtree", pwtree_cb, &cbd, 0) == -1) {
6484bff34e3Sthurlow 		mdb_warn("failed to walk 'nsmb_pwtree'");
6494bff34e3Sthurlow 		return (DCMD_ERR);
6504bff34e3Sthurlow 	}
6514bff34e3Sthurlow 
6524bff34e3Sthurlow 	return (DCMD_OK);
6534bff34e3Sthurlow }
6544bff34e3Sthurlow 
6554bff34e3Sthurlow void
pwtree_help(void)6564bff34e3Sthurlow pwtree_help(void)
6574bff34e3Sthurlow {
6584bff34e3Sthurlow 	mdb_printf("Options:\n"
6594bff34e3Sthurlow 	    "  -u uid       show only entries belonging to uid (decimal)\n");
6604bff34e3Sthurlow }
6614bff34e3Sthurlow 
6624bff34e3Sthurlow 
6634bff34e3Sthurlow static const mdb_dcmd_t dcmds[] = {
6644bff34e3Sthurlow 	{ "nsmb_vc", "?[-rv]",
6654bff34e3Sthurlow 		"show smb_vc (or list)",
6664bff34e3Sthurlow 		smb_vc_dcmd, smb_vc_help },
6674bff34e3Sthurlow 	{ "nsmb_rqlist", ":",
6684bff34e3Sthurlow 		"show smb_rq list on a VC",
6694bff34e3Sthurlow 		rqlist_dcmd, NULL },
6704bff34e3Sthurlow 	{ "nsmb_pwtree", "?[-u uid]",
6714bff34e3Sthurlow 		"list smb_passid_t (password tree)",
6724bff34e3Sthurlow 		pwtree_dcmd, pwtree_help },
6734bff34e3Sthurlow 	{NULL}
6744bff34e3Sthurlow };
6754bff34e3Sthurlow 
6764bff34e3Sthurlow static const mdb_walker_t walkers[] = {
6774bff34e3Sthurlow 	{ "nsmb_vc", "walk nsmb VC list",
6784bff34e3Sthurlow 		smb_vc_walk_init, smb_co_walk_step, NULL },
6794bff34e3Sthurlow 	{ "nsmb_ss", "walk nsmb share list for some VC",
6804bff34e3Sthurlow 		smb_ss_walk_init, smb_co_walk_step, NULL },
681*adee6784SGordon Ross 	{ "nsmb_fh", "walk nsmb share list for some VC",
682*adee6784SGordon Ross 		smb_fh_walk_init, smb_co_walk_step, NULL },
6834bff34e3Sthurlow 	{ "nsmb_rqlist", "walk request list for some VC",
6844bff34e3Sthurlow 		rqlist_walk_init, rqlist_walk_step, NULL },
6854bff34e3Sthurlow 	{ "nsmb_pwtree", "walk passord AVL tree",
6864bff34e3Sthurlow 		pwtree_walk_init, pwtree_walk_step, NULL },
6874bff34e3Sthurlow 	{NULL}
6884bff34e3Sthurlow };
6894bff34e3Sthurlow 
6904bff34e3Sthurlow static const mdb_modinfo_t modinfo = {
6914bff34e3Sthurlow 	MDB_API_VERSION,
6924bff34e3Sthurlow 	dcmds,
6934bff34e3Sthurlow 	walkers
6944bff34e3Sthurlow };
6954bff34e3Sthurlow 
6964bff34e3Sthurlow const mdb_modinfo_t *
_mdb_init(void)6974bff34e3Sthurlow _mdb_init(void)
6984bff34e3Sthurlow {
6994bff34e3Sthurlow 	return (&modinfo);
7004bff34e3Sthurlow }
701