16007Sthurlow /*
26007Sthurlow * CDDL HEADER START
36007Sthurlow *
46007Sthurlow * The contents of this file are subject to the terms of the
56007Sthurlow * Common Development and Distribution License (the "License").
66007Sthurlow * You may not use this file except in compliance with the License.
76007Sthurlow *
86007Sthurlow * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96007Sthurlow * or http://www.opensolaris.org/os/licensing.
106007Sthurlow * See the License for the specific language governing permissions
116007Sthurlow * and limitations under the License.
126007Sthurlow *
136007Sthurlow * When distributing Covered Code, include this CDDL HEADER in each
146007Sthurlow * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156007Sthurlow * If applicable, add the following below this CDDL HEADER, with the
166007Sthurlow * fields enclosed by brackets "[]" replaced with your own identifying
176007Sthurlow * information: Portions Copyright [yyyy] [name of copyright owner]
186007Sthurlow *
196007Sthurlow * CDDL HEADER END
206007Sthurlow */
216007Sthurlow
226007Sthurlow /*
23*10023SGordon.Ross@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
246007Sthurlow * Use is subject to license terms.
256007Sthurlow */
266007Sthurlow
276007Sthurlow
286007Sthurlow #include <sys/mdb_modapi.h>
29*10023SGordon.Ross@Sun.COM #include <mdb/mdb_ctf.h>
306007Sthurlow #include <sys/types.h>
31*10023SGordon.Ross@Sun.COM #include <sys/socket.h>
326007Sthurlow
336007Sthurlow #include "smb_conn.h"
346007Sthurlow #include "smb_rq.h"
356007Sthurlow #include "smb_pass.h"
366007Sthurlow
376007Sthurlow #define OPT_VERBOSE 0x0001 /* Be [-v]erbose in dcmd's */
386007Sthurlow #define OPT_RECURSE 0x0002 /* recursive display */
396007Sthurlow
406007Sthurlow /*
416007Sthurlow * We need to read in a private copy
426007Sthurlow * of every string we want to print out.
436007Sthurlow */
446007Sthurlow void
print_str(uintptr_t addr)456007Sthurlow print_str(uintptr_t addr)
466007Sthurlow {
476007Sthurlow char buf[32];
486007Sthurlow int len, mx = sizeof (buf) - 4;
496007Sthurlow
506007Sthurlow if ((len = mdb_readstr(buf, sizeof (buf), addr)) <= 0) {
516007Sthurlow mdb_printf(" (%p)", addr);
526007Sthurlow } else {
536007Sthurlow if (len > mx)
546007Sthurlow strcpy(&buf[mx], "...");
556007Sthurlow mdb_printf(" %s", buf);
566007Sthurlow }
576007Sthurlow }
586007Sthurlow
596007Sthurlow
606007Sthurlow /*
616007Sthurlow * Walker for smb_connobj_t structures, including
626007Sthurlow * smb_vc_t and smb_share_t which "inherit" from it.
636007Sthurlow * Tricky: Exploit the "inheritance" of smb_connobj_t
646007Sthurlow * with common functions for walk_init, walk_next.
656007Sthurlow */
666007Sthurlow typedef struct smb_co_walk_data {
676007Sthurlow uintptr_t pp;
686007Sthurlow int level; /* SMBL_SM, SMBL_VC, SMBL_SHARE */
696007Sthurlow int size; /* sizeof (union member) */
706007Sthurlow union co_u {
716007Sthurlow smb_connobj_t co; /* copy of the list element */
726007Sthurlow smb_vc_t vc;
736007Sthurlow smb_share_t ss;
746007Sthurlow } u;
756007Sthurlow } smb_co_walk_data_t;
766007Sthurlow
776007Sthurlow /*
786007Sthurlow * Common walk_init for walking structs inherited
796007Sthurlow * from smb_connobj_t (smb_vc_t, smb_share_t)
806007Sthurlow */
816007Sthurlow int
smb_co_walk_init(mdb_walk_state_t * wsp,int level)826007Sthurlow smb_co_walk_init(mdb_walk_state_t *wsp, int level)
836007Sthurlow {
846007Sthurlow smb_co_walk_data_t *smbw;
856007Sthurlow size_t psz;
866007Sthurlow
876007Sthurlow if (wsp->walk_addr == NULL)
886007Sthurlow return (WALK_ERR);
896007Sthurlow
906007Sthurlow smbw = mdb_alloc(sizeof (*smbw), UM_SLEEP | UM_GC);
916007Sthurlow wsp->walk_data = smbw;
926007Sthurlow
936007Sthurlow /*
946007Sthurlow * Save the parent pointer for later checks, and
956007Sthurlow * the level so we know which union member it is.
966007Sthurlow * Also the size of this union member.
976007Sthurlow */
986007Sthurlow smbw->pp = wsp->walk_addr;
996007Sthurlow smbw->level = level;
1006007Sthurlow switch (level) {
1016007Sthurlow case SMBL_SM:
1026007Sthurlow smbw->size = sizeof (smbw->u.co);
1036007Sthurlow break;
1046007Sthurlow case SMBL_VC:
1056007Sthurlow smbw->size = sizeof (smbw->u.vc);
1066007Sthurlow break;
1076007Sthurlow case SMBL_SHARE:
1086007Sthurlow smbw->size = sizeof (smbw->u.ss);
1096007Sthurlow break;
1106007Sthurlow default:
1116007Sthurlow smbw->size = sizeof (smbw->u);
1126007Sthurlow break;
1136007Sthurlow }
1146007Sthurlow
1156007Sthurlow /*
1166007Sthurlow * Read in the parent object. Just need the
1176007Sthurlow * invariant part (smb_connobj_t) so we can
1186007Sthurlow * get the list of children below it.
1196007Sthurlow */
1206007Sthurlow psz = sizeof (smbw->u.co);
1216007Sthurlow if (mdb_vread(&smbw->u.co, psz, smbw->pp) != psz) {
1226007Sthurlow mdb_warn("cannot read connobj from %p", smbw->pp);
1236007Sthurlow return (WALK_ERR);
1246007Sthurlow }
1256007Sthurlow
1266007Sthurlow /*
1276007Sthurlow * Finally, setup to walk the list of children.
1286007Sthurlow */
1296007Sthurlow wsp->walk_addr = (uintptr_t)smbw->u.co.co_children.slh_first;
1306007Sthurlow
1316007Sthurlow return (WALK_NEXT);
1326007Sthurlow }
1336007Sthurlow
1346007Sthurlow /*
1356007Sthurlow * Walk the (global) VC list.
1366007Sthurlow */
1376007Sthurlow int
smb_vc_walk_init(mdb_walk_state_t * wsp)1386007Sthurlow smb_vc_walk_init(mdb_walk_state_t *wsp)
1396007Sthurlow {
1406007Sthurlow GElf_Sym sym;
1416007Sthurlow
1426007Sthurlow if (wsp->walk_addr != NULL) {
1436007Sthurlow mdb_warn("::walk smb_vc only supports global walks\n");
1446007Sthurlow return (WALK_ERR);
1456007Sthurlow }
1466007Sthurlow
1476007Sthurlow /* Locate the VC list head. */
1486007Sthurlow if (mdb_lookup_by_obj("nsmb", "smb_vclist", &sym)) {
1496007Sthurlow mdb_warn("failed to lookup `smb_vclist'\n");
1506007Sthurlow return (WALK_ERR);
1516007Sthurlow }
1526007Sthurlow wsp->walk_addr = sym.st_value;
1536007Sthurlow
1546007Sthurlow return (smb_co_walk_init(wsp, SMBL_VC));
1556007Sthurlow }
1566007Sthurlow
1576007Sthurlow /*
1586007Sthurlow * Walk the share list below some VC.
1596007Sthurlow */
1606007Sthurlow int
smb_ss_walk_init(mdb_walk_state_t * wsp)1616007Sthurlow smb_ss_walk_init(mdb_walk_state_t *wsp)
1626007Sthurlow {
1636007Sthurlow
1646007Sthurlow /*
1656007Sthurlow * Initial walk_addr is address of parent (VC)
1666007Sthurlow */
1676007Sthurlow if (wsp->walk_addr == 0) {
1686007Sthurlow mdb_warn("::walk smb_ss does not support global walks\n");
1696007Sthurlow return (WALK_ERR);
1706007Sthurlow }
1716007Sthurlow
1726007Sthurlow return (smb_co_walk_init(wsp, SMBL_SHARE));
1736007Sthurlow }
1746007Sthurlow
1756007Sthurlow /*
1766007Sthurlow * Common walk_step for walking structs inherited
1776007Sthurlow * from smb_connobj_t (smb_vc_t, smb_share_t)
1786007Sthurlow */
1796007Sthurlow int
smb_co_walk_step(mdb_walk_state_t * wsp)1806007Sthurlow smb_co_walk_step(mdb_walk_state_t *wsp)
1816007Sthurlow {
1826007Sthurlow smb_co_walk_data_t *smbw = wsp->walk_data;
1836007Sthurlow int status;
1846007Sthurlow
1856007Sthurlow if (wsp->walk_addr == NULL)
1866007Sthurlow return (WALK_DONE);
1876007Sthurlow
1886007Sthurlow if (mdb_vread(&smbw->u, smbw->size, wsp->walk_addr)
1896007Sthurlow != smbw->size) {
1906007Sthurlow mdb_warn("cannot read connobj from %p", wsp->walk_addr);
1916007Sthurlow return (WALK_ERR);
1926007Sthurlow }
1936007Sthurlow
1946007Sthurlow /* XXX: Sanity check level? parent pointer? */
1956007Sthurlow
1966007Sthurlow status = wsp->walk_callback(wsp->walk_addr, &smbw->u,
1976007Sthurlow wsp->walk_cbdata);
1986007Sthurlow
1996007Sthurlow wsp->walk_addr = (uintptr_t)smbw->u.co.co_next.sle_next;
2006007Sthurlow
2016007Sthurlow return (status);
2026007Sthurlow }
2036007Sthurlow
2046007Sthurlow
2056007Sthurlow /*
2066007Sthurlow * Dcmd (and callback function) to print a summary of
2076007Sthurlow * all VCs, and optionally all shares under each VC.
2086007Sthurlow */
2096007Sthurlow
2106007Sthurlow typedef struct smb_co_cbdata {
2116007Sthurlow int flags; /* OPT_... */
2126007Sthurlow int printed_header;
213*10023SGordon.Ross@Sun.COM mdb_ctf_id_t ctf_id;
2146007Sthurlow } smb_co_cbdata_t;
2156007Sthurlow
2166007Sthurlow /*
2176007Sthurlow * Call-back function for walking a share list.
2186007Sthurlow */
2196007Sthurlow int
smb_ss_cb(uintptr_t addr,const void * data,void * arg)2206007Sthurlow smb_ss_cb(uintptr_t addr, const void *data, void *arg)
2216007Sthurlow {
2226007Sthurlow const smb_share_t *ssp = data;
2236007Sthurlow smb_co_cbdata_t *cbd = arg;
2246007Sthurlow
225*10023SGordon.Ross@Sun.COM mdb_printf(" %-p\t%s\n", addr, ssp->ss_name);
2266007Sthurlow
2276007Sthurlow if (cbd->flags & OPT_VERBOSE) {
2286007Sthurlow mdb_inc_indent(2);
2296007Sthurlow /* Anything wanted here? */
2306007Sthurlow mdb_dec_indent(2);
2316007Sthurlow }
2326007Sthurlow
2336007Sthurlow return (WALK_NEXT);
2346007Sthurlow }
2356007Sthurlow
236*10023SGordon.Ross@Sun.COM static const char *
vcstate_str(smb_co_cbdata_t * cbd,int stval)237*10023SGordon.Ross@Sun.COM vcstate_str(smb_co_cbdata_t *cbd, int stval)
238*10023SGordon.Ross@Sun.COM {
239*10023SGordon.Ross@Sun.COM static const char prefix[] = "SMBIOD_ST_";
240*10023SGordon.Ross@Sun.COM int prefix_len = sizeof (prefix) - 1;
241*10023SGordon.Ross@Sun.COM mdb_ctf_id_t vcst_enum;
242*10023SGordon.Ross@Sun.COM const char *cp;
243*10023SGordon.Ross@Sun.COM
244*10023SGordon.Ross@Sun.COM /* Got this in smb_vc_dcmd. */
245*10023SGordon.Ross@Sun.COM vcst_enum = cbd->ctf_id;
246*10023SGordon.Ross@Sun.COM
247*10023SGordon.Ross@Sun.COM /* Get the name for the enum value. */
248*10023SGordon.Ross@Sun.COM if ((cp = mdb_ctf_enum_name(vcst_enum, stval)) == NULL)
249*10023SGordon.Ross@Sun.COM return ("?");
250*10023SGordon.Ross@Sun.COM
251*10023SGordon.Ross@Sun.COM /* Skip the prefix part. */
252*10023SGordon.Ross@Sun.COM if (strncmp(cp, prefix, prefix_len) == 0)
253*10023SGordon.Ross@Sun.COM cp += prefix_len;
254*10023SGordon.Ross@Sun.COM
255*10023SGordon.Ross@Sun.COM return (cp);
256*10023SGordon.Ross@Sun.COM }
257*10023SGordon.Ross@Sun.COM
2586007Sthurlow /*
2596007Sthurlow * Call-back function for walking the VC list.
2606007Sthurlow */
2616007Sthurlow int
smb_vc_cb(uintptr_t addr,const void * data,void * arg)2626007Sthurlow smb_vc_cb(uintptr_t addr, const void *data, void *arg)
2636007Sthurlow {
2646007Sthurlow const smb_vc_t *vcp = data;
2656007Sthurlow smb_co_cbdata_t *cbd = arg;
2666007Sthurlow
2676007Sthurlow if (cbd->printed_header == 0) {
2686007Sthurlow cbd->printed_header = 1;
269*10023SGordon.Ross@Sun.COM mdb_printf("// smb_vc_t uid server \tuser\t\tstate\n");
2706007Sthurlow }
2716007Sthurlow
2726007Sthurlow mdb_printf("%-p", addr);
273*10023SGordon.Ross@Sun.COM mdb_printf(" %7d", vcp->vc_owner);
274*10023SGordon.Ross@Sun.COM
275*10023SGordon.Ross@Sun.COM switch (vcp->vc_srvaddr.sa.sa_family) {
276*10023SGordon.Ross@Sun.COM case AF_INET:
277*10023SGordon.Ross@Sun.COM mdb_printf(" %I", vcp->vc_srvaddr.sin.sin_addr);
278*10023SGordon.Ross@Sun.COM break;
279*10023SGordon.Ross@Sun.COM case AF_INET6:
280*10023SGordon.Ross@Sun.COM mdb_printf(" %N", &vcp->vc_srvaddr.sin6.sin6_addr);
281*10023SGordon.Ross@Sun.COM break;
282*10023SGordon.Ross@Sun.COM default:
283*10023SGordon.Ross@Sun.COM mdb_printf(" %15s", "(bad af)");
284*10023SGordon.Ross@Sun.COM break;
285*10023SGordon.Ross@Sun.COM }
286*10023SGordon.Ross@Sun.COM
287*10023SGordon.Ross@Sun.COM if (vcp->vc_username[0] != '\0')
288*10023SGordon.Ross@Sun.COM mdb_printf("\t%s", vcp->vc_username);
289*10023SGordon.Ross@Sun.COM else
290*10023SGordon.Ross@Sun.COM mdb_printf("\t%s", "(?)");
291*10023SGordon.Ross@Sun.COM
292*10023SGordon.Ross@Sun.COM if (vcp->vc_domain[0] != '\0')
293*10023SGordon.Ross@Sun.COM mdb_printf("@%s", vcp->vc_domain);
294*10023SGordon.Ross@Sun.COM
295*10023SGordon.Ross@Sun.COM mdb_printf("\t%s\n", vcstate_str(cbd, vcp->vc_state));
2966007Sthurlow
2976007Sthurlow if (cbd->flags & OPT_RECURSE) {
2986007Sthurlow mdb_inc_indent(2);
2996007Sthurlow if (mdb_pwalk("nsmb_ss", smb_ss_cb, cbd, addr) < 0) {
3006007Sthurlow mdb_warn("failed to walk 'nsmb_ss'");
3016007Sthurlow /* Don't: return (WALK_ERR); */
3026007Sthurlow }
3036007Sthurlow mdb_dec_indent(2);
3046007Sthurlow }
3056007Sthurlow
3066007Sthurlow return (WALK_NEXT);
3076007Sthurlow }
3086007Sthurlow
3096007Sthurlow int
smb_vc_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3106007Sthurlow smb_vc_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3116007Sthurlow {
3126007Sthurlow smb_co_cbdata_t cbd;
3136007Sthurlow smb_vc_t *vcp;
3146007Sthurlow size_t vcsz;
3156007Sthurlow
3166007Sthurlow memset(&cbd, 0, sizeof (cbd));
3176007Sthurlow
3186007Sthurlow if (mdb_getopts(argc, argv,
3196007Sthurlow 'r', MDB_OPT_SETBITS, OPT_RECURSE, &cbd.flags,
3206007Sthurlow 'v', MDB_OPT_SETBITS, OPT_VERBOSE, &cbd.flags,
3216007Sthurlow NULL) != argc) {
3226007Sthurlow return (DCMD_USAGE);
3236007Sthurlow }
3246007Sthurlow
325*10023SGordon.Ross@Sun.COM if (mdb_ctf_lookup_by_name("enum smbiod_state", &cbd.ctf_id) == -1) {
326*10023SGordon.Ross@Sun.COM mdb_warn("Could not find enum smbiod_state");
327*10023SGordon.Ross@Sun.COM }
328*10023SGordon.Ross@Sun.COM
3296007Sthurlow if (!(flags & DCMD_ADDRSPEC)) {
3306007Sthurlow if (mdb_walk("nsmb_vc", smb_vc_cb, &cbd) == -1) {
3316007Sthurlow mdb_warn("failed to walk 'nsmb_vc'");
3326007Sthurlow return (DCMD_ERR);
3336007Sthurlow }
3346007Sthurlow return (DCMD_OK);
3356007Sthurlow }
3366007Sthurlow
3376007Sthurlow vcsz = sizeof (*vcp);
3386007Sthurlow vcp = mdb_alloc(vcsz, UM_SLEEP | UM_GC);
3396007Sthurlow if (mdb_vread(vcp, vcsz, addr) != vcsz) {
3406007Sthurlow mdb_warn("cannot read VC from %p", addr);
3416007Sthurlow return (DCMD_ERR);
3426007Sthurlow }
3436007Sthurlow smb_vc_cb(addr, vcp, &cbd);
3446007Sthurlow
3456007Sthurlow return (DCMD_OK);
3466007Sthurlow }
3476007Sthurlow
3486007Sthurlow void
smb_vc_help(void)3496007Sthurlow smb_vc_help(void)
3506007Sthurlow {
3516007Sthurlow mdb_printf("Options:\n"
3526007Sthurlow " -r recursive display of share lists\n"
3536007Sthurlow " -v be verbose when displaying smb_vc\n");
3546007Sthurlow }
3556007Sthurlow
3566007Sthurlow /*
3576007Sthurlow * Walker for the request list on a VC,
3586007Sthurlow * and dcmd to show a summary.
3596007Sthurlow */
3606007Sthurlow int
rqlist_walk_init(mdb_walk_state_t * wsp)3616007Sthurlow rqlist_walk_init(mdb_walk_state_t *wsp)
3626007Sthurlow {
3636007Sthurlow struct smb_rqhead rqh;
3646007Sthurlow uintptr_t addr;
3656007Sthurlow
3666007Sthurlow /*
3676007Sthurlow * Initial walk_addr is the address of the VC.
3686007Sthurlow * Add offsetof(iod_rqlist) to get the rqhead.
3696007Sthurlow */
3706007Sthurlow if (wsp->walk_addr == 0) {
3716007Sthurlow mdb_warn("::walk smb_ss does not support global walks\n");
3726007Sthurlow return (WALK_ERR);
3736007Sthurlow }
3746007Sthurlow addr = wsp->walk_addr;
3756007Sthurlow addr += OFFSETOF(smb_vc_t, iod_rqlist);
3766007Sthurlow
3776007Sthurlow if (mdb_vread(&rqh, sizeof (rqh), addr) == -1) {
3786007Sthurlow mdb_warn("failed to read smb_rqhead at %p", addr);
3796007Sthurlow return (WALK_ERR);
3806007Sthurlow }
3816007Sthurlow wsp->walk_addr = (uintptr_t)rqh.tqh_first;
3826007Sthurlow
3836007Sthurlow return (WALK_NEXT);
3846007Sthurlow }
3856007Sthurlow
3866007Sthurlow int
rqlist_walk_step(mdb_walk_state_t * wsp)3876007Sthurlow rqlist_walk_step(mdb_walk_state_t *wsp)
3886007Sthurlow {
3896007Sthurlow smb_rq_t rq;
3906007Sthurlow int status;
3916007Sthurlow
3926007Sthurlow if (wsp->walk_addr == NULL)
3936007Sthurlow return (WALK_DONE);
3946007Sthurlow
3956007Sthurlow if (mdb_vread(&rq, sizeof (rq), wsp->walk_addr) == -1) {
3966007Sthurlow mdb_warn("cannot read smb_rq from %p", wsp->walk_addr);
3976007Sthurlow return (WALK_ERR);
3986007Sthurlow }
3996007Sthurlow
4006007Sthurlow status = wsp->walk_callback(wsp->walk_addr, &rq,
4016007Sthurlow wsp->walk_cbdata);
4026007Sthurlow
4036007Sthurlow wsp->walk_addr = (uintptr_t)rq.sr_link.tqe_next;
4046007Sthurlow
4056007Sthurlow return (status);
4066007Sthurlow }
4076007Sthurlow
4086007Sthurlow typedef struct rqlist_cbdata {
4096007Sthurlow int printed_header;
4106007Sthurlow uintptr_t uid; /* optional filtering by UID */
4116007Sthurlow } rqlist_cbdata_t;
4126007Sthurlow
4136007Sthurlow int
rqlist_cb(uintptr_t addr,const void * data,void * arg)4146007Sthurlow rqlist_cb(uintptr_t addr, const void *data, void *arg)
4156007Sthurlow {
4166007Sthurlow const smb_rq_t *rq = data;
4176007Sthurlow rqlist_cbdata_t *cbd = arg;
4186007Sthurlow
4196007Sthurlow if (cbd->printed_header == 0) {
4206007Sthurlow cbd->printed_header = 1;
4216007Sthurlow mdb_printf("// smb_rq_t MID cmd sr_state sr_flags\n");
4226007Sthurlow }
4236007Sthurlow
4246007Sthurlow mdb_printf(" %-p", addr); /* smb_rq_t */
4256007Sthurlow mdb_printf(" x%04x", rq->sr_mid);
4266007Sthurlow mdb_printf(" x%02x", rq->sr_cmd);
4276007Sthurlow mdb_printf(" %d", rq->sr_state);
4286007Sthurlow mdb_printf(" x%x", rq->sr_flags);
4296007Sthurlow mdb_printf("\n");
4306007Sthurlow
4316007Sthurlow return (WALK_NEXT);
4326007Sthurlow }
4336007Sthurlow
4346007Sthurlow /*ARGSUSED*/
4356007Sthurlow int
rqlist_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)4366007Sthurlow rqlist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4376007Sthurlow {
4386007Sthurlow rqlist_cbdata_t cbd;
4396007Sthurlow
4406007Sthurlow memset(&cbd, 0, sizeof (cbd));
4416007Sthurlow
4426007Sthurlow /*
4436007Sthurlow * Initial walk_addr is address of parent (VC)
4446007Sthurlow */
4456007Sthurlow if (!(flags & DCMD_ADDRSPEC)) {
4466007Sthurlow mdb_warn("address required\n");
4476007Sthurlow return (DCMD_ERR);
4486007Sthurlow }
4496007Sthurlow
4506007Sthurlow if (mdb_pwalk("nsmb_rqlist", rqlist_cb, &cbd, addr) == -1) {
4516007Sthurlow mdb_warn("failed to walk 'nsmb_rqlist'");
4526007Sthurlow return (DCMD_ERR);
4536007Sthurlow }
4546007Sthurlow
4556007Sthurlow return (DCMD_OK);
4566007Sthurlow }
4576007Sthurlow
4586007Sthurlow
4596007Sthurlow /*
4606007Sthurlow * AVL walker for the passwords AVL tree,
4616007Sthurlow * and dcmd to show a summary.
4626007Sthurlow */
4636007Sthurlow static int
pwtree_walk_init(mdb_walk_state_t * wsp)4646007Sthurlow pwtree_walk_init(mdb_walk_state_t *wsp)
4656007Sthurlow {
4666007Sthurlow GElf_Sym sym;
4676007Sthurlow
4686007Sthurlow if (wsp->walk_addr != NULL) {
4696007Sthurlow mdb_warn("pwtree walk only supports global walks\n");
4706007Sthurlow return (WALK_ERR);
4716007Sthurlow }
4726007Sthurlow
4736007Sthurlow if (mdb_lookup_by_obj("nsmb", "smb_ptd", &sym) == -1) {
4746007Sthurlow mdb_warn("failed to find symbol 'smb_ptd'");
4756007Sthurlow return (WALK_ERR);
4766007Sthurlow }
4776007Sthurlow
4786007Sthurlow wsp->walk_addr = (uintptr_t)sym.st_value;
4796007Sthurlow
4806007Sthurlow if (mdb_layered_walk("avl", wsp) == -1) {
4816007Sthurlow mdb_warn("failed to walk 'avl'\n");
4826007Sthurlow return (WALK_ERR);
4836007Sthurlow }
4846007Sthurlow
4856007Sthurlow return (WALK_NEXT);
4866007Sthurlow }
4876007Sthurlow
4886007Sthurlow static int
pwtree_walk_step(mdb_walk_state_t * wsp)4896007Sthurlow pwtree_walk_step(mdb_walk_state_t *wsp)
4906007Sthurlow {
4916007Sthurlow smb_passid_t ptnode;
4926007Sthurlow
4936007Sthurlow if (mdb_vread(&ptnode, sizeof (ptnode), wsp->walk_addr) == -1) {
4946007Sthurlow mdb_warn("failed to read smb_passid_t at %p", wsp->walk_addr);
4956007Sthurlow return (WALK_ERR);
4966007Sthurlow }
4976007Sthurlow
4986007Sthurlow return (wsp->walk_callback(wsp->walk_addr, &ptnode, wsp->walk_cbdata));
4996007Sthurlow }
5006007Sthurlow
5016007Sthurlow typedef struct pwtree_cbdata {
5026007Sthurlow int printed_header;
5036007Sthurlow uid_t uid; /* optional filtering by UID */
5046007Sthurlow } pwtree_cbdata_t;
5056007Sthurlow
5066007Sthurlow int
pwtree_cb(uintptr_t addr,const void * data,void * arg)5076007Sthurlow pwtree_cb(uintptr_t addr, const void *data, void *arg)
5086007Sthurlow {
5096007Sthurlow const smb_passid_t *ptn = data;
5106007Sthurlow pwtree_cbdata_t *cbd = arg;
5116007Sthurlow
5126007Sthurlow /* Optional filtering by UID. */
5136007Sthurlow if (cbd->uid != (uid_t)-1 && cbd->uid != ptn->uid) {
5146007Sthurlow return (WALK_NEXT);
5156007Sthurlow }
5166007Sthurlow
5176007Sthurlow if (cbd->printed_header == 0) {
5186007Sthurlow cbd->printed_header = 1;
5196007Sthurlow mdb_printf("// smb_passid_t UID domain user\n");
5206007Sthurlow }
5216007Sthurlow
5226007Sthurlow mdb_printf(" %-p", addr); /* smb_passid_t */
5236007Sthurlow mdb_printf(" %d", (uintptr_t)ptn->uid);
5246007Sthurlow print_str((uintptr_t)ptn->srvdom);
5256007Sthurlow print_str((uintptr_t)ptn->username);
5266007Sthurlow mdb_printf("\n");
5276007Sthurlow
5286007Sthurlow return (WALK_NEXT);
5296007Sthurlow }
5306007Sthurlow
5316007Sthurlow /*ARGSUSED*/
5326007Sthurlow int
pwtree_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5336007Sthurlow pwtree_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5346007Sthurlow {
5356007Sthurlow pwtree_cbdata_t cbd;
5366007Sthurlow char *uid_str = NULL;
5376007Sthurlow char buf[32];
5386007Sthurlow
5396007Sthurlow memset(&cbd, 0, sizeof (cbd));
5406007Sthurlow
5416007Sthurlow if (mdb_getopts(argc, argv,
5426007Sthurlow 'u', MDB_OPT_STR, &uid_str, NULL) != argc) {
5436007Sthurlow return (DCMD_USAGE);
5446007Sthurlow }
5456007Sthurlow if (uid_str) {
5466007Sthurlow /*
5476007Sthurlow * Want the the default radix to be 10 here.
5486007Sthurlow * If the string has some kind of radix prefix,
5496007Sthurlow * just use that as-is, otherwise prepend "0t".
5506007Sthurlow * Cheating on the "not a digit" test, but
5516007Sthurlow * mdb_strtoull will do a real syntax check.
5526007Sthurlow */
5536007Sthurlow if (uid_str[0] == '0' && uid_str[1] > '9') {
5546007Sthurlow cbd.uid = (uid_t)mdb_strtoull(uid_str);
5556007Sthurlow } else {
5566007Sthurlow strcpy(buf, "0t");
5576007Sthurlow strlcat(buf, uid_str, sizeof (buf));
5586007Sthurlow cbd.uid = (uid_t)mdb_strtoull(buf);
5596007Sthurlow }
5606007Sthurlow } else
5616007Sthurlow cbd.uid = (uid_t)-1;
5626007Sthurlow
5636007Sthurlow if (flags & DCMD_ADDRSPEC) {
5646007Sthurlow mdb_warn("address not allowed\n");
5656007Sthurlow return (DCMD_ERR);
5666007Sthurlow }
5676007Sthurlow
5686007Sthurlow if (mdb_pwalk("nsmb_pwtree", pwtree_cb, &cbd, 0) == -1) {
5696007Sthurlow mdb_warn("failed to walk 'nsmb_pwtree'");
5706007Sthurlow return (DCMD_ERR);
5716007Sthurlow }
5726007Sthurlow
5736007Sthurlow return (DCMD_OK);
5746007Sthurlow }
5756007Sthurlow
5766007Sthurlow void
pwtree_help(void)5776007Sthurlow pwtree_help(void)
5786007Sthurlow {
5796007Sthurlow mdb_printf("Options:\n"
5806007Sthurlow " -u uid show only entries belonging to uid (decimal)\n");
5816007Sthurlow }
5826007Sthurlow
5836007Sthurlow
5846007Sthurlow static const mdb_dcmd_t dcmds[] = {
5856007Sthurlow { "nsmb_vc", "?[-rv]",
5866007Sthurlow "show smb_vc (or list)",
5876007Sthurlow smb_vc_dcmd, smb_vc_help },
5886007Sthurlow { "nsmb_rqlist", ":",
5896007Sthurlow "show smb_rq list on a VC",
5906007Sthurlow rqlist_dcmd, NULL },
5916007Sthurlow { "nsmb_pwtree", "?[-u uid]",
5926007Sthurlow "list smb_passid_t (password tree)",
5936007Sthurlow pwtree_dcmd, pwtree_help },
5946007Sthurlow {NULL}
5956007Sthurlow };
5966007Sthurlow
5976007Sthurlow static const mdb_walker_t walkers[] = {
5986007Sthurlow { "nsmb_vc", "walk nsmb VC list",
5996007Sthurlow smb_vc_walk_init, smb_co_walk_step, NULL },
6006007Sthurlow { "nsmb_ss", "walk nsmb share list for some VC",
6016007Sthurlow smb_ss_walk_init, smb_co_walk_step, NULL },
6026007Sthurlow { "nsmb_rqlist", "walk request list for some VC",
6036007Sthurlow rqlist_walk_init, rqlist_walk_step, NULL },
6046007Sthurlow { "nsmb_pwtree", "walk passord AVL tree",
6056007Sthurlow pwtree_walk_init, pwtree_walk_step, NULL },
6066007Sthurlow {NULL}
6076007Sthurlow };
6086007Sthurlow
6096007Sthurlow static const mdb_modinfo_t modinfo = {
6106007Sthurlow MDB_API_VERSION,
6116007Sthurlow dcmds,
6126007Sthurlow walkers
6136007Sthurlow };
6146007Sthurlow
6156007Sthurlow const mdb_modinfo_t *
_mdb_init(void)6166007Sthurlow _mdb_init(void)
6176007Sthurlow {
6186007Sthurlow return (&modinfo);
6196007Sthurlow }
620