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