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