14bff34e3Sthurlow /* 24bff34e3Sthurlow * CDDL HEADER START 34bff34e3Sthurlow * 44bff34e3Sthurlow * The contents of this file are subject to the terms of the 54bff34e3Sthurlow * Common Development and Distribution License (the "License"). 64bff34e3Sthurlow * You may not use this file except in compliance with the License. 74bff34e3Sthurlow * 84bff34e3Sthurlow * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94bff34e3Sthurlow * or http://www.opensolaris.org/os/licensing. 104bff34e3Sthurlow * See the License for the specific language governing permissions 114bff34e3Sthurlow * and limitations under the License. 124bff34e3Sthurlow * 134bff34e3Sthurlow * When distributing Covered Code, include this CDDL HEADER in each 144bff34e3Sthurlow * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154bff34e3Sthurlow * If applicable, add the following below this CDDL HEADER, with the 164bff34e3Sthurlow * fields enclosed by brackets "[]" replaced with your own identifying 174bff34e3Sthurlow * information: Portions Copyright [yyyy] [name of copyright owner] 184bff34e3Sthurlow * 194bff34e3Sthurlow * CDDL HEADER END 204bff34e3Sthurlow */ 214bff34e3Sthurlow 224bff34e3Sthurlow /* 23*430b4c46SGordon Ross * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 254bff34e3Sthurlow * Use is subject to license terms. 264bff34e3Sthurlow */ 274bff34e3Sthurlow 284bff34e3Sthurlow 294bff34e3Sthurlow #include <sys/mdb_modapi.h> 30613a2f6bSGordon Ross #include <mdb/mdb_ctf.h> 314bff34e3Sthurlow #include <sys/types.h> 32613a2f6bSGordon Ross #include <sys/socket.h> 334bff34e3Sthurlow 34*430b4c46SGordon Ross #include <netsmb/smb_conn.h> 35*430b4c46SGordon Ross #include <netsmb/smb_rq.h> 36*430b4c46SGordon Ross #include <netsmb/smb_pass.h> 374bff34e3Sthurlow 384bff34e3Sthurlow #define OPT_VERBOSE 0x0001 /* Be [-v]erbose in dcmd's */ 394bff34e3Sthurlow #define OPT_RECURSE 0x0002 /* recursive display */ 404bff34e3Sthurlow 414bff34e3Sthurlow /* 424bff34e3Sthurlow * We need to read in a private copy 434bff34e3Sthurlow * of every string we want to print out. 444bff34e3Sthurlow */ 454bff34e3Sthurlow void 464bff34e3Sthurlow print_str(uintptr_t addr) 474bff34e3Sthurlow { 484bff34e3Sthurlow char buf[32]; 494bff34e3Sthurlow int len, mx = sizeof (buf) - 4; 504bff34e3Sthurlow 514bff34e3Sthurlow if ((len = mdb_readstr(buf, sizeof (buf), addr)) <= 0) { 524bff34e3Sthurlow mdb_printf(" (%p)", addr); 534bff34e3Sthurlow } else { 544bff34e3Sthurlow if (len > mx) 554bff34e3Sthurlow strcpy(&buf[mx], "..."); 564bff34e3Sthurlow mdb_printf(" %s", buf); 574bff34e3Sthurlow } 584bff34e3Sthurlow } 594bff34e3Sthurlow 604bff34e3Sthurlow 614bff34e3Sthurlow /* 624bff34e3Sthurlow * Walker for smb_connobj_t structures, including 634bff34e3Sthurlow * smb_vc_t and smb_share_t which "inherit" from it. 644bff34e3Sthurlow * Tricky: Exploit the "inheritance" of smb_connobj_t 654bff34e3Sthurlow * with common functions for walk_init, walk_next. 664bff34e3Sthurlow */ 674bff34e3Sthurlow typedef struct smb_co_walk_data { 684bff34e3Sthurlow uintptr_t pp; 694bff34e3Sthurlow int level; /* SMBL_SM, SMBL_VC, SMBL_SHARE */ 704bff34e3Sthurlow int size; /* sizeof (union member) */ 714bff34e3Sthurlow union co_u { 724bff34e3Sthurlow smb_connobj_t co; /* copy of the list element */ 734bff34e3Sthurlow smb_vc_t vc; 744bff34e3Sthurlow smb_share_t ss; 754bff34e3Sthurlow } u; 764bff34e3Sthurlow } smb_co_walk_data_t; 774bff34e3Sthurlow 784bff34e3Sthurlow /* 794bff34e3Sthurlow * Common walk_init for walking structs inherited 804bff34e3Sthurlow * from smb_connobj_t (smb_vc_t, smb_share_t) 814bff34e3Sthurlow */ 824bff34e3Sthurlow int 834bff34e3Sthurlow smb_co_walk_init(mdb_walk_state_t *wsp, int level) 844bff34e3Sthurlow { 854bff34e3Sthurlow smb_co_walk_data_t *smbw; 864bff34e3Sthurlow size_t psz; 874bff34e3Sthurlow 884bff34e3Sthurlow if (wsp->walk_addr == NULL) 894bff34e3Sthurlow return (WALK_ERR); 904bff34e3Sthurlow 914bff34e3Sthurlow smbw = mdb_alloc(sizeof (*smbw), UM_SLEEP | UM_GC); 924bff34e3Sthurlow wsp->walk_data = smbw; 934bff34e3Sthurlow 944bff34e3Sthurlow /* 954bff34e3Sthurlow * Save the parent pointer for later checks, and 964bff34e3Sthurlow * the level so we know which union member it is. 974bff34e3Sthurlow * Also the size of this union member. 984bff34e3Sthurlow */ 994bff34e3Sthurlow smbw->pp = wsp->walk_addr; 1004bff34e3Sthurlow smbw->level = level; 1014bff34e3Sthurlow switch (level) { 1024bff34e3Sthurlow case SMBL_SM: 1034bff34e3Sthurlow smbw->size = sizeof (smbw->u.co); 1044bff34e3Sthurlow break; 1054bff34e3Sthurlow case SMBL_VC: 1064bff34e3Sthurlow smbw->size = sizeof (smbw->u.vc); 1074bff34e3Sthurlow break; 1084bff34e3Sthurlow case SMBL_SHARE: 1094bff34e3Sthurlow smbw->size = sizeof (smbw->u.ss); 1104bff34e3Sthurlow break; 1114bff34e3Sthurlow default: 1124bff34e3Sthurlow smbw->size = sizeof (smbw->u); 1134bff34e3Sthurlow break; 1144bff34e3Sthurlow } 1154bff34e3Sthurlow 1164bff34e3Sthurlow /* 1174bff34e3Sthurlow * Read in the parent object. Just need the 1184bff34e3Sthurlow * invariant part (smb_connobj_t) so we can 1194bff34e3Sthurlow * get the list of children below it. 1204bff34e3Sthurlow */ 1214bff34e3Sthurlow psz = sizeof (smbw->u.co); 1224bff34e3Sthurlow if (mdb_vread(&smbw->u.co, psz, smbw->pp) != psz) { 1234bff34e3Sthurlow mdb_warn("cannot read connobj from %p", smbw->pp); 1244bff34e3Sthurlow return (WALK_ERR); 1254bff34e3Sthurlow } 1264bff34e3Sthurlow 1274bff34e3Sthurlow /* 1284bff34e3Sthurlow * Finally, setup to walk the list of children. 1294bff34e3Sthurlow */ 1304bff34e3Sthurlow wsp->walk_addr = (uintptr_t)smbw->u.co.co_children.slh_first; 1314bff34e3Sthurlow 1324bff34e3Sthurlow return (WALK_NEXT); 1334bff34e3Sthurlow } 1344bff34e3Sthurlow 1354bff34e3Sthurlow /* 1364bff34e3Sthurlow * Walk the (global) VC list. 1374bff34e3Sthurlow */ 1384bff34e3Sthurlow int 1394bff34e3Sthurlow smb_vc_walk_init(mdb_walk_state_t *wsp) 1404bff34e3Sthurlow { 1414bff34e3Sthurlow GElf_Sym sym; 1424bff34e3Sthurlow 1434bff34e3Sthurlow if (wsp->walk_addr != NULL) { 1444bff34e3Sthurlow mdb_warn("::walk smb_vc only supports global walks\n"); 1454bff34e3Sthurlow return (WALK_ERR); 1464bff34e3Sthurlow } 1474bff34e3Sthurlow 1484bff34e3Sthurlow /* Locate the VC list head. */ 1494bff34e3Sthurlow if (mdb_lookup_by_obj("nsmb", "smb_vclist", &sym)) { 1504bff34e3Sthurlow mdb_warn("failed to lookup `smb_vclist'\n"); 1514bff34e3Sthurlow return (WALK_ERR); 1524bff34e3Sthurlow } 1534bff34e3Sthurlow wsp->walk_addr = sym.st_value; 1544bff34e3Sthurlow 1554bff34e3Sthurlow return (smb_co_walk_init(wsp, SMBL_VC)); 1564bff34e3Sthurlow } 1574bff34e3Sthurlow 1584bff34e3Sthurlow /* 1594bff34e3Sthurlow * Walk the share list below some VC. 1604bff34e3Sthurlow */ 1614bff34e3Sthurlow int 1624bff34e3Sthurlow smb_ss_walk_init(mdb_walk_state_t *wsp) 1634bff34e3Sthurlow { 1644bff34e3Sthurlow 1654bff34e3Sthurlow /* 1664bff34e3Sthurlow * Initial walk_addr is address of parent (VC) 1674bff34e3Sthurlow */ 1684bff34e3Sthurlow if (wsp->walk_addr == 0) { 1694bff34e3Sthurlow mdb_warn("::walk smb_ss does not support global walks\n"); 1704bff34e3Sthurlow return (WALK_ERR); 1714bff34e3Sthurlow } 1724bff34e3Sthurlow 1734bff34e3Sthurlow return (smb_co_walk_init(wsp, SMBL_SHARE)); 1744bff34e3Sthurlow } 1754bff34e3Sthurlow 1764bff34e3Sthurlow /* 1774bff34e3Sthurlow * Common walk_step for walking structs inherited 1784bff34e3Sthurlow * from smb_connobj_t (smb_vc_t, smb_share_t) 1794bff34e3Sthurlow */ 1804bff34e3Sthurlow int 1814bff34e3Sthurlow smb_co_walk_step(mdb_walk_state_t *wsp) 1824bff34e3Sthurlow { 1834bff34e3Sthurlow smb_co_walk_data_t *smbw = wsp->walk_data; 1844bff34e3Sthurlow int status; 1854bff34e3Sthurlow 1864bff34e3Sthurlow if (wsp->walk_addr == NULL) 1874bff34e3Sthurlow return (WALK_DONE); 1884bff34e3Sthurlow 1894bff34e3Sthurlow if (mdb_vread(&smbw->u, smbw->size, wsp->walk_addr) 1904bff34e3Sthurlow != smbw->size) { 1914bff34e3Sthurlow mdb_warn("cannot read connobj from %p", wsp->walk_addr); 1924bff34e3Sthurlow return (WALK_ERR); 1934bff34e3Sthurlow } 1944bff34e3Sthurlow 1954bff34e3Sthurlow /* XXX: Sanity check level? parent pointer? */ 1964bff34e3Sthurlow 1974bff34e3Sthurlow status = wsp->walk_callback(wsp->walk_addr, &smbw->u, 1984bff34e3Sthurlow wsp->walk_cbdata); 1994bff34e3Sthurlow 2004bff34e3Sthurlow wsp->walk_addr = (uintptr_t)smbw->u.co.co_next.sle_next; 2014bff34e3Sthurlow 2024bff34e3Sthurlow return (status); 2034bff34e3Sthurlow } 2044bff34e3Sthurlow 2054bff34e3Sthurlow 2064bff34e3Sthurlow /* 2074bff34e3Sthurlow * Dcmd (and callback function) to print a summary of 2084bff34e3Sthurlow * all VCs, and optionally all shares under each VC. 2094bff34e3Sthurlow */ 2104bff34e3Sthurlow 2114bff34e3Sthurlow typedef struct smb_co_cbdata { 2124bff34e3Sthurlow int flags; /* OPT_... */ 2134bff34e3Sthurlow int printed_header; 214613a2f6bSGordon Ross mdb_ctf_id_t ctf_id; 2154bff34e3Sthurlow } smb_co_cbdata_t; 2164bff34e3Sthurlow 2174bff34e3Sthurlow /* 2184bff34e3Sthurlow * Call-back function for walking a share list. 2194bff34e3Sthurlow */ 2204bff34e3Sthurlow int 2214bff34e3Sthurlow smb_ss_cb(uintptr_t addr, const void *data, void *arg) 2224bff34e3Sthurlow { 2234bff34e3Sthurlow const smb_share_t *ssp = data; 2244bff34e3Sthurlow smb_co_cbdata_t *cbd = arg; 2254bff34e3Sthurlow 226613a2f6bSGordon Ross mdb_printf(" %-p\t%s\n", addr, ssp->ss_name); 2274bff34e3Sthurlow 2284bff34e3Sthurlow if (cbd->flags & OPT_VERBOSE) { 2294bff34e3Sthurlow mdb_inc_indent(2); 2304bff34e3Sthurlow /* Anything wanted here? */ 2314bff34e3Sthurlow mdb_dec_indent(2); 2324bff34e3Sthurlow } 2334bff34e3Sthurlow 2344bff34e3Sthurlow return (WALK_NEXT); 2354bff34e3Sthurlow } 2364bff34e3Sthurlow 237613a2f6bSGordon Ross static const char * 238613a2f6bSGordon Ross vcstate_str(smb_co_cbdata_t *cbd, int stval) 239613a2f6bSGordon Ross { 240613a2f6bSGordon Ross static const char prefix[] = "SMBIOD_ST_"; 241613a2f6bSGordon Ross int prefix_len = sizeof (prefix) - 1; 242613a2f6bSGordon Ross mdb_ctf_id_t vcst_enum; 243613a2f6bSGordon Ross const char *cp; 244613a2f6bSGordon Ross 245613a2f6bSGordon Ross /* Got this in smb_vc_dcmd. */ 246613a2f6bSGordon Ross vcst_enum = cbd->ctf_id; 247613a2f6bSGordon Ross 248613a2f6bSGordon Ross /* Get the name for the enum value. */ 249613a2f6bSGordon Ross if ((cp = mdb_ctf_enum_name(vcst_enum, stval)) == NULL) 250613a2f6bSGordon Ross return ("?"); 251613a2f6bSGordon Ross 252613a2f6bSGordon Ross /* Skip the prefix part. */ 253613a2f6bSGordon Ross if (strncmp(cp, prefix, prefix_len) == 0) 254613a2f6bSGordon Ross cp += prefix_len; 255613a2f6bSGordon Ross 256613a2f6bSGordon Ross return (cp); 257613a2f6bSGordon Ross } 258613a2f6bSGordon Ross 2594bff34e3Sthurlow /* 2604bff34e3Sthurlow * Call-back function for walking the VC list. 2614bff34e3Sthurlow */ 2624bff34e3Sthurlow int 2634bff34e3Sthurlow smb_vc_cb(uintptr_t addr, const void *data, void *arg) 2644bff34e3Sthurlow { 2654bff34e3Sthurlow const smb_vc_t *vcp = data; 2664bff34e3Sthurlow smb_co_cbdata_t *cbd = arg; 2674bff34e3Sthurlow 2684bff34e3Sthurlow if (cbd->printed_header == 0) { 2694bff34e3Sthurlow cbd->printed_header = 1; 270613a2f6bSGordon Ross mdb_printf("// smb_vc_t uid server \tuser\t\tstate\n"); 2714bff34e3Sthurlow } 2724bff34e3Sthurlow 2734bff34e3Sthurlow mdb_printf("%-p", addr); 274613a2f6bSGordon Ross mdb_printf(" %7d", vcp->vc_owner); 275613a2f6bSGordon Ross 276613a2f6bSGordon Ross switch (vcp->vc_srvaddr.sa.sa_family) { 277613a2f6bSGordon Ross case AF_INET: 278613a2f6bSGordon Ross mdb_printf(" %I", vcp->vc_srvaddr.sin.sin_addr); 279613a2f6bSGordon Ross break; 280613a2f6bSGordon Ross case AF_INET6: 281613a2f6bSGordon Ross mdb_printf(" %N", &vcp->vc_srvaddr.sin6.sin6_addr); 282613a2f6bSGordon Ross break; 283613a2f6bSGordon Ross default: 284613a2f6bSGordon Ross mdb_printf(" %15s", "(bad af)"); 285613a2f6bSGordon Ross break; 286613a2f6bSGordon Ross } 287613a2f6bSGordon Ross 288613a2f6bSGordon Ross if (vcp->vc_username[0] != '\0') 289613a2f6bSGordon Ross mdb_printf("\t%s", vcp->vc_username); 290613a2f6bSGordon Ross else 291613a2f6bSGordon Ross mdb_printf("\t%s", "(?)"); 292613a2f6bSGordon Ross 293613a2f6bSGordon Ross if (vcp->vc_domain[0] != '\0') 294613a2f6bSGordon Ross mdb_printf("@%s", vcp->vc_domain); 295613a2f6bSGordon Ross 296613a2f6bSGordon Ross mdb_printf("\t%s\n", vcstate_str(cbd, vcp->vc_state)); 2974bff34e3Sthurlow 2984bff34e3Sthurlow if (cbd->flags & OPT_RECURSE) { 2994bff34e3Sthurlow mdb_inc_indent(2); 3004bff34e3Sthurlow if (mdb_pwalk("nsmb_ss", smb_ss_cb, cbd, addr) < 0) { 3014bff34e3Sthurlow mdb_warn("failed to walk 'nsmb_ss'"); 3024bff34e3Sthurlow /* Don't: return (WALK_ERR); */ 3034bff34e3Sthurlow } 3044bff34e3Sthurlow mdb_dec_indent(2); 3054bff34e3Sthurlow } 3064bff34e3Sthurlow 3074bff34e3Sthurlow return (WALK_NEXT); 3084bff34e3Sthurlow } 3094bff34e3Sthurlow 3104bff34e3Sthurlow int 3114bff34e3Sthurlow smb_vc_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3124bff34e3Sthurlow { 3134bff34e3Sthurlow smb_co_cbdata_t cbd; 3144bff34e3Sthurlow smb_vc_t *vcp; 3154bff34e3Sthurlow size_t vcsz; 3164bff34e3Sthurlow 3174bff34e3Sthurlow memset(&cbd, 0, sizeof (cbd)); 3184bff34e3Sthurlow 3194bff34e3Sthurlow if (mdb_getopts(argc, argv, 3204bff34e3Sthurlow 'r', MDB_OPT_SETBITS, OPT_RECURSE, &cbd.flags, 3214bff34e3Sthurlow 'v', MDB_OPT_SETBITS, OPT_VERBOSE, &cbd.flags, 3224bff34e3Sthurlow NULL) != argc) { 3234bff34e3Sthurlow return (DCMD_USAGE); 3244bff34e3Sthurlow } 3254bff34e3Sthurlow 326613a2f6bSGordon Ross if (mdb_ctf_lookup_by_name("enum smbiod_state", &cbd.ctf_id) == -1) { 327613a2f6bSGordon Ross mdb_warn("Could not find enum smbiod_state"); 328613a2f6bSGordon Ross } 329613a2f6bSGordon Ross 3304bff34e3Sthurlow if (!(flags & DCMD_ADDRSPEC)) { 3314bff34e3Sthurlow if (mdb_walk("nsmb_vc", smb_vc_cb, &cbd) == -1) { 3324bff34e3Sthurlow mdb_warn("failed to walk 'nsmb_vc'"); 3334bff34e3Sthurlow return (DCMD_ERR); 3344bff34e3Sthurlow } 3354bff34e3Sthurlow return (DCMD_OK); 3364bff34e3Sthurlow } 3374bff34e3Sthurlow 3384bff34e3Sthurlow vcsz = sizeof (*vcp); 3394bff34e3Sthurlow vcp = mdb_alloc(vcsz, UM_SLEEP | UM_GC); 3404bff34e3Sthurlow if (mdb_vread(vcp, vcsz, addr) != vcsz) { 3414bff34e3Sthurlow mdb_warn("cannot read VC from %p", addr); 3424bff34e3Sthurlow return (DCMD_ERR); 3434bff34e3Sthurlow } 3444bff34e3Sthurlow smb_vc_cb(addr, vcp, &cbd); 3454bff34e3Sthurlow 3464bff34e3Sthurlow return (DCMD_OK); 3474bff34e3Sthurlow } 3484bff34e3Sthurlow 3494bff34e3Sthurlow void 3504bff34e3Sthurlow smb_vc_help(void) 3514bff34e3Sthurlow { 3524bff34e3Sthurlow mdb_printf("Options:\n" 3534bff34e3Sthurlow " -r recursive display of share lists\n" 3544bff34e3Sthurlow " -v be verbose when displaying smb_vc\n"); 3554bff34e3Sthurlow } 3564bff34e3Sthurlow 3574bff34e3Sthurlow /* 3584bff34e3Sthurlow * Walker for the request list on a VC, 3594bff34e3Sthurlow * and dcmd to show a summary. 3604bff34e3Sthurlow */ 3614bff34e3Sthurlow int 3624bff34e3Sthurlow rqlist_walk_init(mdb_walk_state_t *wsp) 3634bff34e3Sthurlow { 3644bff34e3Sthurlow struct smb_rqhead rqh; 3654bff34e3Sthurlow uintptr_t addr; 3664bff34e3Sthurlow 3674bff34e3Sthurlow /* 3684bff34e3Sthurlow * Initial walk_addr is the address of the VC. 3694bff34e3Sthurlow * Add offsetof(iod_rqlist) to get the rqhead. 3704bff34e3Sthurlow */ 3714bff34e3Sthurlow if (wsp->walk_addr == 0) { 3724bff34e3Sthurlow mdb_warn("::walk smb_ss does not support global walks\n"); 3734bff34e3Sthurlow return (WALK_ERR); 3744bff34e3Sthurlow } 3754bff34e3Sthurlow addr = wsp->walk_addr; 3764bff34e3Sthurlow addr += OFFSETOF(smb_vc_t, iod_rqlist); 3774bff34e3Sthurlow 3784bff34e3Sthurlow if (mdb_vread(&rqh, sizeof (rqh), addr) == -1) { 3794bff34e3Sthurlow mdb_warn("failed to read smb_rqhead at %p", addr); 3804bff34e3Sthurlow return (WALK_ERR); 3814bff34e3Sthurlow } 3824bff34e3Sthurlow wsp->walk_addr = (uintptr_t)rqh.tqh_first; 3834bff34e3Sthurlow 3844bff34e3Sthurlow return (WALK_NEXT); 3854bff34e3Sthurlow } 3864bff34e3Sthurlow 3874bff34e3Sthurlow int 3884bff34e3Sthurlow rqlist_walk_step(mdb_walk_state_t *wsp) 3894bff34e3Sthurlow { 3904bff34e3Sthurlow smb_rq_t rq; 3914bff34e3Sthurlow int status; 3924bff34e3Sthurlow 3934bff34e3Sthurlow if (wsp->walk_addr == NULL) 3944bff34e3Sthurlow return (WALK_DONE); 3954bff34e3Sthurlow 3964bff34e3Sthurlow if (mdb_vread(&rq, sizeof (rq), wsp->walk_addr) == -1) { 3974bff34e3Sthurlow mdb_warn("cannot read smb_rq from %p", wsp->walk_addr); 3984bff34e3Sthurlow return (WALK_ERR); 3994bff34e3Sthurlow } 4004bff34e3Sthurlow 4014bff34e3Sthurlow status = wsp->walk_callback(wsp->walk_addr, &rq, 4024bff34e3Sthurlow wsp->walk_cbdata); 4034bff34e3Sthurlow 4044bff34e3Sthurlow wsp->walk_addr = (uintptr_t)rq.sr_link.tqe_next; 4054bff34e3Sthurlow 4064bff34e3Sthurlow return (status); 4074bff34e3Sthurlow } 4084bff34e3Sthurlow 4094bff34e3Sthurlow typedef struct rqlist_cbdata { 4104bff34e3Sthurlow int printed_header; 4114bff34e3Sthurlow uintptr_t uid; /* optional filtering by UID */ 4124bff34e3Sthurlow } rqlist_cbdata_t; 4134bff34e3Sthurlow 4144bff34e3Sthurlow int 4154bff34e3Sthurlow rqlist_cb(uintptr_t addr, const void *data, void *arg) 4164bff34e3Sthurlow { 4174bff34e3Sthurlow const smb_rq_t *rq = data; 4184bff34e3Sthurlow rqlist_cbdata_t *cbd = arg; 4194bff34e3Sthurlow 4204bff34e3Sthurlow if (cbd->printed_header == 0) { 4214bff34e3Sthurlow cbd->printed_header = 1; 4224bff34e3Sthurlow mdb_printf("// smb_rq_t MID cmd sr_state sr_flags\n"); 4234bff34e3Sthurlow } 4244bff34e3Sthurlow 4254bff34e3Sthurlow mdb_printf(" %-p", addr); /* smb_rq_t */ 4264bff34e3Sthurlow mdb_printf(" x%04x", rq->sr_mid); 4274bff34e3Sthurlow mdb_printf(" x%02x", rq->sr_cmd); 4284bff34e3Sthurlow mdb_printf(" %d", rq->sr_state); 4294bff34e3Sthurlow mdb_printf(" x%x", rq->sr_flags); 4304bff34e3Sthurlow mdb_printf("\n"); 4314bff34e3Sthurlow 4324bff34e3Sthurlow return (WALK_NEXT); 4334bff34e3Sthurlow } 4344bff34e3Sthurlow 4354bff34e3Sthurlow /*ARGSUSED*/ 4364bff34e3Sthurlow int 4374bff34e3Sthurlow rqlist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 4384bff34e3Sthurlow { 4394bff34e3Sthurlow rqlist_cbdata_t cbd; 4404bff34e3Sthurlow 4414bff34e3Sthurlow memset(&cbd, 0, sizeof (cbd)); 4424bff34e3Sthurlow 4434bff34e3Sthurlow /* 4444bff34e3Sthurlow * Initial walk_addr is address of parent (VC) 4454bff34e3Sthurlow */ 4464bff34e3Sthurlow if (!(flags & DCMD_ADDRSPEC)) { 4474bff34e3Sthurlow mdb_warn("address required\n"); 4484bff34e3Sthurlow return (DCMD_ERR); 4494bff34e3Sthurlow } 4504bff34e3Sthurlow 4514bff34e3Sthurlow if (mdb_pwalk("nsmb_rqlist", rqlist_cb, &cbd, addr) == -1) { 4524bff34e3Sthurlow mdb_warn("failed to walk 'nsmb_rqlist'"); 4534bff34e3Sthurlow return (DCMD_ERR); 4544bff34e3Sthurlow } 4554bff34e3Sthurlow 4564bff34e3Sthurlow return (DCMD_OK); 4574bff34e3Sthurlow } 4584bff34e3Sthurlow 4594bff34e3Sthurlow 4604bff34e3Sthurlow /* 4614bff34e3Sthurlow * AVL walker for the passwords AVL tree, 4624bff34e3Sthurlow * and dcmd to show a summary. 4634bff34e3Sthurlow */ 4644bff34e3Sthurlow static int 4654bff34e3Sthurlow pwtree_walk_init(mdb_walk_state_t *wsp) 4664bff34e3Sthurlow { 4674bff34e3Sthurlow GElf_Sym sym; 4684bff34e3Sthurlow 4694bff34e3Sthurlow if (wsp->walk_addr != NULL) { 4704bff34e3Sthurlow mdb_warn("pwtree walk only supports global walks\n"); 4714bff34e3Sthurlow return (WALK_ERR); 4724bff34e3Sthurlow } 4734bff34e3Sthurlow 4744bff34e3Sthurlow if (mdb_lookup_by_obj("nsmb", "smb_ptd", &sym) == -1) { 4754bff34e3Sthurlow mdb_warn("failed to find symbol 'smb_ptd'"); 4764bff34e3Sthurlow return (WALK_ERR); 4774bff34e3Sthurlow } 4784bff34e3Sthurlow 4794bff34e3Sthurlow wsp->walk_addr = (uintptr_t)sym.st_value; 4804bff34e3Sthurlow 4814bff34e3Sthurlow if (mdb_layered_walk("avl", wsp) == -1) { 4824bff34e3Sthurlow mdb_warn("failed to walk 'avl'\n"); 4834bff34e3Sthurlow return (WALK_ERR); 4844bff34e3Sthurlow } 4854bff34e3Sthurlow 4864bff34e3Sthurlow return (WALK_NEXT); 4874bff34e3Sthurlow } 4884bff34e3Sthurlow 4894bff34e3Sthurlow static int 4904bff34e3Sthurlow pwtree_walk_step(mdb_walk_state_t *wsp) 4914bff34e3Sthurlow { 4924bff34e3Sthurlow smb_passid_t ptnode; 4934bff34e3Sthurlow 4944bff34e3Sthurlow if (mdb_vread(&ptnode, sizeof (ptnode), wsp->walk_addr) == -1) { 4954bff34e3Sthurlow mdb_warn("failed to read smb_passid_t at %p", wsp->walk_addr); 4964bff34e3Sthurlow return (WALK_ERR); 4974bff34e3Sthurlow } 4984bff34e3Sthurlow 4994bff34e3Sthurlow return (wsp->walk_callback(wsp->walk_addr, &ptnode, wsp->walk_cbdata)); 5004bff34e3Sthurlow } 5014bff34e3Sthurlow 5024bff34e3Sthurlow typedef struct pwtree_cbdata { 5034bff34e3Sthurlow int printed_header; 5044bff34e3Sthurlow uid_t uid; /* optional filtering by UID */ 5054bff34e3Sthurlow } pwtree_cbdata_t; 5064bff34e3Sthurlow 5074bff34e3Sthurlow int 5084bff34e3Sthurlow pwtree_cb(uintptr_t addr, const void *data, void *arg) 5094bff34e3Sthurlow { 5104bff34e3Sthurlow const smb_passid_t *ptn = data; 5114bff34e3Sthurlow pwtree_cbdata_t *cbd = arg; 5124bff34e3Sthurlow 5134bff34e3Sthurlow /* Optional filtering by UID. */ 5144bff34e3Sthurlow if (cbd->uid != (uid_t)-1 && cbd->uid != ptn->uid) { 5154bff34e3Sthurlow return (WALK_NEXT); 5164bff34e3Sthurlow } 5174bff34e3Sthurlow 5184bff34e3Sthurlow if (cbd->printed_header == 0) { 5194bff34e3Sthurlow cbd->printed_header = 1; 5204bff34e3Sthurlow mdb_printf("// smb_passid_t UID domain user\n"); 5214bff34e3Sthurlow } 5224bff34e3Sthurlow 5234bff34e3Sthurlow mdb_printf(" %-p", addr); /* smb_passid_t */ 5244bff34e3Sthurlow mdb_printf(" %d", (uintptr_t)ptn->uid); 5254bff34e3Sthurlow print_str((uintptr_t)ptn->srvdom); 5264bff34e3Sthurlow print_str((uintptr_t)ptn->username); 5274bff34e3Sthurlow mdb_printf("\n"); 5284bff34e3Sthurlow 5294bff34e3Sthurlow return (WALK_NEXT); 5304bff34e3Sthurlow } 5314bff34e3Sthurlow 5324bff34e3Sthurlow /*ARGSUSED*/ 5334bff34e3Sthurlow int 5344bff34e3Sthurlow pwtree_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 5354bff34e3Sthurlow { 5364bff34e3Sthurlow pwtree_cbdata_t cbd; 5374bff34e3Sthurlow char *uid_str = NULL; 5384bff34e3Sthurlow char buf[32]; 5394bff34e3Sthurlow 5404bff34e3Sthurlow memset(&cbd, 0, sizeof (cbd)); 5414bff34e3Sthurlow 5424bff34e3Sthurlow if (mdb_getopts(argc, argv, 5434bff34e3Sthurlow 'u', MDB_OPT_STR, &uid_str, NULL) != argc) { 5444bff34e3Sthurlow return (DCMD_USAGE); 5454bff34e3Sthurlow } 5464bff34e3Sthurlow if (uid_str) { 5474bff34e3Sthurlow /* 5484bff34e3Sthurlow * Want the the default radix to be 10 here. 5494bff34e3Sthurlow * If the string has some kind of radix prefix, 5504bff34e3Sthurlow * just use that as-is, otherwise prepend "0t". 5514bff34e3Sthurlow * Cheating on the "not a digit" test, but 5524bff34e3Sthurlow * mdb_strtoull will do a real syntax check. 5534bff34e3Sthurlow */ 5544bff34e3Sthurlow if (uid_str[0] == '0' && uid_str[1] > '9') { 5554bff34e3Sthurlow cbd.uid = (uid_t)mdb_strtoull(uid_str); 5564bff34e3Sthurlow } else { 5574bff34e3Sthurlow strcpy(buf, "0t"); 5584bff34e3Sthurlow strlcat(buf, uid_str, sizeof (buf)); 5594bff34e3Sthurlow cbd.uid = (uid_t)mdb_strtoull(buf); 5604bff34e3Sthurlow } 5614bff34e3Sthurlow } else 5624bff34e3Sthurlow cbd.uid = (uid_t)-1; 5634bff34e3Sthurlow 5644bff34e3Sthurlow if (flags & DCMD_ADDRSPEC) { 5654bff34e3Sthurlow mdb_warn("address not allowed\n"); 5664bff34e3Sthurlow return (DCMD_ERR); 5674bff34e3Sthurlow } 5684bff34e3Sthurlow 5694bff34e3Sthurlow if (mdb_pwalk("nsmb_pwtree", pwtree_cb, &cbd, 0) == -1) { 5704bff34e3Sthurlow mdb_warn("failed to walk 'nsmb_pwtree'"); 5714bff34e3Sthurlow return (DCMD_ERR); 5724bff34e3Sthurlow } 5734bff34e3Sthurlow 5744bff34e3Sthurlow return (DCMD_OK); 5754bff34e3Sthurlow } 5764bff34e3Sthurlow 5774bff34e3Sthurlow void 5784bff34e3Sthurlow pwtree_help(void) 5794bff34e3Sthurlow { 5804bff34e3Sthurlow mdb_printf("Options:\n" 5814bff34e3Sthurlow " -u uid show only entries belonging to uid (decimal)\n"); 5824bff34e3Sthurlow } 5834bff34e3Sthurlow 5844bff34e3Sthurlow 5854bff34e3Sthurlow static const mdb_dcmd_t dcmds[] = { 5864bff34e3Sthurlow { "nsmb_vc", "?[-rv]", 5874bff34e3Sthurlow "show smb_vc (or list)", 5884bff34e3Sthurlow smb_vc_dcmd, smb_vc_help }, 5894bff34e3Sthurlow { "nsmb_rqlist", ":", 5904bff34e3Sthurlow "show smb_rq list on a VC", 5914bff34e3Sthurlow rqlist_dcmd, NULL }, 5924bff34e3Sthurlow { "nsmb_pwtree", "?[-u uid]", 5934bff34e3Sthurlow "list smb_passid_t (password tree)", 5944bff34e3Sthurlow pwtree_dcmd, pwtree_help }, 5954bff34e3Sthurlow {NULL} 5964bff34e3Sthurlow }; 5974bff34e3Sthurlow 5984bff34e3Sthurlow static const mdb_walker_t walkers[] = { 5994bff34e3Sthurlow { "nsmb_vc", "walk nsmb VC list", 6004bff34e3Sthurlow smb_vc_walk_init, smb_co_walk_step, NULL }, 6014bff34e3Sthurlow { "nsmb_ss", "walk nsmb share list for some VC", 6024bff34e3Sthurlow smb_ss_walk_init, smb_co_walk_step, NULL }, 6034bff34e3Sthurlow { "nsmb_rqlist", "walk request list for some VC", 6044bff34e3Sthurlow rqlist_walk_init, rqlist_walk_step, NULL }, 6054bff34e3Sthurlow { "nsmb_pwtree", "walk passord AVL tree", 6064bff34e3Sthurlow pwtree_walk_init, pwtree_walk_step, NULL }, 6074bff34e3Sthurlow {NULL} 6084bff34e3Sthurlow }; 6094bff34e3Sthurlow 6104bff34e3Sthurlow static const mdb_modinfo_t modinfo = { 6114bff34e3Sthurlow MDB_API_VERSION, 6124bff34e3Sthurlow dcmds, 6134bff34e3Sthurlow walkers 6144bff34e3Sthurlow }; 6154bff34e3Sthurlow 6164bff34e3Sthurlow const mdb_modinfo_t * 6174bff34e3Sthurlow _mdb_init(void) 6184bff34e3Sthurlow { 6194bff34e3Sthurlow return (&modinfo); 6204bff34e3Sthurlow } 621