xref: /onnv-gate/usr/src/cmd/mdb/common/modules/nsmb/nsmb.c (revision 10023:71bf38dba3d6)
16007Sthurlow /*
26007Sthurlow  * CDDL HEADER START
36007Sthurlow  *
46007Sthurlow  * The contents of this file are subject to the terms of the
56007Sthurlow  * Common Development and Distribution License (the "License").
66007Sthurlow  * You may not use this file except in compliance with the License.
76007Sthurlow  *
86007Sthurlow  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96007Sthurlow  * or http://www.opensolaris.org/os/licensing.
106007Sthurlow  * See the License for the specific language governing permissions
116007Sthurlow  * and limitations under the License.
126007Sthurlow  *
136007Sthurlow  * When distributing Covered Code, include this CDDL HEADER in each
146007Sthurlow  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156007Sthurlow  * If applicable, add the following below this CDDL HEADER, with the
166007Sthurlow  * fields enclosed by brackets "[]" replaced with your own identifying
176007Sthurlow  * information: Portions Copyright [yyyy] [name of copyright owner]
186007Sthurlow  *
196007Sthurlow  * CDDL HEADER END
206007Sthurlow  */
216007Sthurlow 
226007Sthurlow /*
23*10023SGordon.Ross@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
246007Sthurlow  * Use is subject to license terms.
256007Sthurlow  */
266007Sthurlow 
276007Sthurlow 
286007Sthurlow #include <sys/mdb_modapi.h>
29*10023SGordon.Ross@Sun.COM #include <mdb/mdb_ctf.h>
306007Sthurlow #include <sys/types.h>
31*10023SGordon.Ross@Sun.COM #include <sys/socket.h>
326007Sthurlow 
336007Sthurlow #include "smb_conn.h"
346007Sthurlow #include "smb_rq.h"
356007Sthurlow #include "smb_pass.h"
366007Sthurlow 
376007Sthurlow #define	OPT_VERBOSE	0x0001	/* Be [-v]erbose in dcmd's */
386007Sthurlow #define	OPT_RECURSE	0x0002	/* recursive display */
396007Sthurlow 
406007Sthurlow /*
416007Sthurlow  * We need to read in a private copy
426007Sthurlow  * of every string we want to print out.
436007Sthurlow  */
446007Sthurlow void
print_str(uintptr_t addr)456007Sthurlow print_str(uintptr_t addr)
466007Sthurlow {
476007Sthurlow 	char buf[32];
486007Sthurlow 	int len, mx = sizeof (buf) - 4;
496007Sthurlow 
506007Sthurlow 	if ((len = mdb_readstr(buf, sizeof (buf), addr)) <= 0) {
516007Sthurlow 		mdb_printf(" (%p)", addr);
526007Sthurlow 	} else {
536007Sthurlow 		if (len > mx)
546007Sthurlow 			strcpy(&buf[mx], "...");
556007Sthurlow 		mdb_printf(" %s", buf);
566007Sthurlow 	}
576007Sthurlow }
586007Sthurlow 
596007Sthurlow 
606007Sthurlow /*
616007Sthurlow  * Walker for smb_connobj_t structures, including
626007Sthurlow  * smb_vc_t and smb_share_t which "inherit" from it.
636007Sthurlow  * Tricky: Exploit the "inheritance" of smb_connobj_t
646007Sthurlow  * with common functions for walk_init, walk_next.
656007Sthurlow  */
666007Sthurlow typedef struct smb_co_walk_data {
676007Sthurlow 	uintptr_t	pp;
686007Sthurlow 	int level;		/* SMBL_SM, SMBL_VC, SMBL_SHARE  */
696007Sthurlow 	int size;		/* sizeof (union member) */
706007Sthurlow 	union co_u {
716007Sthurlow 		smb_connobj_t	co;	/* copy of the list element */
726007Sthurlow 		smb_vc_t	vc;
736007Sthurlow 		smb_share_t	ss;
746007Sthurlow 	} u;
756007Sthurlow } smb_co_walk_data_t;
766007Sthurlow 
776007Sthurlow /*
786007Sthurlow  * Common walk_init for walking structs inherited
796007Sthurlow  * from smb_connobj_t (smb_vc_t, smb_share_t)
806007Sthurlow  */
816007Sthurlow int
smb_co_walk_init(mdb_walk_state_t * wsp,int level)826007Sthurlow smb_co_walk_init(mdb_walk_state_t *wsp, int level)
836007Sthurlow {
846007Sthurlow 	smb_co_walk_data_t *smbw;
856007Sthurlow 	size_t psz;
866007Sthurlow 
876007Sthurlow 	if (wsp->walk_addr == NULL)
886007Sthurlow 		return (WALK_ERR);
896007Sthurlow 
906007Sthurlow 	smbw = mdb_alloc(sizeof (*smbw), UM_SLEEP | UM_GC);
916007Sthurlow 	wsp->walk_data = smbw;
926007Sthurlow 
936007Sthurlow 	/*
946007Sthurlow 	 * Save the parent pointer for later checks, and
956007Sthurlow 	 * the level so we know which union member it is.
966007Sthurlow 	 * Also the size of this union member.
976007Sthurlow 	 */
986007Sthurlow 	smbw->pp = wsp->walk_addr;
996007Sthurlow 	smbw->level = level;
1006007Sthurlow 	switch (level) {
1016007Sthurlow 	case SMBL_SM:
1026007Sthurlow 		smbw->size = sizeof (smbw->u.co);
1036007Sthurlow 		break;
1046007Sthurlow 	case SMBL_VC:
1056007Sthurlow 		smbw->size = sizeof (smbw->u.vc);
1066007Sthurlow 		break;
1076007Sthurlow 	case SMBL_SHARE:
1086007Sthurlow 		smbw->size = sizeof (smbw->u.ss);
1096007Sthurlow 		break;
1106007Sthurlow 	default:
1116007Sthurlow 		smbw->size = sizeof (smbw->u);
1126007Sthurlow 		break;
1136007Sthurlow 	}
1146007Sthurlow 
1156007Sthurlow 	/*
1166007Sthurlow 	 * Read in the parent object.  Just need the
1176007Sthurlow 	 * invariant part (smb_connobj_t) so we can
1186007Sthurlow 	 * get the list of children below it.
1196007Sthurlow 	 */
1206007Sthurlow 	psz = sizeof (smbw->u.co);
1216007Sthurlow 	if (mdb_vread(&smbw->u.co, psz, smbw->pp) != psz) {
1226007Sthurlow 		mdb_warn("cannot read connobj from %p", smbw->pp);
1236007Sthurlow 		return (WALK_ERR);
1246007Sthurlow 	}
1256007Sthurlow 
1266007Sthurlow 	/*
1276007Sthurlow 	 * Finally, setup to walk the list of children.
1286007Sthurlow 	 */
1296007Sthurlow 	wsp->walk_addr = (uintptr_t)smbw->u.co.co_children.slh_first;
1306007Sthurlow 
1316007Sthurlow 	return (WALK_NEXT);
1326007Sthurlow }
1336007Sthurlow 
1346007Sthurlow /*
1356007Sthurlow  * Walk the (global) VC list.
1366007Sthurlow  */
1376007Sthurlow int
smb_vc_walk_init(mdb_walk_state_t * wsp)1386007Sthurlow smb_vc_walk_init(mdb_walk_state_t *wsp)
1396007Sthurlow {
1406007Sthurlow 	GElf_Sym sym;
1416007Sthurlow 
1426007Sthurlow 	if (wsp->walk_addr != NULL) {
1436007Sthurlow 		mdb_warn("::walk smb_vc only supports global walks\n");
1446007Sthurlow 		return (WALK_ERR);
1456007Sthurlow 	}
1466007Sthurlow 
1476007Sthurlow 	/* Locate the VC list head. */
1486007Sthurlow 	if (mdb_lookup_by_obj("nsmb", "smb_vclist", &sym)) {
1496007Sthurlow 		mdb_warn("failed to lookup `smb_vclist'\n");
1506007Sthurlow 		return (WALK_ERR);
1516007Sthurlow 	}
1526007Sthurlow 	wsp->walk_addr = sym.st_value;
1536007Sthurlow 
1546007Sthurlow 	return (smb_co_walk_init(wsp, SMBL_VC));
1556007Sthurlow }
1566007Sthurlow 
1576007Sthurlow /*
1586007Sthurlow  * Walk the share list below some VC.
1596007Sthurlow  */
1606007Sthurlow int
smb_ss_walk_init(mdb_walk_state_t * wsp)1616007Sthurlow smb_ss_walk_init(mdb_walk_state_t *wsp)
1626007Sthurlow {
1636007Sthurlow 
1646007Sthurlow 	/*
1656007Sthurlow 	 * Initial walk_addr is address of parent (VC)
1666007Sthurlow 	 */
1676007Sthurlow 	if (wsp->walk_addr == 0) {
1686007Sthurlow 		mdb_warn("::walk smb_ss does not support global walks\n");
1696007Sthurlow 		return (WALK_ERR);
1706007Sthurlow 	}
1716007Sthurlow 
1726007Sthurlow 	return (smb_co_walk_init(wsp, SMBL_SHARE));
1736007Sthurlow }
1746007Sthurlow 
1756007Sthurlow /*
1766007Sthurlow  * Common walk_step for walking structs inherited
1776007Sthurlow  * from smb_connobj_t (smb_vc_t, smb_share_t)
1786007Sthurlow  */
1796007Sthurlow int
smb_co_walk_step(mdb_walk_state_t * wsp)1806007Sthurlow smb_co_walk_step(mdb_walk_state_t *wsp)
1816007Sthurlow {
1826007Sthurlow 	smb_co_walk_data_t *smbw = wsp->walk_data;
1836007Sthurlow 	int status;
1846007Sthurlow 
1856007Sthurlow 	if (wsp->walk_addr == NULL)
1866007Sthurlow 		return (WALK_DONE);
1876007Sthurlow 
1886007Sthurlow 	if (mdb_vread(&smbw->u, smbw->size, wsp->walk_addr)
1896007Sthurlow 	    != smbw->size) {
1906007Sthurlow 		mdb_warn("cannot read connobj from %p", wsp->walk_addr);
1916007Sthurlow 		return (WALK_ERR);
1926007Sthurlow 	}
1936007Sthurlow 
1946007Sthurlow 	/* XXX: Sanity check level? parent pointer? */
1956007Sthurlow 
1966007Sthurlow 	status = wsp->walk_callback(wsp->walk_addr, &smbw->u,
1976007Sthurlow 	    wsp->walk_cbdata);
1986007Sthurlow 
1996007Sthurlow 	wsp->walk_addr = (uintptr_t)smbw->u.co.co_next.sle_next;
2006007Sthurlow 
2016007Sthurlow 	return (status);
2026007Sthurlow }
2036007Sthurlow 
2046007Sthurlow 
2056007Sthurlow /*
2066007Sthurlow  * Dcmd (and callback function) to print a summary of
2076007Sthurlow  * all VCs, and optionally all shares under each VC.
2086007Sthurlow  */
2096007Sthurlow 
2106007Sthurlow typedef struct smb_co_cbdata {
2116007Sthurlow 	int flags;		/* OPT_...  */
2126007Sthurlow 	int printed_header;
213*10023SGordon.Ross@Sun.COM 	mdb_ctf_id_t ctf_id;
2146007Sthurlow } smb_co_cbdata_t;
2156007Sthurlow 
2166007Sthurlow /*
2176007Sthurlow  * Call-back function for walking a share list.
2186007Sthurlow  */
2196007Sthurlow int
smb_ss_cb(uintptr_t addr,const void * data,void * arg)2206007Sthurlow smb_ss_cb(uintptr_t addr, const void *data, void *arg)
2216007Sthurlow {
2226007Sthurlow 	const smb_share_t *ssp = data;
2236007Sthurlow 	smb_co_cbdata_t *cbd = arg;
2246007Sthurlow 
225*10023SGordon.Ross@Sun.COM 	mdb_printf(" %-p\t%s\n", addr, ssp->ss_name);
2266007Sthurlow 
2276007Sthurlow 	if (cbd->flags & OPT_VERBOSE) {
2286007Sthurlow 		mdb_inc_indent(2);
2296007Sthurlow 		/* Anything wanted here? */
2306007Sthurlow 		mdb_dec_indent(2);
2316007Sthurlow 	}
2326007Sthurlow 
2336007Sthurlow 	return (WALK_NEXT);
2346007Sthurlow }
2356007Sthurlow 
236*10023SGordon.Ross@Sun.COM static const char *
vcstate_str(smb_co_cbdata_t * cbd,int stval)237*10023SGordon.Ross@Sun.COM vcstate_str(smb_co_cbdata_t *cbd, int stval)
238*10023SGordon.Ross@Sun.COM {
239*10023SGordon.Ross@Sun.COM 	static const char prefix[] = "SMBIOD_ST_";
240*10023SGordon.Ross@Sun.COM 	int prefix_len = sizeof (prefix) - 1;
241*10023SGordon.Ross@Sun.COM 	mdb_ctf_id_t vcst_enum;
242*10023SGordon.Ross@Sun.COM 	const char *cp;
243*10023SGordon.Ross@Sun.COM 
244*10023SGordon.Ross@Sun.COM 	/* Got this in smb_vc_dcmd. */
245*10023SGordon.Ross@Sun.COM 	vcst_enum = cbd->ctf_id;
246*10023SGordon.Ross@Sun.COM 
247*10023SGordon.Ross@Sun.COM 	/* Get the name for the enum value. */
248*10023SGordon.Ross@Sun.COM 	if ((cp = mdb_ctf_enum_name(vcst_enum, stval)) == NULL)
249*10023SGordon.Ross@Sun.COM 		return ("?");
250*10023SGordon.Ross@Sun.COM 
251*10023SGordon.Ross@Sun.COM 	/* Skip the prefix part. */
252*10023SGordon.Ross@Sun.COM 	if (strncmp(cp, prefix, prefix_len) == 0)
253*10023SGordon.Ross@Sun.COM 		cp += prefix_len;
254*10023SGordon.Ross@Sun.COM 
255*10023SGordon.Ross@Sun.COM 	return (cp);
256*10023SGordon.Ross@Sun.COM }
257*10023SGordon.Ross@Sun.COM 
2586007Sthurlow /*
2596007Sthurlow  * Call-back function for walking the VC list.
2606007Sthurlow  */
2616007Sthurlow int
smb_vc_cb(uintptr_t addr,const void * data,void * arg)2626007Sthurlow smb_vc_cb(uintptr_t addr, const void *data, void *arg)
2636007Sthurlow {
2646007Sthurlow 	const smb_vc_t *vcp = data;
2656007Sthurlow 	smb_co_cbdata_t *cbd = arg;
2666007Sthurlow 
2676007Sthurlow 	if (cbd->printed_header == 0) {
2686007Sthurlow 		cbd->printed_header = 1;
269*10023SGordon.Ross@Sun.COM 		mdb_printf("// smb_vc_t  uid  server  \tuser\t\tstate\n");
2706007Sthurlow 	}
2716007Sthurlow 
2726007Sthurlow 	mdb_printf("%-p", addr);
273*10023SGordon.Ross@Sun.COM 	mdb_printf(" %7d", vcp->vc_owner);
274*10023SGordon.Ross@Sun.COM 
275*10023SGordon.Ross@Sun.COM 	switch (vcp->vc_srvaddr.sa.sa_family) {
276*10023SGordon.Ross@Sun.COM 	case AF_INET:
277*10023SGordon.Ross@Sun.COM 		mdb_printf(" %I", vcp->vc_srvaddr.sin.sin_addr);
278*10023SGordon.Ross@Sun.COM 		break;
279*10023SGordon.Ross@Sun.COM 	case AF_INET6:
280*10023SGordon.Ross@Sun.COM 		mdb_printf(" %N", &vcp->vc_srvaddr.sin6.sin6_addr);
281*10023SGordon.Ross@Sun.COM 		break;
282*10023SGordon.Ross@Sun.COM 	default:
283*10023SGordon.Ross@Sun.COM 		mdb_printf(" %15s", "(bad af)");
284*10023SGordon.Ross@Sun.COM 		break;
285*10023SGordon.Ross@Sun.COM 	}
286*10023SGordon.Ross@Sun.COM 
287*10023SGordon.Ross@Sun.COM 	if (vcp->vc_username[0] != '\0')
288*10023SGordon.Ross@Sun.COM 		mdb_printf("\t%s", vcp->vc_username);
289*10023SGordon.Ross@Sun.COM 	else
290*10023SGordon.Ross@Sun.COM 		mdb_printf("\t%s", "(?)");
291*10023SGordon.Ross@Sun.COM 
292*10023SGordon.Ross@Sun.COM 	if (vcp->vc_domain[0] != '\0')
293*10023SGordon.Ross@Sun.COM 		mdb_printf("@%s", vcp->vc_domain);
294*10023SGordon.Ross@Sun.COM 
295*10023SGordon.Ross@Sun.COM 	mdb_printf("\t%s\n", vcstate_str(cbd, vcp->vc_state));
2966007Sthurlow 
2976007Sthurlow 	if (cbd->flags & OPT_RECURSE) {
2986007Sthurlow 		mdb_inc_indent(2);
2996007Sthurlow 		if (mdb_pwalk("nsmb_ss", smb_ss_cb, cbd, addr) < 0) {
3006007Sthurlow 			mdb_warn("failed to walk 'nsmb_ss'");
3016007Sthurlow 			/* Don't: return (WALK_ERR); */
3026007Sthurlow 		}
3036007Sthurlow 		mdb_dec_indent(2);
3046007Sthurlow 	}
3056007Sthurlow 
3066007Sthurlow 	return (WALK_NEXT);
3076007Sthurlow }
3086007Sthurlow 
3096007Sthurlow int
smb_vc_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3106007Sthurlow smb_vc_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3116007Sthurlow {
3126007Sthurlow 	smb_co_cbdata_t cbd;
3136007Sthurlow 	smb_vc_t *vcp;
3146007Sthurlow 	size_t vcsz;
3156007Sthurlow 
3166007Sthurlow 	memset(&cbd, 0, sizeof (cbd));
3176007Sthurlow 
3186007Sthurlow 	if (mdb_getopts(argc, argv,
3196007Sthurlow 	    'r', MDB_OPT_SETBITS, OPT_RECURSE, &cbd.flags,
3206007Sthurlow 	    'v', MDB_OPT_SETBITS, OPT_VERBOSE, &cbd.flags,
3216007Sthurlow 	    NULL) != argc) {
3226007Sthurlow 		return (DCMD_USAGE);
3236007Sthurlow 	}
3246007Sthurlow 
325*10023SGordon.Ross@Sun.COM 	if (mdb_ctf_lookup_by_name("enum smbiod_state", &cbd.ctf_id) == -1) {
326*10023SGordon.Ross@Sun.COM 		mdb_warn("Could not find enum smbiod_state");
327*10023SGordon.Ross@Sun.COM 	}
328*10023SGordon.Ross@Sun.COM 
3296007Sthurlow 	if (!(flags & DCMD_ADDRSPEC)) {
3306007Sthurlow 		if (mdb_walk("nsmb_vc", smb_vc_cb, &cbd) == -1) {
3316007Sthurlow 			mdb_warn("failed to walk 'nsmb_vc'");
3326007Sthurlow 			return (DCMD_ERR);
3336007Sthurlow 		}
3346007Sthurlow 		return (DCMD_OK);
3356007Sthurlow 	}
3366007Sthurlow 
3376007Sthurlow 	vcsz = sizeof (*vcp);
3386007Sthurlow 	vcp = mdb_alloc(vcsz, UM_SLEEP | UM_GC);
3396007Sthurlow 	if (mdb_vread(vcp, vcsz, addr) != vcsz) {
3406007Sthurlow 		mdb_warn("cannot read VC from %p", addr);
3416007Sthurlow 		return (DCMD_ERR);
3426007Sthurlow 	}
3436007Sthurlow 	smb_vc_cb(addr, vcp, &cbd);
3446007Sthurlow 
3456007Sthurlow 	return (DCMD_OK);
3466007Sthurlow }
3476007Sthurlow 
3486007Sthurlow void
smb_vc_help(void)3496007Sthurlow smb_vc_help(void)
3506007Sthurlow {
3516007Sthurlow 	mdb_printf("Options:\n"
3526007Sthurlow 	    "  -r           recursive display of share lists\n"
3536007Sthurlow 	    "  -v           be verbose when displaying smb_vc\n");
3546007Sthurlow }
3556007Sthurlow 
3566007Sthurlow /*
3576007Sthurlow  * Walker for the request list on a VC,
3586007Sthurlow  * and dcmd to show a summary.
3596007Sthurlow  */
3606007Sthurlow int
rqlist_walk_init(mdb_walk_state_t * wsp)3616007Sthurlow rqlist_walk_init(mdb_walk_state_t *wsp)
3626007Sthurlow {
3636007Sthurlow 	struct smb_rqhead rqh;
3646007Sthurlow 	uintptr_t addr;
3656007Sthurlow 
3666007Sthurlow 	/*
3676007Sthurlow 	 * Initial walk_addr is the address of the VC.
3686007Sthurlow 	 * Add offsetof(iod_rqlist) to get the rqhead.
3696007Sthurlow 	 */
3706007Sthurlow 	if (wsp->walk_addr == 0) {
3716007Sthurlow 		mdb_warn("::walk smb_ss does not support global walks\n");
3726007Sthurlow 		return (WALK_ERR);
3736007Sthurlow 	}
3746007Sthurlow 	addr = wsp->walk_addr;
3756007Sthurlow 	addr += OFFSETOF(smb_vc_t, iod_rqlist);
3766007Sthurlow 
3776007Sthurlow 	if (mdb_vread(&rqh, sizeof (rqh), addr) == -1) {
3786007Sthurlow 		mdb_warn("failed to read smb_rqhead at %p", addr);
3796007Sthurlow 		return (WALK_ERR);
3806007Sthurlow 	}
3816007Sthurlow 	wsp->walk_addr = (uintptr_t)rqh.tqh_first;
3826007Sthurlow 
3836007Sthurlow 	return (WALK_NEXT);
3846007Sthurlow }
3856007Sthurlow 
3866007Sthurlow int
rqlist_walk_step(mdb_walk_state_t * wsp)3876007Sthurlow rqlist_walk_step(mdb_walk_state_t *wsp)
3886007Sthurlow {
3896007Sthurlow 	smb_rq_t rq;
3906007Sthurlow 	int status;
3916007Sthurlow 
3926007Sthurlow 	if (wsp->walk_addr == NULL)
3936007Sthurlow 		return (WALK_DONE);
3946007Sthurlow 
3956007Sthurlow 	if (mdb_vread(&rq, sizeof (rq), wsp->walk_addr) == -1) {
3966007Sthurlow 		mdb_warn("cannot read smb_rq from %p", wsp->walk_addr);
3976007Sthurlow 		return (WALK_ERR);
3986007Sthurlow 	}
3996007Sthurlow 
4006007Sthurlow 	status = wsp->walk_callback(wsp->walk_addr, &rq,
4016007Sthurlow 	    wsp->walk_cbdata);
4026007Sthurlow 
4036007Sthurlow 	wsp->walk_addr = (uintptr_t)rq.sr_link.tqe_next;
4046007Sthurlow 
4056007Sthurlow 	return (status);
4066007Sthurlow }
4076007Sthurlow 
4086007Sthurlow typedef struct rqlist_cbdata {
4096007Sthurlow 	int printed_header;
4106007Sthurlow 	uintptr_t uid;		/* optional filtering by UID */
4116007Sthurlow } rqlist_cbdata_t;
4126007Sthurlow 
4136007Sthurlow int
rqlist_cb(uintptr_t addr,const void * data,void * arg)4146007Sthurlow rqlist_cb(uintptr_t addr, const void *data, void *arg)
4156007Sthurlow {
4166007Sthurlow 	const smb_rq_t *rq = data;
4176007Sthurlow 	rqlist_cbdata_t *cbd = arg;
4186007Sthurlow 
4196007Sthurlow 	if (cbd->printed_header == 0) {
4206007Sthurlow 		cbd->printed_header = 1;
4216007Sthurlow 		mdb_printf("// smb_rq_t MID cmd sr_state sr_flags\n");
4226007Sthurlow 	}
4236007Sthurlow 
4246007Sthurlow 	mdb_printf(" %-p", addr);	/* smb_rq_t */
4256007Sthurlow 	mdb_printf(" x%04x", rq->sr_mid);
4266007Sthurlow 	mdb_printf(" x%02x", rq->sr_cmd);
4276007Sthurlow 	mdb_printf(" %d", rq->sr_state);
4286007Sthurlow 	mdb_printf(" x%x", rq->sr_flags);
4296007Sthurlow 	mdb_printf("\n");
4306007Sthurlow 
4316007Sthurlow 	return (WALK_NEXT);
4326007Sthurlow }
4336007Sthurlow 
4346007Sthurlow /*ARGSUSED*/
4356007Sthurlow int
rqlist_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)4366007Sthurlow rqlist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4376007Sthurlow {
4386007Sthurlow 	rqlist_cbdata_t cbd;
4396007Sthurlow 
4406007Sthurlow 	memset(&cbd, 0, sizeof (cbd));
4416007Sthurlow 
4426007Sthurlow 	/*
4436007Sthurlow 	 * Initial walk_addr is address of parent (VC)
4446007Sthurlow 	 */
4456007Sthurlow 	if (!(flags & DCMD_ADDRSPEC)) {
4466007Sthurlow 		mdb_warn("address required\n");
4476007Sthurlow 		return (DCMD_ERR);
4486007Sthurlow 	}
4496007Sthurlow 
4506007Sthurlow 	if (mdb_pwalk("nsmb_rqlist", rqlist_cb, &cbd, addr) == -1) {
4516007Sthurlow 		mdb_warn("failed to walk 'nsmb_rqlist'");
4526007Sthurlow 		return (DCMD_ERR);
4536007Sthurlow 	}
4546007Sthurlow 
4556007Sthurlow 	return (DCMD_OK);
4566007Sthurlow }
4576007Sthurlow 
4586007Sthurlow 
4596007Sthurlow /*
4606007Sthurlow  * AVL walker for the passwords AVL tree,
4616007Sthurlow  * and dcmd to show a summary.
4626007Sthurlow  */
4636007Sthurlow static int
pwtree_walk_init(mdb_walk_state_t * wsp)4646007Sthurlow pwtree_walk_init(mdb_walk_state_t *wsp)
4656007Sthurlow {
4666007Sthurlow 	GElf_Sym sym;
4676007Sthurlow 
4686007Sthurlow 	if (wsp->walk_addr != NULL) {
4696007Sthurlow 		mdb_warn("pwtree walk only supports global walks\n");
4706007Sthurlow 		return (WALK_ERR);
4716007Sthurlow 	}
4726007Sthurlow 
4736007Sthurlow 	if (mdb_lookup_by_obj("nsmb", "smb_ptd", &sym) == -1) {
4746007Sthurlow 		mdb_warn("failed to find symbol 'smb_ptd'");
4756007Sthurlow 		return (WALK_ERR);
4766007Sthurlow 	}
4776007Sthurlow 
4786007Sthurlow 	wsp->walk_addr = (uintptr_t)sym.st_value;
4796007Sthurlow 
4806007Sthurlow 	if (mdb_layered_walk("avl", wsp) == -1) {
4816007Sthurlow 		mdb_warn("failed to walk 'avl'\n");
4826007Sthurlow 		return (WALK_ERR);
4836007Sthurlow 	}
4846007Sthurlow 
4856007Sthurlow 	return (WALK_NEXT);
4866007Sthurlow }
4876007Sthurlow 
4886007Sthurlow static int
pwtree_walk_step(mdb_walk_state_t * wsp)4896007Sthurlow pwtree_walk_step(mdb_walk_state_t *wsp)
4906007Sthurlow {
4916007Sthurlow 	smb_passid_t	ptnode;
4926007Sthurlow 
4936007Sthurlow 	if (mdb_vread(&ptnode, sizeof (ptnode), wsp->walk_addr) == -1) {
4946007Sthurlow 		mdb_warn("failed to read smb_passid_t at %p", wsp->walk_addr);
4956007Sthurlow 		return (WALK_ERR);
4966007Sthurlow 	}
4976007Sthurlow 
4986007Sthurlow 	return (wsp->walk_callback(wsp->walk_addr, &ptnode, wsp->walk_cbdata));
4996007Sthurlow }
5006007Sthurlow 
5016007Sthurlow typedef struct pwtree_cbdata {
5026007Sthurlow 	int printed_header;
5036007Sthurlow 	uid_t uid;		/* optional filtering by UID */
5046007Sthurlow } pwtree_cbdata_t;
5056007Sthurlow 
5066007Sthurlow int
pwtree_cb(uintptr_t addr,const void * data,void * arg)5076007Sthurlow pwtree_cb(uintptr_t addr, const void *data, void *arg)
5086007Sthurlow {
5096007Sthurlow 	const smb_passid_t *ptn = data;
5106007Sthurlow 	pwtree_cbdata_t *cbd = arg;
5116007Sthurlow 
5126007Sthurlow 	/* Optional filtering by UID. */
5136007Sthurlow 	if (cbd->uid != (uid_t)-1 && cbd->uid != ptn->uid) {
5146007Sthurlow 		return (WALK_NEXT);
5156007Sthurlow 	}
5166007Sthurlow 
5176007Sthurlow 	if (cbd->printed_header == 0) {
5186007Sthurlow 		cbd->printed_header = 1;
5196007Sthurlow 		mdb_printf("// smb_passid_t UID domain user\n");
5206007Sthurlow 	}
5216007Sthurlow 
5226007Sthurlow 	mdb_printf(" %-p", addr);	/* smb_passid_t */
5236007Sthurlow 	mdb_printf(" %d", (uintptr_t)ptn->uid);
5246007Sthurlow 	print_str((uintptr_t)ptn->srvdom);
5256007Sthurlow 	print_str((uintptr_t)ptn->username);
5266007Sthurlow 	mdb_printf("\n");
5276007Sthurlow 
5286007Sthurlow 	return (WALK_NEXT);
5296007Sthurlow }
5306007Sthurlow 
5316007Sthurlow /*ARGSUSED*/
5326007Sthurlow int
pwtree_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5336007Sthurlow pwtree_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5346007Sthurlow {
5356007Sthurlow 	pwtree_cbdata_t cbd;
5366007Sthurlow 	char *uid_str = NULL;
5376007Sthurlow 	char buf[32];
5386007Sthurlow 
5396007Sthurlow 	memset(&cbd, 0, sizeof (cbd));
5406007Sthurlow 
5416007Sthurlow 	if (mdb_getopts(argc, argv,
5426007Sthurlow 	    'u', MDB_OPT_STR, &uid_str, NULL) != argc) {
5436007Sthurlow 		return (DCMD_USAGE);
5446007Sthurlow 	}
5456007Sthurlow 	if (uid_str) {
5466007Sthurlow 		/*
5476007Sthurlow 		 * Want the the default radix to be 10 here.
5486007Sthurlow 		 * If the string has some kind of radix prefix,
5496007Sthurlow 		 * just use that as-is, otherwise prepend "0t".
5506007Sthurlow 		 * Cheating on the "not a digit" test, but
5516007Sthurlow 		 * mdb_strtoull will do a real syntax check.
5526007Sthurlow 		 */
5536007Sthurlow 		if (uid_str[0] == '0' && uid_str[1] > '9') {
5546007Sthurlow 			cbd.uid = (uid_t)mdb_strtoull(uid_str);
5556007Sthurlow 		} else {
5566007Sthurlow 			strcpy(buf, "0t");
5576007Sthurlow 			strlcat(buf, uid_str, sizeof (buf));
5586007Sthurlow 			cbd.uid = (uid_t)mdb_strtoull(buf);
5596007Sthurlow 		}
5606007Sthurlow 	} else
5616007Sthurlow 		cbd.uid = (uid_t)-1;
5626007Sthurlow 
5636007Sthurlow 	if (flags & DCMD_ADDRSPEC) {
5646007Sthurlow 		mdb_warn("address not allowed\n");
5656007Sthurlow 		return (DCMD_ERR);
5666007Sthurlow 	}
5676007Sthurlow 
5686007Sthurlow 	if (mdb_pwalk("nsmb_pwtree", pwtree_cb, &cbd, 0) == -1) {
5696007Sthurlow 		mdb_warn("failed to walk 'nsmb_pwtree'");
5706007Sthurlow 		return (DCMD_ERR);
5716007Sthurlow 	}
5726007Sthurlow 
5736007Sthurlow 	return (DCMD_OK);
5746007Sthurlow }
5756007Sthurlow 
5766007Sthurlow void
pwtree_help(void)5776007Sthurlow pwtree_help(void)
5786007Sthurlow {
5796007Sthurlow 	mdb_printf("Options:\n"
5806007Sthurlow 	    "  -u uid       show only entries belonging to uid (decimal)\n");
5816007Sthurlow }
5826007Sthurlow 
5836007Sthurlow 
5846007Sthurlow static const mdb_dcmd_t dcmds[] = {
5856007Sthurlow 	{ "nsmb_vc", "?[-rv]",
5866007Sthurlow 		"show smb_vc (or list)",
5876007Sthurlow 		smb_vc_dcmd, smb_vc_help },
5886007Sthurlow 	{ "nsmb_rqlist", ":",
5896007Sthurlow 		"show smb_rq list on a VC",
5906007Sthurlow 		rqlist_dcmd, NULL },
5916007Sthurlow 	{ "nsmb_pwtree", "?[-u uid]",
5926007Sthurlow 		"list smb_passid_t (password tree)",
5936007Sthurlow 		pwtree_dcmd, pwtree_help },
5946007Sthurlow 	{NULL}
5956007Sthurlow };
5966007Sthurlow 
5976007Sthurlow static const mdb_walker_t walkers[] = {
5986007Sthurlow 	{ "nsmb_vc", "walk nsmb VC list",
5996007Sthurlow 		smb_vc_walk_init, smb_co_walk_step, NULL },
6006007Sthurlow 	{ "nsmb_ss", "walk nsmb share list for some VC",
6016007Sthurlow 		smb_ss_walk_init, smb_co_walk_step, NULL },
6026007Sthurlow 	{ "nsmb_rqlist", "walk request list for some VC",
6036007Sthurlow 		rqlist_walk_init, rqlist_walk_step, NULL },
6046007Sthurlow 	{ "nsmb_pwtree", "walk passord AVL tree",
6056007Sthurlow 		pwtree_walk_init, pwtree_walk_step, NULL },
6066007Sthurlow 	{NULL}
6076007Sthurlow };
6086007Sthurlow 
6096007Sthurlow static const mdb_modinfo_t modinfo = {
6106007Sthurlow 	MDB_API_VERSION,
6116007Sthurlow 	dcmds,
6126007Sthurlow 	walkers
6136007Sthurlow };
6146007Sthurlow 
6156007Sthurlow const mdb_modinfo_t *
_mdb_init(void)6166007Sthurlow _mdb_init(void)
6176007Sthurlow {
6186007Sthurlow 	return (&modinfo);
6196007Sthurlow }
620