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
print_str(uintptr_t addr)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
smb_co_walk_init(mdb_walk_state_t * wsp,int level)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
smb_vc_walk_init(mdb_walk_state_t * wsp)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
smb_ss_walk_init(mdb_walk_state_t * wsp)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
smb_co_walk_step(mdb_walk_state_t * wsp)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
smb_ss_cb(uintptr_t addr,const void * data,void * arg)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 *
vcstate_str(smb_co_cbdata_t * cbd,int stval)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
smb_vc_cb(uintptr_t addr,const void * data,void * arg)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
smb_vc_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
smb_vc_help(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
rqlist_walk_init(mdb_walk_state_t * wsp)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
rqlist_walk_step(mdb_walk_state_t * wsp)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
rqlist_cb(uintptr_t addr,const void * data,void * arg)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
rqlist_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
pwtree_walk_init(mdb_walk_state_t * wsp)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
pwtree_walk_step(mdb_walk_state_t * wsp)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
pwtree_cb(uintptr_t addr,const void * data,void * arg)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
pwtree_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
pwtree_help(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 *
_mdb_init(void)6174bff34e3Sthurlow _mdb_init(void)
6184bff34e3Sthurlow {
6194bff34e3Sthurlow return (&modinfo);
6204bff34e3Sthurlow }
621