8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / mdb / common / modules / nsmb / nsmb.c
bloba1ce03833f5c8e4748c423574275a8ee4a600470
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
29 #include <sys/mdb_modapi.h>
30 #include <mdb/mdb_ctf.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
34 #include <netsmb/smb_conn.h>
35 #include <netsmb/smb_rq.h>
36 #include <netsmb/smb_pass.h>
38 #define OPT_VERBOSE 0x0001 /* Be [-v]erbose in dcmd's */
39 #define OPT_RECURSE 0x0002 /* recursive display */
42 * We need to read in a private copy
43 * of every string we want to print out.
45 void
46 print_str(uintptr_t addr)
48 char buf[32];
49 int len, mx = sizeof (buf) - 4;
51 if ((len = mdb_readstr(buf, sizeof (buf), addr)) <= 0) {
52 mdb_printf(" (%p)", addr);
53 } else {
54 if (len > mx)
55 strcpy(&buf[mx], "...");
56 mdb_printf(" %s", buf);
62 * Walker for smb_connobj_t structures, including
63 * smb_vc_t and smb_share_t which "inherit" from it.
64 * Tricky: Exploit the "inheritance" of smb_connobj_t
65 * with common functions for walk_init, walk_next.
67 typedef struct smb_co_walk_data {
68 uintptr_t pp;
69 int level; /* SMBL_SM, SMBL_VC, SMBL_SHARE */
70 int size; /* sizeof (union member) */
71 union co_u {
72 smb_connobj_t co; /* copy of the list element */
73 smb_vc_t vc;
74 smb_share_t ss;
75 } u;
76 } smb_co_walk_data_t;
79 * Common walk_init for walking structs inherited
80 * from smb_connobj_t (smb_vc_t, smb_share_t)
82 int
83 smb_co_walk_init(mdb_walk_state_t *wsp, int level)
85 smb_co_walk_data_t *smbw;
86 size_t psz;
88 if (wsp->walk_addr == NULL)
89 return (WALK_ERR);
91 smbw = mdb_alloc(sizeof (*smbw), UM_SLEEP | UM_GC);
92 wsp->walk_data = smbw;
95 * Save the parent pointer for later checks, and
96 * the level so we know which union member it is.
97 * Also the size of this union member.
99 smbw->pp = wsp->walk_addr;
100 smbw->level = level;
101 switch (level) {
102 case SMBL_SM:
103 smbw->size = sizeof (smbw->u.co);
104 break;
105 case SMBL_VC:
106 smbw->size = sizeof (smbw->u.vc);
107 break;
108 case SMBL_SHARE:
109 smbw->size = sizeof (smbw->u.ss);
110 break;
111 default:
112 smbw->size = sizeof (smbw->u);
113 break;
117 * Read in the parent object. Just need the
118 * invariant part (smb_connobj_t) so we can
119 * get the list of children below it.
121 psz = sizeof (smbw->u.co);
122 if (mdb_vread(&smbw->u.co, psz, smbw->pp) != psz) {
123 mdb_warn("cannot read connobj from %p", smbw->pp);
124 return (WALK_ERR);
128 * Finally, setup to walk the list of children.
130 wsp->walk_addr = (uintptr_t)smbw->u.co.co_children.slh_first;
132 return (WALK_NEXT);
136 * Walk the (global) VC list.
139 smb_vc_walk_init(mdb_walk_state_t *wsp)
141 GElf_Sym sym;
143 if (wsp->walk_addr != NULL) {
144 mdb_warn("::walk smb_vc only supports global walks\n");
145 return (WALK_ERR);
148 /* Locate the VC list head. */
149 if (mdb_lookup_by_obj("nsmb", "smb_vclist", &sym)) {
150 mdb_warn("failed to lookup `smb_vclist'\n");
151 return (WALK_ERR);
153 wsp->walk_addr = sym.st_value;
155 return (smb_co_walk_init(wsp, SMBL_VC));
159 * Walk the share list below some VC.
162 smb_ss_walk_init(mdb_walk_state_t *wsp)
166 * Initial walk_addr is address of parent (VC)
168 if (wsp->walk_addr == 0) {
169 mdb_warn("::walk smb_ss does not support global walks\n");
170 return (WALK_ERR);
173 return (smb_co_walk_init(wsp, SMBL_SHARE));
177 * Common walk_step for walking structs inherited
178 * from smb_connobj_t (smb_vc_t, smb_share_t)
181 smb_co_walk_step(mdb_walk_state_t *wsp)
183 smb_co_walk_data_t *smbw = wsp->walk_data;
184 int status;
186 if (wsp->walk_addr == NULL)
187 return (WALK_DONE);
189 if (mdb_vread(&smbw->u, smbw->size, wsp->walk_addr)
190 != smbw->size) {
191 mdb_warn("cannot read connobj from %p", wsp->walk_addr);
192 return (WALK_ERR);
195 /* XXX: Sanity check level? parent pointer? */
197 status = wsp->walk_callback(wsp->walk_addr, &smbw->u,
198 wsp->walk_cbdata);
200 wsp->walk_addr = (uintptr_t)smbw->u.co.co_next.sle_next;
202 return (status);
207 * Dcmd (and callback function) to print a summary of
208 * all VCs, and optionally all shares under each VC.
211 typedef struct smb_co_cbdata {
212 int flags; /* OPT_... */
213 int printed_header;
214 mdb_ctf_id_t ctf_id;
215 } smb_co_cbdata_t;
218 * Call-back function for walking a share list.
221 smb_ss_cb(uintptr_t addr, const void *data, void *arg)
223 const smb_share_t *ssp = data;
224 smb_co_cbdata_t *cbd = arg;
226 mdb_printf(" %-p\t%s\n", addr, ssp->ss_name);
228 if (cbd->flags & OPT_VERBOSE) {
229 mdb_inc_indent(2);
230 /* Anything wanted here? */
231 mdb_dec_indent(2);
234 return (WALK_NEXT);
237 static const char *
238 vcstate_str(smb_co_cbdata_t *cbd, int stval)
240 static const char prefix[] = "SMBIOD_ST_";
241 int prefix_len = sizeof (prefix) - 1;
242 mdb_ctf_id_t vcst_enum;
243 const char *cp;
245 /* Got this in smb_vc_dcmd. */
246 vcst_enum = cbd->ctf_id;
248 /* Get the name for the enum value. */
249 if ((cp = mdb_ctf_enum_name(vcst_enum, stval)) == NULL)
250 return ("?");
252 /* Skip the prefix part. */
253 if (strncmp(cp, prefix, prefix_len) == 0)
254 cp += prefix_len;
256 return (cp);
260 * Call-back function for walking the VC list.
263 smb_vc_cb(uintptr_t addr, const void *data, void *arg)
265 const smb_vc_t *vcp = data;
266 smb_co_cbdata_t *cbd = arg;
268 if (cbd->printed_header == 0) {
269 cbd->printed_header = 1;
270 mdb_printf("// smb_vc_t uid server \tuser\t\tstate\n");
273 mdb_printf("%-p", addr);
274 mdb_printf(" %7d", vcp->vc_owner);
276 switch (vcp->vc_srvaddr.sa.sa_family) {
277 case AF_INET:
278 mdb_printf(" %I", vcp->vc_srvaddr.sin.sin_addr);
279 break;
280 case AF_INET6:
281 mdb_printf(" %N", &vcp->vc_srvaddr.sin6.sin6_addr);
282 break;
283 default:
284 mdb_printf(" %15s", "(bad af)");
285 break;
288 if (vcp->vc_username[0] != '\0')
289 mdb_printf("\t%s", vcp->vc_username);
290 else
291 mdb_printf("\t%s", "(?)");
293 if (vcp->vc_domain[0] != '\0')
294 mdb_printf("@%s", vcp->vc_domain);
296 mdb_printf("\t%s\n", vcstate_str(cbd, vcp->vc_state));
298 if (cbd->flags & OPT_RECURSE) {
299 mdb_inc_indent(2);
300 if (mdb_pwalk("nsmb_ss", smb_ss_cb, cbd, addr) < 0) {
301 mdb_warn("failed to walk 'nsmb_ss'");
302 /* Don't: return (WALK_ERR); */
304 mdb_dec_indent(2);
307 return (WALK_NEXT);
311 smb_vc_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
313 smb_co_cbdata_t cbd;
314 smb_vc_t *vcp;
315 size_t vcsz;
317 memset(&cbd, 0, sizeof (cbd));
319 if (mdb_getopts(argc, argv,
320 'r', MDB_OPT_SETBITS, OPT_RECURSE, &cbd.flags,
321 'v', MDB_OPT_SETBITS, OPT_VERBOSE, &cbd.flags,
322 NULL) != argc) {
323 return (DCMD_USAGE);
326 if (mdb_ctf_lookup_by_name("enum smbiod_state", &cbd.ctf_id) == -1) {
327 mdb_warn("Could not find enum smbiod_state");
330 if (!(flags & DCMD_ADDRSPEC)) {
331 if (mdb_walk("nsmb_vc", smb_vc_cb, &cbd) == -1) {
332 mdb_warn("failed to walk 'nsmb_vc'");
333 return (DCMD_ERR);
335 return (DCMD_OK);
338 vcsz = sizeof (*vcp);
339 vcp = mdb_alloc(vcsz, UM_SLEEP | UM_GC);
340 if (mdb_vread(vcp, vcsz, addr) != vcsz) {
341 mdb_warn("cannot read VC from %p", addr);
342 return (DCMD_ERR);
344 smb_vc_cb(addr, vcp, &cbd);
346 return (DCMD_OK);
349 void
350 smb_vc_help(void)
352 mdb_printf("Options:\n"
353 " -r recursive display of share lists\n"
354 " -v be verbose when displaying smb_vc\n");
358 * Walker for the request list on a VC,
359 * and dcmd to show a summary.
362 rqlist_walk_init(mdb_walk_state_t *wsp)
364 struct smb_rqhead rqh;
365 uintptr_t addr;
368 * Initial walk_addr is the address of the VC.
369 * Add offsetof(iod_rqlist) to get the rqhead.
371 if (wsp->walk_addr == 0) {
372 mdb_warn("::walk smb_ss does not support global walks\n");
373 return (WALK_ERR);
375 addr = wsp->walk_addr;
376 addr += OFFSETOF(smb_vc_t, iod_rqlist);
378 if (mdb_vread(&rqh, sizeof (rqh), addr) == -1) {
379 mdb_warn("failed to read smb_rqhead at %p", addr);
380 return (WALK_ERR);
382 wsp->walk_addr = (uintptr_t)rqh.tqh_first;
384 return (WALK_NEXT);
388 rqlist_walk_step(mdb_walk_state_t *wsp)
390 smb_rq_t rq;
391 int status;
393 if (wsp->walk_addr == NULL)
394 return (WALK_DONE);
396 if (mdb_vread(&rq, sizeof (rq), wsp->walk_addr) == -1) {
397 mdb_warn("cannot read smb_rq from %p", wsp->walk_addr);
398 return (WALK_ERR);
401 status = wsp->walk_callback(wsp->walk_addr, &rq,
402 wsp->walk_cbdata);
404 wsp->walk_addr = (uintptr_t)rq.sr_link.tqe_next;
406 return (status);
409 typedef struct rqlist_cbdata {
410 int printed_header;
411 uintptr_t uid; /* optional filtering by UID */
412 } rqlist_cbdata_t;
415 rqlist_cb(uintptr_t addr, const void *data, void *arg)
417 const smb_rq_t *rq = data;
418 rqlist_cbdata_t *cbd = arg;
420 if (cbd->printed_header == 0) {
421 cbd->printed_header = 1;
422 mdb_printf("// smb_rq_t MID cmd sr_state sr_flags\n");
425 mdb_printf(" %-p", addr); /* smb_rq_t */
426 mdb_printf(" x%04x", rq->sr_mid);
427 mdb_printf(" x%02x", rq->sr_cmd);
428 mdb_printf(" %d", rq->sr_state);
429 mdb_printf(" x%x", rq->sr_flags);
430 mdb_printf("\n");
432 return (WALK_NEXT);
435 /*ARGSUSED*/
437 rqlist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
439 rqlist_cbdata_t cbd;
441 memset(&cbd, 0, sizeof (cbd));
444 * Initial walk_addr is address of parent (VC)
446 if (!(flags & DCMD_ADDRSPEC)) {
447 mdb_warn("address required\n");
448 return (DCMD_ERR);
451 if (mdb_pwalk("nsmb_rqlist", rqlist_cb, &cbd, addr) == -1) {
452 mdb_warn("failed to walk 'nsmb_rqlist'");
453 return (DCMD_ERR);
456 return (DCMD_OK);
461 * AVL walker for the passwords AVL tree,
462 * and dcmd to show a summary.
464 static int
465 pwtree_walk_init(mdb_walk_state_t *wsp)
467 GElf_Sym sym;
469 if (wsp->walk_addr != NULL) {
470 mdb_warn("pwtree walk only supports global walks\n");
471 return (WALK_ERR);
474 if (mdb_lookup_by_obj("nsmb", "smb_ptd", &sym) == -1) {
475 mdb_warn("failed to find symbol 'smb_ptd'");
476 return (WALK_ERR);
479 wsp->walk_addr = (uintptr_t)sym.st_value;
481 if (mdb_layered_walk("avl", wsp) == -1) {
482 mdb_warn("failed to walk 'avl'\n");
483 return (WALK_ERR);
486 return (WALK_NEXT);
489 static int
490 pwtree_walk_step(mdb_walk_state_t *wsp)
492 smb_passid_t ptnode;
494 if (mdb_vread(&ptnode, sizeof (ptnode), wsp->walk_addr) == -1) {
495 mdb_warn("failed to read smb_passid_t at %p", wsp->walk_addr);
496 return (WALK_ERR);
499 return (wsp->walk_callback(wsp->walk_addr, &ptnode, wsp->walk_cbdata));
502 typedef struct pwtree_cbdata {
503 int printed_header;
504 uid_t uid; /* optional filtering by UID */
505 } pwtree_cbdata_t;
508 pwtree_cb(uintptr_t addr, const void *data, void *arg)
510 const smb_passid_t *ptn = data;
511 pwtree_cbdata_t *cbd = arg;
513 /* Optional filtering by UID. */
514 if (cbd->uid != (uid_t)-1 && cbd->uid != ptn->uid) {
515 return (WALK_NEXT);
518 if (cbd->printed_header == 0) {
519 cbd->printed_header = 1;
520 mdb_printf("// smb_passid_t UID domain user\n");
523 mdb_printf(" %-p", addr); /* smb_passid_t */
524 mdb_printf(" %d", (uintptr_t)ptn->uid);
525 print_str((uintptr_t)ptn->srvdom);
526 print_str((uintptr_t)ptn->username);
527 mdb_printf("\n");
529 return (WALK_NEXT);
532 /*ARGSUSED*/
534 pwtree_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
536 pwtree_cbdata_t cbd;
537 char *uid_str = NULL;
538 char buf[32];
540 memset(&cbd, 0, sizeof (cbd));
542 if (mdb_getopts(argc, argv,
543 'u', MDB_OPT_STR, &uid_str, NULL) != argc) {
544 return (DCMD_USAGE);
546 if (uid_str) {
548 * Want the the default radix to be 10 here.
549 * If the string has some kind of radix prefix,
550 * just use that as-is, otherwise prepend "0t".
551 * Cheating on the "not a digit" test, but
552 * mdb_strtoull will do a real syntax check.
554 if (uid_str[0] == '0' && uid_str[1] > '9') {
555 cbd.uid = (uid_t)mdb_strtoull(uid_str);
556 } else {
557 strcpy(buf, "0t");
558 strlcat(buf, uid_str, sizeof (buf));
559 cbd.uid = (uid_t)mdb_strtoull(buf);
561 } else
562 cbd.uid = (uid_t)-1;
564 if (flags & DCMD_ADDRSPEC) {
565 mdb_warn("address not allowed\n");
566 return (DCMD_ERR);
569 if (mdb_pwalk("nsmb_pwtree", pwtree_cb, &cbd, 0) == -1) {
570 mdb_warn("failed to walk 'nsmb_pwtree'");
571 return (DCMD_ERR);
574 return (DCMD_OK);
577 void
578 pwtree_help(void)
580 mdb_printf("Options:\n"
581 " -u uid show only entries belonging to uid (decimal)\n");
585 static const mdb_dcmd_t dcmds[] = {
586 { "nsmb_vc", "?[-rv]",
587 "show smb_vc (or list)",
588 smb_vc_dcmd, smb_vc_help },
589 { "nsmb_rqlist", ":",
590 "show smb_rq list on a VC",
591 rqlist_dcmd, NULL },
592 { "nsmb_pwtree", "?[-u uid]",
593 "list smb_passid_t (password tree)",
594 pwtree_dcmd, pwtree_help },
595 {NULL}
598 static const mdb_walker_t walkers[] = {
599 { "nsmb_vc", "walk nsmb VC list",
600 smb_vc_walk_init, smb_co_walk_step, NULL },
601 { "nsmb_ss", "walk nsmb share list for some VC",
602 smb_ss_walk_init, smb_co_walk_step, NULL },
603 { "nsmb_rqlist", "walk request list for some VC",
604 rqlist_walk_init, rqlist_walk_step, NULL },
605 { "nsmb_pwtree", "walk passord AVL tree",
606 pwtree_walk_init, pwtree_walk_step, NULL },
607 {NULL}
610 static const mdb_modinfo_t modinfo = {
611 MDB_API_VERSION,
612 dcmds,
613 walkers
616 const mdb_modinfo_t *
617 _mdb_init(void)
619 return (&modinfo);