xref: /onnv-gate/usr/src/cmd/mdb/common/modules/nsmb/nsmb.c (revision 6007:d57e38e8fdd1)
1*6007Sthurlow /*
2*6007Sthurlow  * CDDL HEADER START
3*6007Sthurlow  *
4*6007Sthurlow  * The contents of this file are subject to the terms of the
5*6007Sthurlow  * Common Development and Distribution License (the "License").
6*6007Sthurlow  * You may not use this file except in compliance with the License.
7*6007Sthurlow  *
8*6007Sthurlow  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*6007Sthurlow  * or http://www.opensolaris.org/os/licensing.
10*6007Sthurlow  * See the License for the specific language governing permissions
11*6007Sthurlow  * and limitations under the License.
12*6007Sthurlow  *
13*6007Sthurlow  * When distributing Covered Code, include this CDDL HEADER in each
14*6007Sthurlow  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*6007Sthurlow  * If applicable, add the following below this CDDL HEADER, with the
16*6007Sthurlow  * fields enclosed by brackets "[]" replaced with your own identifying
17*6007Sthurlow  * information: Portions Copyright [yyyy] [name of copyright owner]
18*6007Sthurlow  *
19*6007Sthurlow  * CDDL HEADER END
20*6007Sthurlow  */
21*6007Sthurlow 
22*6007Sthurlow /*
23*6007Sthurlow  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*6007Sthurlow  * Use is subject to license terms.
25*6007Sthurlow  */
26*6007Sthurlow 
27*6007Sthurlow 
28*6007Sthurlow #pragma ident	"%Z%%M%	%I%	%E% SMI"
29*6007Sthurlow 
30*6007Sthurlow #include <sys/mdb_modapi.h>
31*6007Sthurlow #include <sys/types.h>
32*6007Sthurlow 
33*6007Sthurlow #include "smb_conn.h"
34*6007Sthurlow #include "smb_rq.h"
35*6007Sthurlow #include "smb_pass.h"
36*6007Sthurlow 
37*6007Sthurlow #define	OPT_VERBOSE	0x0001	/* Be [-v]erbose in dcmd's */
38*6007Sthurlow #define	OPT_RECURSE	0x0002	/* recursive display */
39*6007Sthurlow 
40*6007Sthurlow /*
41*6007Sthurlow  * We need to read in a private copy
42*6007Sthurlow  * of every string we want to print out.
43*6007Sthurlow  */
44*6007Sthurlow void
45*6007Sthurlow print_str(uintptr_t addr)
46*6007Sthurlow {
47*6007Sthurlow 	char buf[32];
48*6007Sthurlow 	int len, mx = sizeof (buf) - 4;
49*6007Sthurlow 
50*6007Sthurlow 	if ((len = mdb_readstr(buf, sizeof (buf), addr)) <= 0) {
51*6007Sthurlow 		mdb_printf(" (%p)", addr);
52*6007Sthurlow 	} else {
53*6007Sthurlow 		if (len > mx)
54*6007Sthurlow 			strcpy(&buf[mx], "...");
55*6007Sthurlow 		mdb_printf(" %s", buf);
56*6007Sthurlow 	}
57*6007Sthurlow }
58*6007Sthurlow 
59*6007Sthurlow 
60*6007Sthurlow /*
61*6007Sthurlow  * Walker for smb_connobj_t structures, including
62*6007Sthurlow  * smb_vc_t and smb_share_t which "inherit" from it.
63*6007Sthurlow  * Tricky: Exploit the "inheritance" of smb_connobj_t
64*6007Sthurlow  * with common functions for walk_init, walk_next.
65*6007Sthurlow  */
66*6007Sthurlow typedef struct smb_co_walk_data {
67*6007Sthurlow 	uintptr_t	pp;
68*6007Sthurlow 	int level;		/* SMBL_SM, SMBL_VC, SMBL_SHARE  */
69*6007Sthurlow 	int size;		/* sizeof (union member) */
70*6007Sthurlow 	union co_u {
71*6007Sthurlow 		smb_connobj_t	co;	/* copy of the list element */
72*6007Sthurlow 		smb_vc_t	vc;
73*6007Sthurlow 		smb_share_t	ss;
74*6007Sthurlow 	} u;
75*6007Sthurlow } smb_co_walk_data_t;
76*6007Sthurlow 
77*6007Sthurlow /*
78*6007Sthurlow  * Common walk_init for walking structs inherited
79*6007Sthurlow  * from smb_connobj_t (smb_vc_t, smb_share_t)
80*6007Sthurlow  */
81*6007Sthurlow int
82*6007Sthurlow smb_co_walk_init(mdb_walk_state_t *wsp, int level)
83*6007Sthurlow {
84*6007Sthurlow 	smb_co_walk_data_t *smbw;
85*6007Sthurlow 	size_t psz;
86*6007Sthurlow 
87*6007Sthurlow 	if (wsp->walk_addr == NULL)
88*6007Sthurlow 		return (WALK_ERR);
89*6007Sthurlow 
90*6007Sthurlow 	smbw = mdb_alloc(sizeof (*smbw), UM_SLEEP | UM_GC);
91*6007Sthurlow 	wsp->walk_data = smbw;
92*6007Sthurlow 
93*6007Sthurlow 	/*
94*6007Sthurlow 	 * Save the parent pointer for later checks, and
95*6007Sthurlow 	 * the level so we know which union member it is.
96*6007Sthurlow 	 * Also the size of this union member.
97*6007Sthurlow 	 */
98*6007Sthurlow 	smbw->pp = wsp->walk_addr;
99*6007Sthurlow 	smbw->level = level;
100*6007Sthurlow 	switch (level) {
101*6007Sthurlow 	case SMBL_SM:
102*6007Sthurlow 		smbw->size = sizeof (smbw->u.co);
103*6007Sthurlow 		break;
104*6007Sthurlow 	case SMBL_VC:
105*6007Sthurlow 		smbw->size = sizeof (smbw->u.vc);
106*6007Sthurlow 		break;
107*6007Sthurlow 	case SMBL_SHARE:
108*6007Sthurlow 		smbw->size = sizeof (smbw->u.ss);
109*6007Sthurlow 		break;
110*6007Sthurlow 	default:
111*6007Sthurlow 		smbw->size = sizeof (smbw->u);
112*6007Sthurlow 		break;
113*6007Sthurlow 	}
114*6007Sthurlow 
115*6007Sthurlow 	/*
116*6007Sthurlow 	 * Read in the parent object.  Just need the
117*6007Sthurlow 	 * invariant part (smb_connobj_t) so we can
118*6007Sthurlow 	 * get the list of children below it.
119*6007Sthurlow 	 */
120*6007Sthurlow 	psz = sizeof (smbw->u.co);
121*6007Sthurlow 	if (mdb_vread(&smbw->u.co, psz, smbw->pp) != psz) {
122*6007Sthurlow 		mdb_warn("cannot read connobj from %p", smbw->pp);
123*6007Sthurlow 		return (WALK_ERR);
124*6007Sthurlow 	}
125*6007Sthurlow 
126*6007Sthurlow 	/*
127*6007Sthurlow 	 * Finally, setup to walk the list of children.
128*6007Sthurlow 	 */
129*6007Sthurlow 	wsp->walk_addr = (uintptr_t)smbw->u.co.co_children.slh_first;
130*6007Sthurlow 
131*6007Sthurlow 	return (WALK_NEXT);
132*6007Sthurlow }
133*6007Sthurlow 
134*6007Sthurlow /*
135*6007Sthurlow  * Walk the (global) VC list.
136*6007Sthurlow  */
137*6007Sthurlow int
138*6007Sthurlow smb_vc_walk_init(mdb_walk_state_t *wsp)
139*6007Sthurlow {
140*6007Sthurlow 	GElf_Sym sym;
141*6007Sthurlow 
142*6007Sthurlow 	if (wsp->walk_addr != NULL) {
143*6007Sthurlow 		mdb_warn("::walk smb_vc only supports global walks\n");
144*6007Sthurlow 		return (WALK_ERR);
145*6007Sthurlow 	}
146*6007Sthurlow 
147*6007Sthurlow 	/* Locate the VC list head. */
148*6007Sthurlow 	if (mdb_lookup_by_obj("nsmb", "smb_vclist", &sym)) {
149*6007Sthurlow 		mdb_warn("failed to lookup `smb_vclist'\n");
150*6007Sthurlow 		return (WALK_ERR);
151*6007Sthurlow 	}
152*6007Sthurlow 	wsp->walk_addr = sym.st_value;
153*6007Sthurlow 
154*6007Sthurlow 	return (smb_co_walk_init(wsp, SMBL_VC));
155*6007Sthurlow }
156*6007Sthurlow 
157*6007Sthurlow /*
158*6007Sthurlow  * Walk the share list below some VC.
159*6007Sthurlow  */
160*6007Sthurlow int
161*6007Sthurlow smb_ss_walk_init(mdb_walk_state_t *wsp)
162*6007Sthurlow {
163*6007Sthurlow 
164*6007Sthurlow 	/*
165*6007Sthurlow 	 * Initial walk_addr is address of parent (VC)
166*6007Sthurlow 	 */
167*6007Sthurlow 	if (wsp->walk_addr == 0) {
168*6007Sthurlow 		mdb_warn("::walk smb_ss does not support global walks\n");
169*6007Sthurlow 		return (WALK_ERR);
170*6007Sthurlow 	}
171*6007Sthurlow 
172*6007Sthurlow 	return (smb_co_walk_init(wsp, SMBL_SHARE));
173*6007Sthurlow }
174*6007Sthurlow 
175*6007Sthurlow /*
176*6007Sthurlow  * Common walk_step for walking structs inherited
177*6007Sthurlow  * from smb_connobj_t (smb_vc_t, smb_share_t)
178*6007Sthurlow  */
179*6007Sthurlow int
180*6007Sthurlow smb_co_walk_step(mdb_walk_state_t *wsp)
181*6007Sthurlow {
182*6007Sthurlow 	smb_co_walk_data_t *smbw = wsp->walk_data;
183*6007Sthurlow 	int status;
184*6007Sthurlow 
185*6007Sthurlow 	if (wsp->walk_addr == NULL)
186*6007Sthurlow 		return (WALK_DONE);
187*6007Sthurlow 
188*6007Sthurlow 	if (mdb_vread(&smbw->u, smbw->size, wsp->walk_addr)
189*6007Sthurlow 	    != smbw->size) {
190*6007Sthurlow 		mdb_warn("cannot read connobj from %p", wsp->walk_addr);
191*6007Sthurlow 		return (WALK_ERR);
192*6007Sthurlow 	}
193*6007Sthurlow 
194*6007Sthurlow 	/* XXX: Sanity check level? parent pointer? */
195*6007Sthurlow 
196*6007Sthurlow 	status = wsp->walk_callback(wsp->walk_addr, &smbw->u,
197*6007Sthurlow 	    wsp->walk_cbdata);
198*6007Sthurlow 
199*6007Sthurlow 	wsp->walk_addr = (uintptr_t)smbw->u.co.co_next.sle_next;
200*6007Sthurlow 
201*6007Sthurlow 	return (status);
202*6007Sthurlow }
203*6007Sthurlow 
204*6007Sthurlow 
205*6007Sthurlow /*
206*6007Sthurlow  * Dcmd (and callback function) to print a summary of
207*6007Sthurlow  * all VCs, and optionally all shares under each VC.
208*6007Sthurlow  */
209*6007Sthurlow 
210*6007Sthurlow typedef struct smb_co_cbdata {
211*6007Sthurlow 	int flags;		/* OPT_...  */
212*6007Sthurlow 	int printed_header;
213*6007Sthurlow } smb_co_cbdata_t;
214*6007Sthurlow 
215*6007Sthurlow /*
216*6007Sthurlow  * Call-back function for walking a share list.
217*6007Sthurlow  */
218*6007Sthurlow int
219*6007Sthurlow smb_ss_cb(uintptr_t addr, const void *data, void *arg)
220*6007Sthurlow {
221*6007Sthurlow 	const smb_share_t *ssp = data;
222*6007Sthurlow 	smb_co_cbdata_t *cbd = arg;
223*6007Sthurlow 
224*6007Sthurlow 	mdb_printf(" %-p", addr);
225*6007Sthurlow 	print_str((uintptr_t)ssp->ss_name);
226*6007Sthurlow 	mdb_printf("\n");
227*6007Sthurlow 
228*6007Sthurlow 	if (cbd->flags & OPT_VERBOSE) {
229*6007Sthurlow 		mdb_inc_indent(2);
230*6007Sthurlow 		/* Anything wanted here? */
231*6007Sthurlow 		mdb_dec_indent(2);
232*6007Sthurlow 	}
233*6007Sthurlow 
234*6007Sthurlow 	return (WALK_NEXT);
235*6007Sthurlow }
236*6007Sthurlow 
237*6007Sthurlow /*
238*6007Sthurlow  * Call-back function for walking the VC list.
239*6007Sthurlow  */
240*6007Sthurlow int
241*6007Sthurlow smb_vc_cb(uintptr_t addr, const void *data, void *arg)
242*6007Sthurlow {
243*6007Sthurlow 	const smb_vc_t *vcp = data;
244*6007Sthurlow 	smb_co_cbdata_t *cbd = arg;
245*6007Sthurlow 
246*6007Sthurlow 	if (cbd->printed_header == 0) {
247*6007Sthurlow 		cbd->printed_header = 1;
248*6007Sthurlow 		mdb_printf("// smb_vc_t uid server user\n");
249*6007Sthurlow 	}
250*6007Sthurlow 
251*6007Sthurlow 	mdb_printf("%-p", addr);
252*6007Sthurlow 	mdb_printf(" %d", vcp->vc_uid);
253*6007Sthurlow 	print_str((uintptr_t)vcp->vc_srvname);
254*6007Sthurlow 	print_str((uintptr_t)vcp->vc_username);
255*6007Sthurlow 	mdb_printf("\n");
256*6007Sthurlow 
257*6007Sthurlow 	if (cbd->flags & OPT_RECURSE) {
258*6007Sthurlow 		mdb_inc_indent(2);
259*6007Sthurlow 		if (mdb_pwalk("nsmb_ss", smb_ss_cb, cbd, addr) < 0) {
260*6007Sthurlow 			mdb_warn("failed to walk 'nsmb_ss'");
261*6007Sthurlow 			/* Don't: return (WALK_ERR); */
262*6007Sthurlow 		}
263*6007Sthurlow 		mdb_dec_indent(2);
264*6007Sthurlow 	}
265*6007Sthurlow 
266*6007Sthurlow 	return (WALK_NEXT);
267*6007Sthurlow }
268*6007Sthurlow 
269*6007Sthurlow int
270*6007Sthurlow smb_vc_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
271*6007Sthurlow {
272*6007Sthurlow 	smb_co_cbdata_t cbd;
273*6007Sthurlow 	smb_vc_t *vcp;
274*6007Sthurlow 	size_t vcsz;
275*6007Sthurlow 
276*6007Sthurlow 	memset(&cbd, 0, sizeof (cbd));
277*6007Sthurlow 
278*6007Sthurlow 	if (mdb_getopts(argc, argv,
279*6007Sthurlow 	    'r', MDB_OPT_SETBITS, OPT_RECURSE, &cbd.flags,
280*6007Sthurlow 	    'v', MDB_OPT_SETBITS, OPT_VERBOSE, &cbd.flags,
281*6007Sthurlow 	    NULL) != argc) {
282*6007Sthurlow 		return (DCMD_USAGE);
283*6007Sthurlow 	}
284*6007Sthurlow 
285*6007Sthurlow 	if (!(flags & DCMD_ADDRSPEC)) {
286*6007Sthurlow 		if (mdb_walk("nsmb_vc", smb_vc_cb, &cbd) == -1) {
287*6007Sthurlow 			mdb_warn("failed to walk 'nsmb_vc'");
288*6007Sthurlow 			return (DCMD_ERR);
289*6007Sthurlow 		}
290*6007Sthurlow 		return (DCMD_OK);
291*6007Sthurlow 	}
292*6007Sthurlow 
293*6007Sthurlow 	vcsz = sizeof (*vcp);
294*6007Sthurlow 	vcp = mdb_alloc(vcsz, UM_SLEEP | UM_GC);
295*6007Sthurlow 	if (mdb_vread(vcp, vcsz, addr) != vcsz) {
296*6007Sthurlow 		mdb_warn("cannot read VC from %p", addr);
297*6007Sthurlow 		return (DCMD_ERR);
298*6007Sthurlow 	}
299*6007Sthurlow 	smb_vc_cb(addr, vcp, &cbd);
300*6007Sthurlow 
301*6007Sthurlow 	return (DCMD_OK);
302*6007Sthurlow }
303*6007Sthurlow 
304*6007Sthurlow void
305*6007Sthurlow smb_vc_help(void)
306*6007Sthurlow {
307*6007Sthurlow 	mdb_printf("Options:\n"
308*6007Sthurlow 	    "  -r           recursive display of share lists\n"
309*6007Sthurlow 	    "  -v           be verbose when displaying smb_vc\n");
310*6007Sthurlow }
311*6007Sthurlow 
312*6007Sthurlow /*
313*6007Sthurlow  * Walker for the request list on a VC,
314*6007Sthurlow  * and dcmd to show a summary.
315*6007Sthurlow  */
316*6007Sthurlow int
317*6007Sthurlow rqlist_walk_init(mdb_walk_state_t *wsp)
318*6007Sthurlow {
319*6007Sthurlow 	struct smb_rqhead rqh;
320*6007Sthurlow 	uintptr_t addr;
321*6007Sthurlow 
322*6007Sthurlow 	/*
323*6007Sthurlow 	 * Initial walk_addr is the address of the VC.
324*6007Sthurlow 	 * Add offsetof(iod_rqlist) to get the rqhead.
325*6007Sthurlow 	 */
326*6007Sthurlow 	if (wsp->walk_addr == 0) {
327*6007Sthurlow 		mdb_warn("::walk smb_ss does not support global walks\n");
328*6007Sthurlow 		return (WALK_ERR);
329*6007Sthurlow 	}
330*6007Sthurlow 	addr = wsp->walk_addr;
331*6007Sthurlow 	addr += OFFSETOF(smb_vc_t, iod_rqlist);
332*6007Sthurlow 
333*6007Sthurlow 	if (mdb_vread(&rqh, sizeof (rqh), addr) == -1) {
334*6007Sthurlow 		mdb_warn("failed to read smb_rqhead at %p", addr);
335*6007Sthurlow 		return (WALK_ERR);
336*6007Sthurlow 	}
337*6007Sthurlow 	wsp->walk_addr = (uintptr_t)rqh.tqh_first;
338*6007Sthurlow 
339*6007Sthurlow 	return (WALK_NEXT);
340*6007Sthurlow }
341*6007Sthurlow 
342*6007Sthurlow int
343*6007Sthurlow rqlist_walk_step(mdb_walk_state_t *wsp)
344*6007Sthurlow {
345*6007Sthurlow 	smb_rq_t rq;
346*6007Sthurlow 	int status;
347*6007Sthurlow 
348*6007Sthurlow 	if (wsp->walk_addr == NULL)
349*6007Sthurlow 		return (WALK_DONE);
350*6007Sthurlow 
351*6007Sthurlow 	if (mdb_vread(&rq, sizeof (rq), wsp->walk_addr) == -1) {
352*6007Sthurlow 		mdb_warn("cannot read smb_rq from %p", wsp->walk_addr);
353*6007Sthurlow 		return (WALK_ERR);
354*6007Sthurlow 	}
355*6007Sthurlow 
356*6007Sthurlow 	status = wsp->walk_callback(wsp->walk_addr, &rq,
357*6007Sthurlow 	    wsp->walk_cbdata);
358*6007Sthurlow 
359*6007Sthurlow 	wsp->walk_addr = (uintptr_t)rq.sr_link.tqe_next;
360*6007Sthurlow 
361*6007Sthurlow 	return (status);
362*6007Sthurlow }
363*6007Sthurlow 
364*6007Sthurlow typedef struct rqlist_cbdata {
365*6007Sthurlow 	int printed_header;
366*6007Sthurlow 	uintptr_t uid;		/* optional filtering by UID */
367*6007Sthurlow } rqlist_cbdata_t;
368*6007Sthurlow 
369*6007Sthurlow int
370*6007Sthurlow rqlist_cb(uintptr_t addr, const void *data, void *arg)
371*6007Sthurlow {
372*6007Sthurlow 	const smb_rq_t *rq = data;
373*6007Sthurlow 	rqlist_cbdata_t *cbd = arg;
374*6007Sthurlow 
375*6007Sthurlow 	if (cbd->printed_header == 0) {
376*6007Sthurlow 		cbd->printed_header = 1;
377*6007Sthurlow 		mdb_printf("// smb_rq_t MID cmd sr_state sr_flags\n");
378*6007Sthurlow 	}
379*6007Sthurlow 
380*6007Sthurlow 	mdb_printf(" %-p", addr);	/* smb_rq_t */
381*6007Sthurlow 	mdb_printf(" x%04x", rq->sr_mid);
382*6007Sthurlow 	mdb_printf(" x%02x", rq->sr_cmd);
383*6007Sthurlow 	mdb_printf(" %d", rq->sr_state);
384*6007Sthurlow 	mdb_printf(" x%x", rq->sr_flags);
385*6007Sthurlow 	mdb_printf("\n");
386*6007Sthurlow 
387*6007Sthurlow 	return (WALK_NEXT);
388*6007Sthurlow }
389*6007Sthurlow 
390*6007Sthurlow /*ARGSUSED*/
391*6007Sthurlow int
392*6007Sthurlow rqlist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
393*6007Sthurlow {
394*6007Sthurlow 	rqlist_cbdata_t cbd;
395*6007Sthurlow 
396*6007Sthurlow 	memset(&cbd, 0, sizeof (cbd));
397*6007Sthurlow 
398*6007Sthurlow 	/*
399*6007Sthurlow 	 * Initial walk_addr is address of parent (VC)
400*6007Sthurlow 	 */
401*6007Sthurlow 	if (!(flags & DCMD_ADDRSPEC)) {
402*6007Sthurlow 		mdb_warn("address required\n");
403*6007Sthurlow 		return (DCMD_ERR);
404*6007Sthurlow 	}
405*6007Sthurlow 
406*6007Sthurlow 	if (mdb_pwalk("nsmb_rqlist", rqlist_cb, &cbd, addr) == -1) {
407*6007Sthurlow 		mdb_warn("failed to walk 'nsmb_rqlist'");
408*6007Sthurlow 		return (DCMD_ERR);
409*6007Sthurlow 	}
410*6007Sthurlow 
411*6007Sthurlow 	return (DCMD_OK);
412*6007Sthurlow }
413*6007Sthurlow 
414*6007Sthurlow 
415*6007Sthurlow /*
416*6007Sthurlow  * AVL walker for the passwords AVL tree,
417*6007Sthurlow  * and dcmd to show a summary.
418*6007Sthurlow  */
419*6007Sthurlow static int
420*6007Sthurlow pwtree_walk_init(mdb_walk_state_t *wsp)
421*6007Sthurlow {
422*6007Sthurlow 	GElf_Sym sym;
423*6007Sthurlow 
424*6007Sthurlow 	if (wsp->walk_addr != NULL) {
425*6007Sthurlow 		mdb_warn("pwtree walk only supports global walks\n");
426*6007Sthurlow 		return (WALK_ERR);
427*6007Sthurlow 	}
428*6007Sthurlow 
429*6007Sthurlow 	if (mdb_lookup_by_obj("nsmb", "smb_ptd", &sym) == -1) {
430*6007Sthurlow 		mdb_warn("failed to find symbol 'smb_ptd'");
431*6007Sthurlow 		return (WALK_ERR);
432*6007Sthurlow 	}
433*6007Sthurlow 
434*6007Sthurlow 	wsp->walk_addr = (uintptr_t)sym.st_value;
435*6007Sthurlow 
436*6007Sthurlow 	if (mdb_layered_walk("avl", wsp) == -1) {
437*6007Sthurlow 		mdb_warn("failed to walk 'avl'\n");
438*6007Sthurlow 		return (WALK_ERR);
439*6007Sthurlow 	}
440*6007Sthurlow 
441*6007Sthurlow 	return (WALK_NEXT);
442*6007Sthurlow }
443*6007Sthurlow 
444*6007Sthurlow static int
445*6007Sthurlow pwtree_walk_step(mdb_walk_state_t *wsp)
446*6007Sthurlow {
447*6007Sthurlow 	smb_passid_t	ptnode;
448*6007Sthurlow 
449*6007Sthurlow 	if (mdb_vread(&ptnode, sizeof (ptnode), wsp->walk_addr) == -1) {
450*6007Sthurlow 		mdb_warn("failed to read smb_passid_t at %p", wsp->walk_addr);
451*6007Sthurlow 		return (WALK_ERR);
452*6007Sthurlow 	}
453*6007Sthurlow 
454*6007Sthurlow 	return (wsp->walk_callback(wsp->walk_addr, &ptnode, wsp->walk_cbdata));
455*6007Sthurlow }
456*6007Sthurlow 
457*6007Sthurlow typedef struct pwtree_cbdata {
458*6007Sthurlow 	int printed_header;
459*6007Sthurlow 	uid_t uid;		/* optional filtering by UID */
460*6007Sthurlow } pwtree_cbdata_t;
461*6007Sthurlow 
462*6007Sthurlow int
463*6007Sthurlow pwtree_cb(uintptr_t addr, const void *data, void *arg)
464*6007Sthurlow {
465*6007Sthurlow 	const smb_passid_t *ptn = data;
466*6007Sthurlow 	pwtree_cbdata_t *cbd = arg;
467*6007Sthurlow 
468*6007Sthurlow 	/* Optional filtering by UID. */
469*6007Sthurlow 	if (cbd->uid != (uid_t)-1 && cbd->uid != ptn->uid) {
470*6007Sthurlow 		return (WALK_NEXT);
471*6007Sthurlow 	}
472*6007Sthurlow 
473*6007Sthurlow 	if (cbd->printed_header == 0) {
474*6007Sthurlow 		cbd->printed_header = 1;
475*6007Sthurlow 		mdb_printf("// smb_passid_t UID domain user\n");
476*6007Sthurlow 	}
477*6007Sthurlow 
478*6007Sthurlow 	mdb_printf(" %-p", addr);	/* smb_passid_t */
479*6007Sthurlow 	mdb_printf(" %d", (uintptr_t)ptn->uid);
480*6007Sthurlow 	print_str((uintptr_t)ptn->srvdom);
481*6007Sthurlow 	print_str((uintptr_t)ptn->username);
482*6007Sthurlow 	mdb_printf("\n");
483*6007Sthurlow 
484*6007Sthurlow 	return (WALK_NEXT);
485*6007Sthurlow }
486*6007Sthurlow 
487*6007Sthurlow /*ARGSUSED*/
488*6007Sthurlow int
489*6007Sthurlow pwtree_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
490*6007Sthurlow {
491*6007Sthurlow 	pwtree_cbdata_t cbd;
492*6007Sthurlow 	char *uid_str = NULL;
493*6007Sthurlow 	char buf[32];
494*6007Sthurlow 
495*6007Sthurlow 	memset(&cbd, 0, sizeof (cbd));
496*6007Sthurlow 
497*6007Sthurlow 	if (mdb_getopts(argc, argv,
498*6007Sthurlow 	    'u', MDB_OPT_STR, &uid_str, NULL) != argc) {
499*6007Sthurlow 		return (DCMD_USAGE);
500*6007Sthurlow 	}
501*6007Sthurlow 	if (uid_str) {
502*6007Sthurlow 		/*
503*6007Sthurlow 		 * Want the the default radix to be 10 here.
504*6007Sthurlow 		 * If the string has some kind of radix prefix,
505*6007Sthurlow 		 * just use that as-is, otherwise prepend "0t".
506*6007Sthurlow 		 * Cheating on the "not a digit" test, but
507*6007Sthurlow 		 * mdb_strtoull will do a real syntax check.
508*6007Sthurlow 		 */
509*6007Sthurlow 		if (uid_str[0] == '0' && uid_str[1] > '9') {
510*6007Sthurlow 			cbd.uid = (uid_t)mdb_strtoull(uid_str);
511*6007Sthurlow 		} else {
512*6007Sthurlow 			strcpy(buf, "0t");
513*6007Sthurlow 			strlcat(buf, uid_str, sizeof (buf));
514*6007Sthurlow 			cbd.uid = (uid_t)mdb_strtoull(buf);
515*6007Sthurlow 		}
516*6007Sthurlow 	} else
517*6007Sthurlow 		cbd.uid = (uid_t)-1;
518*6007Sthurlow 
519*6007Sthurlow 	if (flags & DCMD_ADDRSPEC) {
520*6007Sthurlow 		mdb_warn("address not allowed\n");
521*6007Sthurlow 		return (DCMD_ERR);
522*6007Sthurlow 	}
523*6007Sthurlow 
524*6007Sthurlow 	if (mdb_pwalk("nsmb_pwtree", pwtree_cb, &cbd, 0) == -1) {
525*6007Sthurlow 		mdb_warn("failed to walk 'nsmb_pwtree'");
526*6007Sthurlow 		return (DCMD_ERR);
527*6007Sthurlow 	}
528*6007Sthurlow 
529*6007Sthurlow 	return (DCMD_OK);
530*6007Sthurlow }
531*6007Sthurlow 
532*6007Sthurlow void
533*6007Sthurlow pwtree_help(void)
534*6007Sthurlow {
535*6007Sthurlow 	mdb_printf("Options:\n"
536*6007Sthurlow 	    "  -u uid       show only entries belonging to uid (decimal)\n");
537*6007Sthurlow }
538*6007Sthurlow 
539*6007Sthurlow 
540*6007Sthurlow static const mdb_dcmd_t dcmds[] = {
541*6007Sthurlow 	{ "nsmb_vc", "?[-rv]",
542*6007Sthurlow 		"show smb_vc (or list)",
543*6007Sthurlow 		smb_vc_dcmd, smb_vc_help },
544*6007Sthurlow 	{ "nsmb_rqlist", ":",
545*6007Sthurlow 		"show smb_rq list on a VC",
546*6007Sthurlow 		rqlist_dcmd, NULL },
547*6007Sthurlow 	{ "nsmb_pwtree", "?[-u uid]",
548*6007Sthurlow 		"list smb_passid_t (password tree)",
549*6007Sthurlow 		pwtree_dcmd, pwtree_help },
550*6007Sthurlow 	{NULL}
551*6007Sthurlow };
552*6007Sthurlow 
553*6007Sthurlow static const mdb_walker_t walkers[] = {
554*6007Sthurlow 	{ "nsmb_vc", "walk nsmb VC list",
555*6007Sthurlow 		smb_vc_walk_init, smb_co_walk_step, NULL },
556*6007Sthurlow 	{ "nsmb_ss", "walk nsmb share list for some VC",
557*6007Sthurlow 		smb_ss_walk_init, smb_co_walk_step, NULL },
558*6007Sthurlow 	{ "nsmb_rqlist", "walk request list for some VC",
559*6007Sthurlow 		rqlist_walk_init, rqlist_walk_step, NULL },
560*6007Sthurlow 	{ "nsmb_pwtree", "walk passord AVL tree",
561*6007Sthurlow 		pwtree_walk_init, pwtree_walk_step, NULL },
562*6007Sthurlow 	{NULL}
563*6007Sthurlow };
564*6007Sthurlow 
565*6007Sthurlow static const mdb_modinfo_t modinfo = {
566*6007Sthurlow 	MDB_API_VERSION,
567*6007Sthurlow 	dcmds,
568*6007Sthurlow 	walkers
569*6007Sthurlow };
570*6007Sthurlow 
571*6007Sthurlow const mdb_modinfo_t *
572*6007Sthurlow _mdb_init(void)
573*6007Sthurlow {
574*6007Sthurlow 	return (&modinfo);
575*6007Sthurlow }
576