xref: /onnv-gate/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c (revision 5331:3047ad28a67b)
1*5331Samw /*
2*5331Samw  * CDDL HEADER START
3*5331Samw  *
4*5331Samw  * The contents of this file are subject to the terms of the
5*5331Samw  * Common Development and Distribution License (the "License").
6*5331Samw  * You may not use this file except in compliance with the License.
7*5331Samw  *
8*5331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5331Samw  * or http://www.opensolaris.org/os/licensing.
10*5331Samw  * See the License for the specific language governing permissions
11*5331Samw  * and limitations under the License.
12*5331Samw  *
13*5331Samw  * When distributing Covered Code, include this CDDL HEADER in each
14*5331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5331Samw  * If applicable, add the following below this CDDL HEADER, with the
16*5331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
17*5331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5331Samw  *
19*5331Samw  * CDDL HEADER END
20*5331Samw  */
21*5331Samw /*
22*5331Samw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*5331Samw  * Use is subject to license terms.
24*5331Samw  */
25*5331Samw 
26*5331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5331Samw 
28*5331Samw #include <sys/mdb_modapi.h>
29*5331Samw #include <smbsrv/smb_vops.h>
30*5331Samw #include <smbsrv/smb.h>
31*5331Samw #include <smbsrv/mlsvc.h>
32*5331Samw #include <smbsrv/smbvar.h>
33*5331Samw 
34*5331Samw #define	SMB_DCMD_INDENT		4
35*5331Samw 
36*5331Samw static void smb_lookup_svc_state_str(smb_svcstate_t state, char *dst_str,
37*5331Samw     int slen);
38*5331Samw 
39*5331Samw /*
40*5331Samw  * Initialize the smb_session_t walker by reading the value of smb_info
41*5331Samw  * object in the kernel's symbol table. Only global walk supported.
42*5331Samw  */
43*5331Samw static int
44*5331Samw smb_session_walk_init(mdb_walk_state_t *wsp)
45*5331Samw {
46*5331Samw 	GElf_Sym	sym;
47*5331Samw 	uintptr_t	svcsm_addr;
48*5331Samw 
49*5331Samw 	if (wsp->walk_addr == NULL) {
50*5331Samw 		if (mdb_lookup_by_name("smb_info", &sym) == -1) {
51*5331Samw 			mdb_warn("failed to find 'smb_info'");
52*5331Samw 			return (WALK_ERR);
53*5331Samw 		}
54*5331Samw 		svcsm_addr = (uintptr_t)(sym.st_value +
55*5331Samw 		    offsetof(struct smb_info, si_svc_sm_ctx));
56*5331Samw 		wsp->walk_addr = svcsm_addr +
57*5331Samw 		    offsetof(smb_svc_sm_ctx_t, ssc_active_sessions);
58*5331Samw 	} else {
59*5331Samw 		mdb_printf("smb_session walk only supports global walks\n");
60*5331Samw 		return (WALK_ERR);
61*5331Samw 	}
62*5331Samw 
63*5331Samw 	if (mdb_layered_walk("list", wsp) == -1) {
64*5331Samw 		mdb_warn("failed to walk 'list'");
65*5331Samw 		return (WALK_ERR);
66*5331Samw 	}
67*5331Samw 
68*5331Samw 	return (WALK_NEXT);
69*5331Samw }
70*5331Samw 
71*5331Samw static int
72*5331Samw smb_session_walk_step(mdb_walk_state_t *wsp)
73*5331Samw {
74*5331Samw 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
75*5331Samw 	    wsp->walk_cbdata));
76*5331Samw }
77*5331Samw 
78*5331Samw /*
79*5331Samw  * Initialize the smb_node_t walker by reading the value of smb_info
80*5331Samw  * object in the kernel's symbol table. Only global walk supported.
81*5331Samw  */
82*5331Samw static int
83*5331Samw smb_node_walk_init(mdb_walk_state_t *wsp)
84*5331Samw {
85*5331Samw 	GElf_Sym	sym;
86*5331Samw 	int		i;
87*5331Samw 	uintptr_t	node_hash_table_addr;
88*5331Samw 
89*5331Samw 	if (wsp->walk_addr == NULL) {
90*5331Samw 		if (mdb_lookup_by_name("smb_info", &sym) == -1) {
91*5331Samw 			mdb_warn("failed to find 'smb_info'");
92*5331Samw 			return (WALK_ERR);
93*5331Samw 		}
94*5331Samw 		node_hash_table_addr = (uintptr_t)(sym.st_value +
95*5331Samw 		    offsetof(struct smb_info, node_hash_table));
96*5331Samw 	} else {
97*5331Samw 		mdb_printf("smb_node walk only supports global walks\n");
98*5331Samw 		return (WALK_ERR);
99*5331Samw 	}
100*5331Samw 
101*5331Samw 	for (i = 0; i < SMBND_HASH_MASK + 1; i++) {
102*5331Samw 		wsp->walk_addr = node_hash_table_addr +
103*5331Samw 		    (i * sizeof (smb_llist_t)) +
104*5331Samw 		    offsetof(smb_llist_t, ll_list);
105*5331Samw 		if (mdb_layered_walk("list", wsp) == -1) {
106*5331Samw 			mdb_warn("failed to walk 'list'");
107*5331Samw 			return (WALK_ERR);
108*5331Samw 		}
109*5331Samw 	}
110*5331Samw 
111*5331Samw 	return (WALK_NEXT);
112*5331Samw }
113*5331Samw 
114*5331Samw static int
115*5331Samw smb_node_walk_step(mdb_walk_state_t *wsp)
116*5331Samw {
117*5331Samw 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
118*5331Samw 	    wsp->walk_cbdata));
119*5331Samw }
120*5331Samw 
121*5331Samw /*
122*5331Samw  * ::smb_info
123*5331Samw  *
124*5331Samw  * smb_info dcmd - Print out the smb_info structure.
125*5331Samw  */
126*5331Samw /*ARGSUSED*/
127*5331Samw static int
128*5331Samw smb_information(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
129*5331Samw {
130*5331Samw 	int print_config = FALSE;
131*5331Samw 	struct smb_info	smb_info;
132*5331Samw 	GElf_Sym smb_info_sym;
133*5331Samw 	char state_name[40];
134*5331Samw 	char last_state_name[40];
135*5331Samw 
136*5331Samw 	if (mdb_getopts(argc, argv,
137*5331Samw 	    'c', MDB_OPT_SETBITS, TRUE, &print_config,
138*5331Samw 	    NULL) != argc)
139*5331Samw 		return (DCMD_USAGE);
140*5331Samw 
141*5331Samw 	if (flags & DCMD_ADDRSPEC)
142*5331Samw 		return (DCMD_USAGE);
143*5331Samw 
144*5331Samw 	if (mdb_lookup_by_obj(MDB_OBJ_EVERY, "smb_info", &smb_info_sym)) {
145*5331Samw 		mdb_warn("failed to find symbol smb_info");
146*5331Samw 		return (DCMD_ERR);
147*5331Samw 	}
148*5331Samw 
149*5331Samw 	if (mdb_readvar(&smb_info, "smb_info") == -1) {
150*5331Samw 		mdb_warn("failed to read smb_info structure");
151*5331Samw 		return (DCMD_ERR);
152*5331Samw 	}
153*5331Samw 
154*5331Samw 	/* Lookup state string */
155*5331Samw 	smb_lookup_svc_state_str(smb_info.si_svc_sm_ctx.ssc_state,
156*5331Samw 	    state_name, 40);
157*5331Samw 	smb_lookup_svc_state_str(smb_info.si_svc_sm_ctx.ssc_last_state,
158*5331Samw 	    last_state_name, 40);
159*5331Samw 
160*5331Samw 	mdb_printf("SMB information:\n\n");
161*5331Samw 	mdb_printf("        SMB state :\t%s (%d)\n", state_name,
162*5331Samw 	    smb_info.si_svc_sm_ctx.ssc_state);
163*5331Samw 	mdb_printf("   SMB last state :\t%s (%d)\n", last_state_name,
164*5331Samw 	    smb_info.si_svc_sm_ctx.ssc_last_state);
165*5331Samw 	mdb_printf("  Active Sessions :\t%d\n",
166*5331Samw 	    smb_info.si_svc_sm_ctx.ssc_active_session_count);
167*5331Samw 	mdb_printf("Deferred Sessions :\t%d\n",
168*5331Samw 	    smb_info.si_svc_sm_ctx.ssc_deferred_session_count);
169*5331Samw 	mdb_printf("   SMB Open Files :\t%d\n", smb_info.open_files);
170*5331Samw 	mdb_printf("   SMB Open Trees :\t%d\n", smb_info.open_trees);
171*5331Samw 	mdb_printf("   SMB Open Users :\t%d\n\n", smb_info.open_users);
172*5331Samw 
173*5331Samw 	if (print_config) {
174*5331Samw 		mdb_printf("Configuration:\n\n");
175*5331Samw 		(void) mdb_inc_indent(SMB_DCMD_INDENT);
176*5331Samw 		mdb_printf("Max Buffer Size %d\n",
177*5331Samw 		    smb_info.si.skc_maxbufsize);
178*5331Samw 		mdb_printf("Max Worker Thread %d\n",
179*5331Samw 		    smb_info.si.skc_maxworkers);
180*5331Samw 		mdb_printf("Max Connections %d\n",
181*5331Samw 		    smb_info.si.skc_maxconnections);
182*5331Samw 		mdb_printf("Keep Alive Timeout %d\n",
183*5331Samw 		    smb_info.si.skc_keepalive);
184*5331Samw 		mdb_printf("%sRestrict Anonymous Access\n",
185*5331Samw 		    (smb_info.si.skc_restrict_anon) ? "" : "Do Not ");
186*5331Samw 		mdb_printf("Signing %s\n",
187*5331Samw 		    (smb_info.si.skc_signing_enable) ? "Enabled" : "Disabled");
188*5331Samw 		mdb_printf("Signing %sRequired\n",
189*5331Samw 		    (smb_info.si.skc_signing_required) ? "" : "Not ");
190*5331Samw 		mdb_printf("Signing Check %s\n",
191*5331Samw 		    (smb_info.si.skc_signing_check) ? "Enabled" : "Disabled");
192*5331Samw 		mdb_printf("Oplocks %s\n",
193*5331Samw 		    (smb_info.si.skc_oplock_enable) ? "Enabled" : "Disabled");
194*5331Samw 		mdb_printf("Oplock Timeout %d millisec\n",
195*5331Samw 		    smb_info.si.skc_oplock_timeout);
196*5331Samw 		mdb_printf("Flush %sRequired\n",
197*5331Samw 		    (smb_info.si.skc_flush_required) ? "" : "Not ");
198*5331Samw 		mdb_printf("Sync %s\n",
199*5331Samw 		    (smb_info.si.skc_sync_enable) ? "Enabled" : "Disabled");
200*5331Samw 		mdb_printf("Dir Symlink %s\n",
201*5331Samw 		    (smb_info.si.skc_dirsymlink_enable) ?
202*5331Samw 		    "Enabled" : "Disabled");
203*5331Samw 		mdb_printf("%sAnnounce Quota\n",
204*5331Samw 		    (smb_info.si.skc_announce_quota) ? "" : "Do Not ");
205*5331Samw 		mdb_printf("Security Mode %d\n", smb_info.si.skc_secmode);
206*5331Samw 		mdb_printf("LM Level %d\n", smb_info.si.skc_lmlevel);
207*5331Samw 		mdb_printf("Domain %s\n", smb_info.si.skc_resource_domain);
208*5331Samw 		mdb_printf("Hostname %s\n", smb_info.si.skc_hostname);
209*5331Samw 		mdb_printf("Comment %s\n", smb_info.si.skc_system_comment);
210*5331Samw 		(void) mdb_dec_indent(SMB_DCMD_INDENT);
211*5331Samw 		mdb_printf("\n");
212*5331Samw 	}
213*5331Samw 
214*5331Samw 	return (DCMD_OK);
215*5331Samw }
216*5331Samw 
217*5331Samw static void
218*5331Samw smb_lookup_svc_state_str(smb_svcstate_t state, char *dst_str, int slen)
219*5331Samw {
220*5331Samw 	GElf_Sym	smb_statename_table_sym;
221*5331Samw 	uintptr_t	statename_addr_addr, statename_addr;
222*5331Samw 
223*5331Samw 	if (mdb_lookup_by_name("smb_svcstate_state_name",
224*5331Samw 	    &smb_statename_table_sym)) {
225*5331Samw 		(void) mdb_snprintf(dst_str, slen, "UNKNOWN");
226*5331Samw 		return;
227*5331Samw 	}
228*5331Samw 
229*5331Samw 	/* Lookup state string */
230*5331Samw 	statename_addr_addr = smb_statename_table_sym.st_value +
231*5331Samw 	    (state * sizeof (uintptr_t));
232*5331Samw 	if (mdb_vread(&statename_addr, sizeof (uintptr_t),
233*5331Samw 	    statename_addr_addr) == -1) {
234*5331Samw 		(void) mdb_snprintf(dst_str, slen, "UNKNOWN");
235*5331Samw 		return;
236*5331Samw 	} else {
237*5331Samw 		if (mdb_readstr(dst_str, slen, statename_addr) == -1) {
238*5331Samw 			(void) mdb_snprintf(dst_str, slen, "UNKNOWN");
239*5331Samw 			return;
240*5331Samw 		}
241*5331Samw 	}
242*5331Samw }
243*5331Samw 
244*5331Samw static void
245*5331Samw smb_node_help(void)
246*5331Samw {
247*5331Samw 	mdb_printf(
248*5331Samw 	    "Display the contents of smb_node_t, with optional filtering.\n\n");
249*5331Samw 	mdb_dec_indent(2);
250*5331Samw 	mdb_printf("%<b>OPTIONS%</b>\n");
251*5331Samw 	mdb_inc_indent(2);
252*5331Samw 	mdb_printf(
253*5331Samw 	    "-v\tDisplay verbose smb_node information\n"
254*5331Samw 	    "-p\tDisplay the full path of the vnode associated\n"
255*5331Samw 	    "-s\tDisplay the stack of the last 16 calls that modified the "
256*5331Samw 	    "reference\n\tcount\n");
257*5331Samw }
258*5331Samw 
259*5331Samw /*
260*5331Samw  * ::smb_node
261*5331Samw  *
262*5331Samw  * smb_node dcmd - Print out smb_node structure.
263*5331Samw  */
264*5331Samw /*ARGSUSED*/
265*5331Samw static int
266*5331Samw smb_node(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
267*5331Samw {
268*5331Samw 	smb_node_t	node;
269*5331Samw 	int		verbose = FALSE;
270*5331Samw 	int		print_full_path = FALSE;
271*5331Samw 	int		stack_trace = FALSE;
272*5331Samw 	vnode_t		vnode;
273*5331Samw 	char		od_name[MAXNAMELEN];
274*5331Samw 	char		path_name[1024];
275*5331Samw 	uintptr_t	list_addr;
276*5331Samw 
277*5331Samw 	if (mdb_getopts(argc, argv,
278*5331Samw 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
279*5331Samw 	    'p', MDB_OPT_SETBITS, TRUE, &print_full_path,
280*5331Samw 	    's', MDB_OPT_SETBITS, TRUE, &stack_trace,
281*5331Samw 	    NULL) != argc)
282*5331Samw 		return (DCMD_USAGE);
283*5331Samw 
284*5331Samw 	/*
285*5331Samw 	 * If no smb_node address was specified on the command line, we can
286*5331Samw 	 * print out all smb nodes by invoking the smb_node walker, using
287*5331Samw 	 * this dcmd itself as the callback.
288*5331Samw 	 */
289*5331Samw 	if (!(flags & DCMD_ADDRSPEC)) {
290*5331Samw 		if (mdb_walk_dcmd("smb_node", "smb_node",
291*5331Samw 		    argc, argv) == -1) {
292*5331Samw 			mdb_warn("failed to walk 'smb_node'");
293*5331Samw 			return (DCMD_ERR);
294*5331Samw 		}
295*5331Samw 		return (DCMD_OK);
296*5331Samw 	}
297*5331Samw 
298*5331Samw 	/*
299*5331Samw 	 * If this is the first invocation of the command, print a nice
300*5331Samw 	 * header line for the output that will follow.
301*5331Samw 	 */
302*5331Samw 	if (DCMD_HDRSPEC(flags)) {
303*5331Samw 		if (verbose)
304*5331Samw 			mdb_printf("SMB node information:\n\n");
305*5331Samw 		else
306*5331Samw 			mdb_printf("%<u>%?s %?s %18s %6s %5s %4s%</u>\n",
307*5331Samw 			    "SMB Nodes:", "VP", "NODE NAME",
308*5331Samw 			    "OFILES", "LOCKS", "REF");
309*5331Samw 	}
310*5331Samw 
311*5331Samw 	/*
312*5331Samw 	 * For each smb_node, we just need to read the smb_node_t struct,
313*5331Samw 	 * read and then print out the following fields.
314*5331Samw 	 */
315*5331Samw 	if (mdb_vread(&node, sizeof (node), addr) == sizeof (node)) {
316*5331Samw 		(void) mdb_snprintf(od_name, MAXNAMELEN, "%s", node.od_name);
317*5331Samw 		if (print_full_path) {
318*5331Samw 			if (mdb_vread(&vnode, sizeof (vnode_t),
319*5331Samw 			    (uintptr_t)node.vp) ==
320*5331Samw 			    sizeof (vnode_t)) {
321*5331Samw 				if (mdb_readstr(path_name, 1024,
322*5331Samw 				    (uintptr_t)vnode.v_path) != 0) {
323*5331Samw 					(void) mdb_snprintf(od_name,
324*5331Samw 					    MAXNAMELEN, "N/A");
325*5331Samw 				}
326*5331Samw 			}
327*5331Samw 		}
328*5331Samw 		if (verbose) {
329*5331Samw 			mdb_printf("VP              :\t%p\n",
330*5331Samw 			    node.vp);
331*5331Samw 			mdb_printf("Name            :\t%s\n",
332*5331Samw 			    od_name);
333*5331Samw 			if (print_full_path) {
334*5331Samw 				mdb_printf("V-node Path     :\t%s\n",
335*5331Samw 				    path_name);
336*5331Samw 			}
337*5331Samw 			mdb_printf("Ofiles          :\t%u\n",
338*5331Samw 			    node.n_ofile_list.ll_count);
339*5331Samw 			mdb_printf("Range Locks     :\t%u\n",
340*5331Samw 			    node.n_lock_list.ll_count);
341*5331Samw 			if (node.n_lock_list.ll_count != 0) {
342*5331Samw 				(void) mdb_inc_indent(SMB_DCMD_INDENT);
343*5331Samw 				list_addr = addr +
344*5331Samw 				    offsetof(smb_node_t, n_lock_list) +
345*5331Samw 				    offsetof(smb_llist_t, ll_list);
346*5331Samw 				if (mdb_pwalk_dcmd("list", "smb_lock",
347*5331Samw 				    0, NULL, list_addr)) {
348*5331Samw 					mdb_warn("failed to walk node's active"
349*5331Samw 					    " locks");
350*5331Samw 				}
351*5331Samw 				(void) mdb_dec_indent(SMB_DCMD_INDENT);
352*5331Samw 			}
353*5331Samw 			mdb_printf("Reference Count :\t%u\n",
354*5331Samw 			    node.n_refcnt);
355*5331Samw 			mdb_printf("\n");
356*5331Samw 		} else {
357*5331Samw 			mdb_printf("%?p %?p %18s %5d %5d %4d\n",
358*5331Samw 			    addr, node.vp, od_name, node.n_ofile_list.ll_count,
359*5331Samw 			    node.n_lock_list.ll_count, node.n_refcnt);
360*5331Samw 			if (print_full_path) {
361*5331Samw 				if (mdb_vread(&vnode, sizeof (vnode_t),
362*5331Samw 				    (uintptr_t)node.vp) ==
363*5331Samw 				    sizeof (vnode_t)) {
364*5331Samw 					if (mdb_readstr(path_name, 1024,
365*5331Samw 					    (uintptr_t)vnode.v_path)) {
366*5331Samw 						mdb_printf("\t%s\n",
367*5331Samw 						    path_name);
368*5331Samw 					}
369*5331Samw 				}
370*5331Samw 			}
371*5331Samw 		}
372*5331Samw 		if (stack_trace && node.n_audit_buf) {
373*5331Samw 			int ctr;
374*5331Samw 			smb_audit_buf_node_t *anb;
375*5331Samw 
376*5331Samw 			anb = mdb_alloc(sizeof (smb_audit_buf_node_t),
377*5331Samw 			    UM_SLEEP);
378*5331Samw 
379*5331Samw 			if (mdb_vread(anb, sizeof (*anb),
380*5331Samw 			    (uintptr_t)node.n_audit_buf) != sizeof (*anb)) {
381*5331Samw 				mdb_free(anb, sizeof (smb_audit_buf_node_t));
382*5331Samw 				mdb_warn("failed to read audit buffer");
383*5331Samw 				return (DCMD_ERR);
384*5331Samw 			}
385*5331Samw 			ctr = anb->anb_max_index + 1;
386*5331Samw 			anb->anb_index--;
387*5331Samw 			anb->anb_index &= anb->anb_max_index;
388*5331Samw 
389*5331Samw 			while (ctr) {
390*5331Samw 				smb_audit_record_node_t	*anr;
391*5331Samw 
392*5331Samw 				anr = anb->anb_records + anb->anb_index;
393*5331Samw 
394*5331Samw 				if (anr->anr_depth) {
395*5331Samw 					char c[MDB_SYM_NAMLEN];
396*5331Samw 					GElf_Sym sym;
397*5331Samw 					int i;
398*5331Samw 
399*5331Samw 					mdb_printf("\nRefCnt: %u\t",
400*5331Samw 					    anr->anr_refcnt);
401*5331Samw 
402*5331Samw 					for (i = 0;
403*5331Samw 					    i < anr->anr_depth;
404*5331Samw 					    i++) {
405*5331Samw 						if (mdb_lookup_by_addr(
406*5331Samw 						    anr->anr_stack[i],
407*5331Samw 						    MDB_SYM_FUZZY,
408*5331Samw 						    c, sizeof (c),
409*5331Samw 						    &sym) == -1) {
410*5331Samw 							continue;
411*5331Samw 						}
412*5331Samw 						mdb_printf("%s+0x%1x",
413*5331Samw 						    c,
414*5331Samw 						    anr->anr_stack[i] -
415*5331Samw 						    (uintptr_t)sym.st_value);
416*5331Samw 						++i;
417*5331Samw 						break;
418*5331Samw 					}
419*5331Samw 
420*5331Samw 					while (i < anr->anr_depth) {
421*5331Samw 						if (mdb_lookup_by_addr(
422*5331Samw 						    anr->anr_stack[i],
423*5331Samw 						    MDB_SYM_FUZZY,
424*5331Samw 						    c, sizeof (c),
425*5331Samw 						    &sym) == -1) {
426*5331Samw 							++i;
427*5331Samw 							continue;
428*5331Samw 						}
429*5331Samw 						mdb_printf("\n\t\t%s+0x%1x",
430*5331Samw 						    c,
431*5331Samw 						    anr->anr_stack[i] -
432*5331Samw 						    (uintptr_t)sym.st_value);
433*5331Samw 						++i;
434*5331Samw 					}
435*5331Samw 					mdb_printf("\n");
436*5331Samw 				}
437*5331Samw 				anb->anb_index--;
438*5331Samw 				anb->anb_index &= anb->anb_max_index;
439*5331Samw 				ctr--;
440*5331Samw 			}
441*5331Samw 			mdb_free(anb, sizeof (smb_audit_buf_node_t));
442*5331Samw 		}
443*5331Samw 	} else {
444*5331Samw 		mdb_warn("failed to read struct smb_node at %p", addr);
445*5331Samw 		return (DCMD_ERR);
446*5331Samw 	}
447*5331Samw 
448*5331Samw 	return (DCMD_OK);
449*5331Samw }
450*5331Samw 
451*5331Samw static void
452*5331Samw smb_session_help(void)
453*5331Samw {
454*5331Samw 	mdb_printf(
455*5331Samw 	    "Display the contents of smb_session_t, with optional"
456*5331Samw 	    " filtering.\n\n");
457*5331Samw 	mdb_dec_indent(2);
458*5331Samw 	mdb_printf("%<b>OPTIONS%</b>\n");
459*5331Samw 	mdb_inc_indent(2);
460*5331Samw 	mdb_printf(
461*5331Samw 	    "-v\tDisplay verbose smb_session information\n"
462*5331Samw 	    "-r\tDisplay the list of smb requests attached\n"
463*5331Samw 	    "-u\tDisplay the list of users attached\n");
464*5331Samw }
465*5331Samw 
466*5331Samw /*
467*5331Samw  * ::smb_session
468*5331Samw  *
469*5331Samw  * smb_session dcmd - Print out the smb_session structure.
470*5331Samw  */
471*5331Samw /*ARGSUSED*/
472*5331Samw static int
473*5331Samw smb_session(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
474*5331Samw {
475*5331Samw 	smb_session_t	session;
476*5331Samw 	int		print_requests = FALSE;
477*5331Samw 	int		print_users = FALSE;
478*5331Samw 	int		verbose = FALSE;
479*5331Samw 	uintptr_t	list_addr;
480*5331Samw 
481*5331Samw 	if (mdb_getopts(argc, argv,
482*5331Samw 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
483*5331Samw 	    'r', MDB_OPT_SETBITS, TRUE, &print_requests,
484*5331Samw 	    'u', MDB_OPT_SETBITS, TRUE, &print_users,
485*5331Samw 	    NULL) != argc)
486*5331Samw 		return (DCMD_USAGE);
487*5331Samw 
488*5331Samw 	/*
489*5331Samw 	 * If no smb_session address was specified on the command line, we can
490*5331Samw 	 * print out all smb sessions by invoking the smb_session walker, using
491*5331Samw 	 * this dcmd itself as the callback.
492*5331Samw 	 */
493*5331Samw 	if (!(flags & DCMD_ADDRSPEC)) {
494*5331Samw 		if (mdb_walk_dcmd("smb_session", "smb_session",
495*5331Samw 		    argc, argv) == -1) {
496*5331Samw 			mdb_warn("failed to walk 'smb_session'");
497*5331Samw 			return (DCMD_ERR);
498*5331Samw 		}
499*5331Samw 		return (DCMD_OK);
500*5331Samw 	}
501*5331Samw 
502*5331Samw 	/*
503*5331Samw 	 * If this is the first invocation of the command, print a nice
504*5331Samw 	 * header line for the output that will follow.
505*5331Samw 	 */
506*5331Samw 	if (DCMD_HDRSPEC(flags)) {
507*5331Samw 		if (verbose)
508*5331Samw 			mdb_printf("SMB session information:\n\n");
509*5331Samw 		else
510*5331Samw 			mdb_printf("%<u>%-?s %16s %16s %5s %10s%</u>\n",
511*5331Samw 			    "Sessions:", "CLIENT_IP_ADDR", "LOCAL_IP_ADDR",
512*5331Samw 			    "KID", "STATE");
513*5331Samw 	}
514*5331Samw 
515*5331Samw 	/*
516*5331Samw 	 * For each smb_session, we just need to read the smb_session_t struct,
517*5331Samw 	 * read and then print out the following fields.
518*5331Samw 	 */
519*5331Samw 	if (mdb_vread(&session, sizeof (session), addr) == sizeof (session)) {
520*5331Samw 		if (verbose) {
521*5331Samw 			mdb_printf("IP address      :\t%I\n",
522*5331Samw 			    session.ipaddr);
523*5331Samw 			mdb_printf("Local IP Address:\t%I\n",
524*5331Samw 			    session.local_ipaddr);
525*5331Samw 			mdb_printf("Session KID     :\t%u\n",
526*5331Samw 			    session.s_kid);
527*5331Samw 			mdb_printf("Workstation Name:\t%s\n",
528*5331Samw 			    session.workstation);
529*5331Samw 			mdb_printf("Session state   :\t%u\n",
530*5331Samw 			    session.s_state);
531*5331Samw 			mdb_printf("users           :\t%u\n",
532*5331Samw 			    session.s_user_list.ll_count);
533*5331Samw 			mdb_printf("trees           :\t%u\n",
534*5331Samw 			    session.s_tree_cnt);
535*5331Samw 			mdb_printf("files           :\t%u\n",
536*5331Samw 			    session.s_file_cnt);
537*5331Samw 			mdb_printf("shares          :\t%u\n",
538*5331Samw 			    session.s_dir_cnt);
539*5331Samw 			mdb_printf("xa count        :\t%u\n\n",
540*5331Samw 			    session.s_xa_list.ll_count);
541*5331Samw 			mdb_printf("\n");
542*5331Samw 		} else {
543*5331Samw 			mdb_printf("%?p %16I %16I %5u %10u\n", addr,
544*5331Samw 			    session.ipaddr, session.local_ipaddr,
545*5331Samw 			    session.s_kid, session.s_state);
546*5331Samw 		}
547*5331Samw 	} else {
548*5331Samw 		mdb_warn("failed to read struct smb_session at %p", &session);
549*5331Samw 		return (DCMD_ERR);
550*5331Samw 	}
551*5331Samw 
552*5331Samw 	if (print_requests) {
553*5331Samw 		(void) mdb_inc_indent(SMB_DCMD_INDENT);
554*5331Samw 		list_addr = addr + offsetof(smb_session_t, s_req_list) +
555*5331Samw 		    offsetof(smb_slist_t, sl_list);
556*5331Samw 		if (mdb_pwalk_dcmd("list", "smb_request", 0, NULL, list_addr)) {
557*5331Samw 			mdb_warn("failed to walk request list\n");
558*5331Samw 			(void) mdb_dec_indent(SMB_DCMD_INDENT);
559*5331Samw 			return (DCMD_ERR);
560*5331Samw 		}
561*5331Samw 		(void) mdb_dec_indent(SMB_DCMD_INDENT);
562*5331Samw 	}
563*5331Samw 
564*5331Samw 	if (print_users) {
565*5331Samw 		(void) mdb_inc_indent(SMB_DCMD_INDENT);
566*5331Samw 		list_addr = addr + offsetof(smb_session_t, s_user_list) +
567*5331Samw 		    offsetof(smb_llist_t, ll_list);
568*5331Samw 		if (mdb_pwalk_dcmd("list", "smb_user", 0, NULL, list_addr)) {
569*5331Samw 			mdb_warn("failed to walk user list\n");
570*5331Samw 			(void) mdb_dec_indent(SMB_DCMD_INDENT);
571*5331Samw 			return (DCMD_ERR);
572*5331Samw 		}
573*5331Samw 		(void) mdb_dec_indent(SMB_DCMD_INDENT);
574*5331Samw 	}
575*5331Samw 
576*5331Samw 	return (DCMD_OK);
577*5331Samw }
578*5331Samw 
579*5331Samw static int
580*5331Samw smb_request(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
581*5331Samw {
582*5331Samw 	smb_request_t	request;
583*5331Samw 	int		verbose = FALSE;
584*5331Samw 
585*5331Samw 	if (mdb_getopts(argc, argv,
586*5331Samw 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
587*5331Samw 	    NULL) != argc)
588*5331Samw 		return (DCMD_USAGE);
589*5331Samw 
590*5331Samw 	/*
591*5331Samw 	 * An smb_requets_t address must be specified.
592*5331Samw 	 */
593*5331Samw 	if (!(flags & DCMD_ADDRSPEC))
594*5331Samw 		return (DCMD_USAGE);
595*5331Samw 
596*5331Samw 	/*
597*5331Samw 	 * If this is the first invocation of the command, print a nice
598*5331Samw 	 * header line for the output that will follow.
599*5331Samw 	 */
600*5331Samw 	if (DCMD_HDRSPEC(flags)) {
601*5331Samw 		if (verbose)
602*5331Samw 			mdb_printf("SMB request information:\n\n");
603*5331Samw 		else
604*5331Samw 			mdb_printf("%<u>%-?s %4s %6s %4s %4s %4s %4s%</u>\n",
605*5331Samw 			    "Requests: ", "COM", "STATE",
606*5331Samw 			    "TID", "PID", "UID", "MID");
607*5331Samw 	}
608*5331Samw 
609*5331Samw 	if (mdb_vread(&request, sizeof (request), addr) == sizeof (request)) {
610*5331Samw 		if (verbose) {
611*5331Samw 			mdb_printf("First SMB COM    :\t%I\n",
612*5331Samw 			    request.first_smb_com);
613*5331Samw 			mdb_printf("State            :\t%I\n",
614*5331Samw 			    request.sr_state);
615*5331Samw 			mdb_printf("Tree ID          :\t%u\n",
616*5331Samw 			    request.smb_tid);
617*5331Samw 			mdb_printf("Process ID       :\t%u\n",
618*5331Samw 			    request.smb_pid);
619*5331Samw 			mdb_printf("User ID          :\t%u\n",
620*5331Samw 			    request.smb_uid);
621*5331Samw 			mdb_printf("Multiplex ID     :\t%u\n",
622*5331Samw 			    request.smb_mid);
623*5331Samw 			mdb_printf("\n");
624*5331Samw 		} else {
625*5331Samw 			mdb_printf("%?p %04x %6x %04x %04x %04x"
626*5331Samw 			    " %04x\n", addr,
627*5331Samw 			    request.first_smb_com, request.sr_state,
628*5331Samw 			    request.smb_tid, request.smb_pid,
629*5331Samw 			    request.smb_uid, request.smb_mid);
630*5331Samw 		}
631*5331Samw 	} else {
632*5331Samw 		mdb_warn("failed to read struct smb_request at %p", addr);
633*5331Samw 		return (DCMD_ERR);
634*5331Samw 	}
635*5331Samw 
636*5331Samw 	return (DCMD_OK);
637*5331Samw }
638*5331Samw 
639*5331Samw static int
640*5331Samw smb_lock(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
641*5331Samw {
642*5331Samw 	smb_lock_t	lock;
643*5331Samw 	int		verbose = FALSE;
644*5331Samw 	uintptr_t	list_addr;
645*5331Samw 	char		*lock_type;
646*5331Samw 
647*5331Samw 	if (mdb_getopts(argc, argv,
648*5331Samw 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
649*5331Samw 	    NULL) != argc)
650*5331Samw 		return (DCMD_USAGE);
651*5331Samw 
652*5331Samw 	/*
653*5331Samw 	 * An smb_lock_t address must be specified.
654*5331Samw 	 */
655*5331Samw 	if (!(flags & DCMD_ADDRSPEC))
656*5331Samw 		return (DCMD_USAGE);
657*5331Samw 
658*5331Samw 	/*
659*5331Samw 	 * If this is the first invocation of the command, print a nice
660*5331Samw 	 * header line for the output that will follow.
661*5331Samw 	 */
662*5331Samw 	if (DCMD_HDRSPEC(flags)) {
663*5331Samw 		if (verbose)
664*5331Samw 			mdb_printf("SMB lock information:\n\n");
665*5331Samw 		else
666*5331Samw 			mdb_printf("%<u>%-?s %4s %16s %8s %9s%</u>\n",
667*5331Samw 			    "Locks: ", "TYPE", "START", "LENGTH",
668*5331Samw 			    "CONFLICTS");
669*5331Samw 	}
670*5331Samw 
671*5331Samw 	if (mdb_vread(&lock, sizeof (lock), addr) == sizeof (lock)) {
672*5331Samw 		switch (lock.l_type) {
673*5331Samw 		case SMB_LOCK_TYPE_READWRITE:
674*5331Samw 			lock_type = "RW";
675*5331Samw 			break;
676*5331Samw 		case SMB_LOCK_TYPE_READONLY:
677*5331Samw 			lock_type = "RO";
678*5331Samw 			break;
679*5331Samw 		default:
680*5331Samw 			lock_type = "N/A";
681*5331Samw 			break;
682*5331Samw 		}
683*5331Samw 		if (verbose) {
684*5331Samw 			mdb_printf("Type             :\t%s (%u)\n",
685*5331Samw 			    lock_type, lock.l_type);
686*5331Samw 			mdb_printf("Start            :\t%llx\n",
687*5331Samw 			    lock.l_start);
688*5331Samw 			mdb_printf("Length           :\t%lx\n",
689*5331Samw 			    lock.l_length);
690*5331Samw 			mdb_printf("Session          :\t%p\n",
691*5331Samw 			    lock.l_session);
692*5331Samw 			mdb_printf("File             :\t%p\n",
693*5331Samw 			    lock.l_file);
694*5331Samw 			mdb_printf("User ID          :\t%u\n",
695*5331Samw 			    lock.l_uid);
696*5331Samw 			mdb_printf("Process ID       :\t%u\n",
697*5331Samw 			    lock.l_pid);
698*5331Samw 			mdb_printf("Conflicts        :\t%u\n",
699*5331Samw 			    lock.l_conflict_list.sl_count);
700*5331Samw 			if (lock.l_conflict_list.sl_count != 0) {
701*5331Samw 				(void) mdb_inc_indent(SMB_DCMD_INDENT);
702*5331Samw 				list_addr = addr +
703*5331Samw 				    offsetof(smb_lock_t, l_conflict_list) +
704*5331Samw 				    offsetof(smb_slist_t, sl_list);
705*5331Samw 				if (mdb_pwalk_dcmd("list", "smb_lock",
706*5331Samw 				    0, NULL, list_addr)) {
707*5331Samw 					mdb_warn("failed to walk conflict "
708*5331Samw 					    "locks ");
709*5331Samw 				}
710*5331Samw 				(void) mdb_dec_indent(SMB_DCMD_INDENT);
711*5331Samw 			}
712*5331Samw 			mdb_printf("Blocked by       :\t%p\n",
713*5331Samw 			    lock.l_blocked_by);
714*5331Samw 			mdb_printf("Flags            :\t0x%x\n",
715*5331Samw 			    lock.l_flags);
716*5331Samw 			mdb_printf("\n");
717*5331Samw 		} else {
718*5331Samw 			mdb_printf("%?p %4s %16llx %08lx %9x", addr,
719*5331Samw 			    lock_type, lock.l_start, lock.l_length,
720*5331Samw 			    lock.l_conflict_list.sl_count);
721*5331Samw 		}
722*5331Samw 	} else {
723*5331Samw 		mdb_warn("failed to read struct smb_request at %p", addr);
724*5331Samw 		return (DCMD_ERR);
725*5331Samw 	}
726*5331Samw 
727*5331Samw 	return (DCMD_OK);
728*5331Samw }
729*5331Samw 
730*5331Samw static void
731*5331Samw smb_user_help(void)
732*5331Samw {
733*5331Samw 	mdb_printf(
734*5331Samw 	    "Display the contents of smb_user_t, with optional filtering.\n\n");
735*5331Samw 	mdb_dec_indent(2);
736*5331Samw 	mdb_printf("%<b>OPTIONS%</b>\n");
737*5331Samw 	mdb_inc_indent(2);
738*5331Samw 	mdb_printf(
739*5331Samw 	    "-v\tDisplay verbose smb_user information\n"
740*5331Samw 	    "-q\tDon't Display the contents of the smb_user. This option "
741*5331Samw 	    "should be\n\tused in conjunction with -d or -f\n"
742*5331Samw 	    "-d\tDisplay the list of smb_odirs attached\n"
743*5331Samw 	    "-f\tDisplay the list of smb_ofiles attached\n"
744*5331Samw 	    "-t\tDisplay the list of smb_trees attached\n");
745*5331Samw }
746*5331Samw 
747*5331Samw static int
748*5331Samw smb_user(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
749*5331Samw {
750*5331Samw 	smb_user_t	user;
751*5331Samw 	int		print_odir = FALSE;
752*5331Samw 	int		print_ofile = FALSE;
753*5331Samw 	int		print_tree = FALSE;
754*5331Samw 	int		verbose = FALSE;
755*5331Samw 	int		quiet = FALSE;
756*5331Samw 	uintptr_t	list_addr;
757*5331Samw 	int		new_argc;
758*5331Samw 	mdb_arg_t	new_argv[3];
759*5331Samw 
760*5331Samw 	if (mdb_getopts(argc, argv,
761*5331Samw 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
762*5331Samw 	    'q', MDB_OPT_SETBITS, TRUE, &quiet,
763*5331Samw 	    'd', MDB_OPT_SETBITS, TRUE, &print_odir,
764*5331Samw 	    'f', MDB_OPT_SETBITS, TRUE, &print_ofile,
765*5331Samw 	    't', MDB_OPT_SETBITS, TRUE, &print_tree,
766*5331Samw 	    NULL) != argc)
767*5331Samw 		return (DCMD_USAGE);
768*5331Samw 
769*5331Samw 	/*
770*5331Samw 	 * An smb_user address must be specified on the command line.
771*5331Samw 	 */
772*5331Samw 	if (!(flags & DCMD_ADDRSPEC))
773*5331Samw 		return (DCMD_USAGE);
774*5331Samw 
775*5331Samw 	/*
776*5331Samw 	 * If this is the first invocation of the command, print a nice
777*5331Samw 	 * header line for the output that will follow.
778*5331Samw 	 */
779*5331Samw 	if (DCMD_HDRSPEC(flags) && !quiet) {
780*5331Samw 		if (verbose)
781*5331Samw 			mdb_printf("SMB user information:\n\n");
782*5331Samw 		else
783*5331Samw 			mdb_printf("%<u>%-?s %4s %6s %8s %16s %8s   %s%</u>\n",
784*5331Samw 			    "Users:", "UID", "STATE", "FLAGS", "CRED",
785*5331Samw 			    "REFCNT", "ACCOUNT");
786*5331Samw 	}
787*5331Samw 
788*5331Samw 	if (mdb_vread(&user, sizeof (user), addr) !=  sizeof (user)) {
789*5331Samw 		mdb_warn("failed to read struct smb_user at %?p", addr);
790*5331Samw 		return (DCMD_ERR);
791*5331Samw 	}
792*5331Samw 
793*5331Samw 	if (!quiet) {
794*5331Samw 		char domain[SMB_PI_MAX_DOMAIN];
795*5331Samw 		char account[SMB_PI_MAX_USERNAME];
796*5331Samw 		int valid_domain = 0, valid_account = 0;
797*5331Samw 
798*5331Samw 		if (mdb_vread(domain, user.u_domain_len,
799*5331Samw 		    (uintptr_t)user.u_domain) == user.u_domain_len)
800*5331Samw 			valid_domain = 1;
801*5331Samw 		if (mdb_vread(account, user.u_name_len,
802*5331Samw 		    (uintptr_t)user.u_name) == user.u_name_len)
803*5331Samw 			valid_account = 1;
804*5331Samw 
805*5331Samw 		if (verbose) {
806*5331Samw 			mdb_printf("User ID          :\t%04x\n",
807*5331Samw 			    user.u_uid);
808*5331Samw 			mdb_printf("State            :\t%d\n",
809*5331Samw 			    user.u_state);
810*5331Samw 			mdb_printf("Flags            :\t%08x\n",
811*5331Samw 			    user.u_flags);
812*5331Samw 			mdb_printf("Privileges       :\t%08x\n",
813*5331Samw 			    user.u_privileges);
814*5331Samw 			mdb_printf("Credential       :\t%llx\n",
815*5331Samw 			    user.u_cred);
816*5331Samw 			mdb_printf("Reference Count  :\t%d\n",
817*5331Samw 			    user.u_refcnt);
818*5331Samw 			if (valid_domain && valid_account)
819*5331Samw 				mdb_printf("User Account     :\t%s\\%s\n",
820*5331Samw 				    domain, account);
821*5331Samw 			mdb_printf("\n");
822*5331Samw 		} else {
823*5331Samw 			mdb_printf("%?p %04x %6d %08x %?p %8d   %s\\%s\n",
824*5331Samw 			    addr, user.u_uid, user.u_state, user.u_flags,
825*5331Samw 			    user.u_cred, user.u_refcnt,
826*5331Samw 			    valid_domain ? domain : "UNKNOWN",
827*5331Samw 			    valid_account ? account : "UNKNOWN");
828*5331Samw 		}
829*5331Samw 	}
830*5331Samw 
831*5331Samw 	new_argc = 0;
832*5331Samw 	if (!print_tree) {
833*5331Samw 		new_argv[new_argc].a_type = MDB_TYPE_STRING;
834*5331Samw 		new_argv[new_argc].a_un.a_str = "-q";
835*5331Samw 		new_argc++;
836*5331Samw 	}
837*5331Samw 	if (print_ofile) {
838*5331Samw 		new_argv[new_argc].a_type = MDB_TYPE_STRING;
839*5331Samw 		new_argv[new_argc].a_un.a_str = "-f";
840*5331Samw 		new_argc++;
841*5331Samw 	}
842*5331Samw 	if (print_odir) {
843*5331Samw 		new_argv[new_argc].a_type = MDB_TYPE_STRING;
844*5331Samw 		new_argv[new_argc].a_un.a_str = "-d";
845*5331Samw 		new_argc++;
846*5331Samw 	}
847*5331Samw 
848*5331Samw 	if (print_tree || print_ofile || print_odir) {
849*5331Samw 		(void) mdb_inc_indent(SMB_DCMD_INDENT);
850*5331Samw 		list_addr = addr + offsetof(smb_user_t, u_tree_list) +
851*5331Samw 		    offsetof(smb_llist_t, ll_list);
852*5331Samw 		if (mdb_pwalk_dcmd("list", "smb_tree", new_argc, new_argv,
853*5331Samw 		    list_addr)) {
854*5331Samw 			mdb_warn("failed to walk tree list\n");
855*5331Samw 			(void) mdb_dec_indent(SMB_DCMD_INDENT);
856*5331Samw 			return (DCMD_ERR);
857*5331Samw 		}
858*5331Samw 		(void) mdb_dec_indent(SMB_DCMD_INDENT);
859*5331Samw 	}
860*5331Samw 
861*5331Samw 	return (DCMD_OK);
862*5331Samw }
863*5331Samw 
864*5331Samw static void
865*5331Samw smb_tree_help(void)
866*5331Samw {
867*5331Samw 	mdb_printf(
868*5331Samw 	    "Display the contents of smb_tree_t, with optional filtering.\n\n");
869*5331Samw 	mdb_dec_indent(2);
870*5331Samw 	mdb_printf("%<b>OPTIONS%</b>\n");
871*5331Samw 	mdb_inc_indent(2);
872*5331Samw 	mdb_printf(
873*5331Samw 	    "-v\tDisplay verbose smb_tree information\n"
874*5331Samw 	    "-q\tDon't Display the contents of the smb_tree. This option "
875*5331Samw 	    "should be\n\tused in conjunction with -d or -f\n"
876*5331Samw 	    "-d\tDisplay the list of smb_odirs attached\n"
877*5331Samw 	    "-f\tDisplay the list of smb_ofiles attached\n");
878*5331Samw }
879*5331Samw 
880*5331Samw static int
881*5331Samw smb_tree(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
882*5331Samw {
883*5331Samw 	smb_tree_t	tree;
884*5331Samw 	int		print_odir = FALSE;
885*5331Samw 	int		print_ofile = FALSE;
886*5331Samw 	int		verbose = FALSE;
887*5331Samw 	int		quiet = FALSE;
888*5331Samw 	uintptr_t	list_addr;
889*5331Samw 
890*5331Samw 	if (mdb_getopts(argc, argv,
891*5331Samw 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
892*5331Samw 	    'd', MDB_OPT_SETBITS, TRUE, &print_odir,
893*5331Samw 	    'f', MDB_OPT_SETBITS, TRUE, &print_ofile,
894*5331Samw 	    'q', MDB_OPT_SETBITS, TRUE, &quiet,
895*5331Samw 	    NULL) != argc)
896*5331Samw 		return (DCMD_USAGE);
897*5331Samw 
898*5331Samw 	/*
899*5331Samw 	 * If no smb_session address was specified on the command line, we can
900*5331Samw 	 * print out all smb sessions by invoking the smb_session walker, using
901*5331Samw 	 * this dcmd itself as the callback.
902*5331Samw 	 */
903*5331Samw 	if (!(flags & DCMD_ADDRSPEC))
904*5331Samw 		return (DCMD_USAGE);
905*5331Samw 
906*5331Samw 	/*
907*5331Samw 	 * If this is the first invocation of the command, print a nice
908*5331Samw 	 * header line for the output that will follow.
909*5331Samw 	 */
910*5331Samw 	if (DCMD_HDRSPEC(flags)) {
911*5331Samw 		if (verbose)
912*5331Samw 			mdb_printf("SMB tree information:\n\n");
913*5331Samw 		else
914*5331Samw 			mdb_printf("%<u>%-?s %4s %6s %16s %10s%</u>\n",
915*5331Samw 			    "Trees:", "TID", "STATE", "SMB NODE",
916*5331Samw 			    "SHARE NAME");
917*5331Samw 	}
918*5331Samw 
919*5331Samw 	/*
920*5331Samw 	 * Read tree and print some of the fields
921*5331Samw 	 */
922*5331Samw 	if (mdb_vread(&tree, sizeof (tree), addr) != sizeof (tree)) {
923*5331Samw 		mdb_warn("failed to read struct smb_tree at %p", addr);
924*5331Samw 		return (DCMD_ERR);
925*5331Samw 	}
926*5331Samw 	if (!quiet) {
927*5331Samw 		if (verbose) {
928*5331Samw 			mdb_printf("Tree ID          :\t%04x\n",
929*5331Samw 			    tree.t_tid);
930*5331Samw 			mdb_printf("State            :\t%d\n",
931*5331Samw 			    tree.t_state);
932*5331Samw 			mdb_printf("Share name       :\t%s\n",
933*5331Samw 			    tree.t_sharename);
934*5331Samw 			mdb_printf("Resource         :\t%s\n",
935*5331Samw 			    tree.t_resource);
936*5331Samw 			mdb_printf("Umask            :\t%04x\n",
937*5331Samw 			    tree.t_umask);
938*5331Samw 			mdb_printf("Access           :\t%04x\n",
939*5331Samw 			    tree.t_access);
940*5331Samw 			mdb_printf("Flags            :\t%08x\n",
941*5331Samw 			    tree.t_flags);
942*5331Samw 			mdb_printf("SMB Node         :\t%llx\n",
943*5331Samw 			    tree.t_snode);
944*5331Samw 			mdb_printf("Reference Count  :\t%d\n",
945*5331Samw 			    tree.t_refcnt);
946*5331Samw 			mdb_printf("\n");
947*5331Samw 		} else {
948*5331Samw 			mdb_printf("%?p %04x %6d %16llx %s\n", addr,
949*5331Samw 			    tree.t_tid, tree.t_state, tree.t_snode,
950*5331Samw 			    tree.t_sharename);
951*5331Samw 		}
952*5331Samw 	}
953*5331Samw 
954*5331Samw 	if (print_odir) {
955*5331Samw 		(void) mdb_inc_indent(SMB_DCMD_INDENT);
956*5331Samw 		list_addr = addr + offsetof(smb_tree_t, t_odir_list) +
957*5331Samw 		    offsetof(smb_llist_t, ll_list);
958*5331Samw 		if (mdb_pwalk_dcmd("list", "smb_odir", 0, NULL, list_addr)) {
959*5331Samw 			mdb_warn("failed to walk odir list\n");
960*5331Samw 			(void) mdb_dec_indent(SMB_DCMD_INDENT);
961*5331Samw 			return (DCMD_ERR);
962*5331Samw 		}
963*5331Samw 		(void) mdb_dec_indent(SMB_DCMD_INDENT);
964*5331Samw 	}
965*5331Samw 
966*5331Samw 	if (print_ofile) {
967*5331Samw 		(void) mdb_inc_indent(SMB_DCMD_INDENT);
968*5331Samw 		list_addr = addr + offsetof(smb_tree_t, t_ofile_list) +
969*5331Samw 		    offsetof(smb_llist_t, ll_list);
970*5331Samw 		if (mdb_pwalk_dcmd("list", "smb_ofile", 0, NULL, list_addr)) {
971*5331Samw 			mdb_warn("failed to walk ofile list\n");
972*5331Samw 			(void) mdb_dec_indent(SMB_DCMD_INDENT);
973*5331Samw 			return (DCMD_ERR);
974*5331Samw 		}
975*5331Samw 		(void) mdb_dec_indent(SMB_DCMD_INDENT);
976*5331Samw 	}
977*5331Samw 
978*5331Samw 	return (DCMD_OK);
979*5331Samw }
980*5331Samw 
981*5331Samw static int
982*5331Samw smb_odir(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
983*5331Samw {
984*5331Samw 	smb_odir_t	odir;
985*5331Samw 	int		verbose = FALSE;
986*5331Samw 
987*5331Samw 	if (mdb_getopts(argc, argv,
988*5331Samw 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
989*5331Samw 	    NULL) != argc)
990*5331Samw 		return (DCMD_USAGE);
991*5331Samw 
992*5331Samw 	/*
993*5331Samw 	 * If no smb_session address was specified on the command line, we can
994*5331Samw 	 * print out all smb sessions by invoking the smb_session walker, using
995*5331Samw 	 * this dcmd itself as the callback.
996*5331Samw 	 */
997*5331Samw 	if (!(flags & DCMD_ADDRSPEC))
998*5331Samw 		return (DCMD_USAGE);
999*5331Samw 
1000*5331Samw 	/*
1001*5331Samw 	 * If this is the first invocation of the command, print a nice
1002*5331Samw 	 * header line for the output that will follow.
1003*5331Samw 	 */
1004*5331Samw 	if (DCMD_HDRSPEC(flags)) {
1005*5331Samw 		if (verbose)
1006*5331Samw 			mdb_printf("SMB odir information:\n\n");
1007*5331Samw 		else
1008*5331Samw 			mdb_printf("%<u>%-?s %8s %?s %10s%</u>\n",
1009*5331Samw 			    "odir:", "STATE", "SMB NODE", "PATTERN");
1010*5331Samw 	}
1011*5331Samw 
1012*5331Samw 	/*
1013*5331Samw 	 * For each smb_session, we just need to read the smb_session_t struct,
1014*5331Samw 	 * read and then print out the following fields.
1015*5331Samw 	 */
1016*5331Samw 	if (mdb_vread(&odir, sizeof (odir), addr) == sizeof (odir)) {
1017*5331Samw 		if (verbose) {
1018*5331Samw 			mdb_printf("State            :\t%d\n",
1019*5331Samw 			    odir.d_state);
1020*5331Samw 			mdb_printf("Pattern          :\t%s\n",
1021*5331Samw 			    odir.d_pattern);
1022*5331Samw 			mdb_printf("SMB Node         :\t%s\n",
1023*5331Samw 			    odir.d_dir_snode);
1024*5331Samw 			mdb_printf("\n");
1025*5331Samw 		} else {
1026*5331Samw 			mdb_printf("%?p %8d %16llx %s\n", addr,
1027*5331Samw 			    odir.d_state, odir.d_dir_snode, odir.d_pattern);
1028*5331Samw 		}
1029*5331Samw 	} else {
1030*5331Samw 		mdb_warn("failed to read struct smb_odir at %p", addr);
1031*5331Samw 		return (DCMD_ERR);
1032*5331Samw 	}
1033*5331Samw 
1034*5331Samw 	return (DCMD_OK);
1035*5331Samw }
1036*5331Samw 
1037*5331Samw static int
1038*5331Samw smb_ofile(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1039*5331Samw {
1040*5331Samw 	smb_ofile_t ofile;
1041*5331Samw 	int verbose = FALSE;
1042*5331Samw 
1043*5331Samw 	if (mdb_getopts(argc, argv,
1044*5331Samw 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
1045*5331Samw 	    NULL) != argc)
1046*5331Samw 		return (DCMD_USAGE);
1047*5331Samw 
1048*5331Samw 	/*
1049*5331Samw 	 * If no smb_session address was specified on the command line, we can
1050*5331Samw 	 * print out all smb sessions by invoking the smb_session walker, using
1051*5331Samw 	 * this dcmd itself as the callback.
1052*5331Samw 	 */
1053*5331Samw 	if (!(flags & DCMD_ADDRSPEC))
1054*5331Samw 		return (DCMD_USAGE);
1055*5331Samw 
1056*5331Samw 	/*
1057*5331Samw 	 * If this is the first invocation of the command, print a nice
1058*5331Samw 	 * header line for the output that will follow.
1059*5331Samw 	 */
1060*5331Samw 	if (DCMD_HDRSPEC(flags)) {
1061*5331Samw 		if (verbose)
1062*5331Samw 			mdb_printf("SMB ofile information:\n\n");
1063*5331Samw 		else
1064*5331Samw 			mdb_printf("%<u>%-?s %04s %8s %?s %8s %?s%</u>\n",
1065*5331Samw 			    "ofiles:", "FID", "STATE", "SMB NODE", "FLAGS",
1066*5331Samw 			    "CRED");
1067*5331Samw 	}
1068*5331Samw 
1069*5331Samw 	/*
1070*5331Samw 	 * For each smb_session, we just need to read the smb_session_t struct,
1071*5331Samw 	 * read and then print out the following fields.
1072*5331Samw 	 */
1073*5331Samw 	if (mdb_vread(&ofile, sizeof (ofile), addr) == sizeof (ofile)) {
1074*5331Samw 		if (verbose) {
1075*5331Samw 			mdb_printf("Ofile ID         :\t%04x\n",
1076*5331Samw 			    ofile.f_fid);
1077*5331Samw 			mdb_printf("State            :\t%d\n",
1078*5331Samw 			    ofile.f_state);
1079*5331Samw 			mdb_printf("SMB Node         :\t%llx\n",
1080*5331Samw 			    ofile.f_node);
1081*5331Samw 			mdb_printf("LLF Offset       :\t%llx (%s)\n",
1082*5331Samw 			    ofile.f_llf_pos,
1083*5331Samw 			    ((ofile.f_flags & SMB_OFLAGS_LLF_POS_VALID) ?
1084*5331Samw 			    "Valid" : "Invalid"));
1085*5331Samw 			mdb_printf("FLAGS            :\t%08x\n",
1086*5331Samw 			    ofile.f_flags);
1087*5331Samw 			mdb_printf("Credential       :\t%llx\n",
1088*5331Samw 			    ofile.f_cr);
1089*5331Samw 			mdb_printf("\n");
1090*5331Samw 		} else {
1091*5331Samw 			mdb_printf("%?p %04x %8d %16llx %08x %?\n", addr,
1092*5331Samw 			    ofile.f_fid, ofile.f_state, ofile.f_node,
1093*5331Samw 			    ofile.f_flags, ofile.f_cr);
1094*5331Samw 		}
1095*5331Samw 	} else {
1096*5331Samw 		mdb_warn("failed to read struct smb_odir at %p", addr);
1097*5331Samw 		return (DCMD_ERR);
1098*5331Samw 	}
1099*5331Samw 
1100*5331Samw 	return (DCMD_OK);
1101*5331Samw }
1102*5331Samw 
1103*5331Samw 
1104*5331Samw /*
1105*5331Samw  * ::smb_dispatch_stats
1106*5331Samw  *
1107*5331Samw  * smb_dispatch_stats dcmd - Prints all dispatched SMB requests statistics.
1108*5331Samw  */
1109*5331Samw /*ARGSUSED*/
1110*5331Samw static int
1111*5331Samw smb_stats(uintptr_t addr, uint_t flags, int argc,
1112*5331Samw     const mdb_arg_t *argv)
1113*5331Samw {
1114*5331Samw 	smb_dispatch_table_t	*disp;
1115*5331Samw 	GElf_Sym		sym;
1116*5331Samw 	int			nstats = 0, i;
1117*5331Samw 
1118*5331Samw 	if ((flags & DCMD_ADDRSPEC) || argc != 0)
1119*5331Samw 		return (DCMD_USAGE);
1120*5331Samw 
1121*5331Samw 	if (mdb_lookup_by_obj(MDB_OBJ_EVERY, "dispatch", &sym)) {
1122*5331Samw 		mdb_warn("failed to find dispatch object");
1123*5331Samw 		return (DCMD_ERR);
1124*5331Samw 	}
1125*5331Samw 
1126*5331Samw 	disp = mdb_alloc(sym.st_size, UM_SLEEP | UM_GC);
1127*5331Samw 	if (mdb_vread(disp, sym.st_size, sym.st_value) == -1) {
1128*5331Samw 		mdb_warn("failed to read from dispatch object");
1129*5331Samw 		return (DCMD_ERR);
1130*5331Samw 	}
1131*5331Samw 
1132*5331Samw 	nstats = sym.st_size / sizeof (smb_dispatch_table_t);
1133*5331Samw 
1134*5331Samw 	mdb_printf("All dispatched SMB requests statistics:\n\n");
1135*5331Samw 	for (i = 0; i < nstats; i++) {
1136*5331Samw 		if (disp[i].sdt_function)
1137*5331Samw 			mdb_printf("    %40s\t: %lld\n",
1138*5331Samw 			    disp[i].sdt_dispatch_stats.name,
1139*5331Samw 			    disp[i].sdt_dispatch_stats.value.ui64);
1140*5331Samw 	}
1141*5331Samw 	return (DCMD_OK);
1142*5331Samw }
1143*5331Samw 
1144*5331Samw /*
1145*5331Samw  * MDB module linkage information:
1146*5331Samw  *
1147*5331Samw  * We declare a list of structures describing our dcmds, a list of structures
1148*5331Samw  * describing our walkers and a function named _mdb_init to return a pointer
1149*5331Samw  * to our module information.
1150*5331Samw  */
1151*5331Samw static const mdb_dcmd_t dcmds[] = {
1152*5331Samw 	{   "smb_info", "[-c]",
1153*5331Samw 	    "print smb_info information", smb_information },
1154*5331Samw 	{   "smb_node", "?[-vps]",
1155*5331Samw 	    "print smb_node_t information", smb_node, smb_node_help },
1156*5331Samw 	{   "smb_session", "?[-vru]",
1157*5331Samw 	    "print smb_session_t information", smb_session, smb_session_help},
1158*5331Samw 	{   "smb_request", ":[-v]",
1159*5331Samw 	    "print smb_request_t information", smb_request },
1160*5331Samw 	{   "smb_lock", ":[-v]",
1161*5331Samw 	    "print smb_lock_t information", smb_lock },
1162*5331Samw 	{   "smb_user", ":[-vdftq]",
1163*5331Samw 	    "print smb_user_t information", smb_user, smb_user_help },
1164*5331Samw 	{   "smb_tree", ":[-vdfq]",
1165*5331Samw 	    "print smb_tree_t information", smb_tree, smb_tree_help },
1166*5331Samw 	{   "smb_odir", ":[-v]",
1167*5331Samw 	    "print smb_odir_t information", smb_odir },
1168*5331Samw 	{   "smb_ofile", "[-v]",
1169*5331Samw 	    "print smb_odir_t information", smb_ofile },
1170*5331Samw 	{   "smb_stats", NULL,
1171*5331Samw 	    "print all smb dispatched requests statistics",
1172*5331Samw 	    smb_stats },
1173*5331Samw 	{ NULL }
1174*5331Samw };
1175*5331Samw 
1176*5331Samw static const mdb_walker_t walkers[] = {
1177*5331Samw 	{  "smb_session", "walk list of smb_session_t structures",
1178*5331Samw 	    smb_session_walk_init, smb_session_walk_step,
1179*5331Samw 	    NULL },
1180*5331Samw 	{  "smb_node", "walk list of smb_node_t structures",
1181*5331Samw 	    smb_node_walk_init, smb_node_walk_step,
1182*5331Samw 	    NULL },
1183*5331Samw 	{ NULL }
1184*5331Samw };
1185*5331Samw 
1186*5331Samw static const mdb_modinfo_t modinfo = {
1187*5331Samw 	MDB_API_VERSION, dcmds, walkers
1188*5331Samw };
1189*5331Samw 
1190*5331Samw const mdb_modinfo_t *
1191*5331Samw _mdb_init(void)
1192*5331Samw {
1193*5331Samw 	return (&modinfo);
1194*5331Samw }
1195