Mercurial > illumos > onarm
annotate usr/src/cmd/mdb/common/modules/nsmb/nsmb.c @ 4:1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Mon, 31 Aug 2009 14:38:03 +0900 |
parents | c9caec207d52 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 * CDDL HEADER START | |
3 * | |
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. | |
7 * | |
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. | |
12 * | |
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] | |
18 * | |
19 * CDDL HEADER END | |
20 */ | |
21 | |
22 /* | |
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. | |
24 * Use is subject to license terms. | |
25 */ | |
26 | |
27 | |
4
1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
Koji Uno <koji.uno@sun.com>
parents:
0
diff
changeset
|
28 #pragma ident "%Z%%M% %I% %E% SMI" |
0 | 29 |
30 #include <sys/mdb_modapi.h> | |
31 #include <sys/types.h> | |
32 | |
33 #include "smb_conn.h" | |
34 #include "smb_rq.h" | |
35 #include "smb_pass.h" | |
36 | |
37 #define OPT_VERBOSE 0x0001 /* Be [-v]erbose in dcmd's */ | |
38 #define OPT_RECURSE 0x0002 /* recursive display */ | |
39 | |
40 /* | |
41 * We need to read in a private copy | |
42 * of every string we want to print out. | |
43 */ | |
44 void | |
45 print_str(uintptr_t addr) | |
46 { | |
47 char buf[32]; | |
48 int len, mx = sizeof (buf) - 4; | |
49 | |
50 if ((len = mdb_readstr(buf, sizeof (buf), addr)) <= 0) { | |
51 mdb_printf(" (%p)", addr); | |
52 } else { | |
53 if (len > mx) | |
54 strcpy(&buf[mx], "..."); | |
55 mdb_printf(" %s", buf); | |
56 } | |
57 } | |
58 | |
59 | |
60 /* | |
61 * Walker for smb_connobj_t structures, including | |
62 * smb_vc_t and smb_share_t which "inherit" from it. | |
63 * Tricky: Exploit the "inheritance" of smb_connobj_t | |
64 * with common functions for walk_init, walk_next. | |
65 */ | |
66 typedef struct smb_co_walk_data { | |
67 uintptr_t pp; | |
68 int level; /* SMBL_SM, SMBL_VC, SMBL_SHARE */ | |
69 int size; /* sizeof (union member) */ | |
70 union co_u { | |
71 smb_connobj_t co; /* copy of the list element */ | |
72 smb_vc_t vc; | |
73 smb_share_t ss; | |
74 } u; | |
75 } smb_co_walk_data_t; | |
76 | |
77 /* | |
78 * Common walk_init for walking structs inherited | |
79 * from smb_connobj_t (smb_vc_t, smb_share_t) | |
80 */ | |
81 int | |
82 smb_co_walk_init(mdb_walk_state_t *wsp, int level) | |
83 { | |
84 smb_co_walk_data_t *smbw; | |
85 size_t psz; | |
86 | |
87 if (wsp->walk_addr == NULL) | |
88 return (WALK_ERR); | |
89 | |
90 smbw = mdb_alloc(sizeof (*smbw), UM_SLEEP | UM_GC); | |
91 wsp->walk_data = smbw; | |
92 | |
93 /* | |
94 * Save the parent pointer for later checks, and | |
95 * the level so we know which union member it is. | |
96 * Also the size of this union member. | |
97 */ | |
98 smbw->pp = wsp->walk_addr; | |
99 smbw->level = level; | |
100 switch (level) { | |
101 case SMBL_SM: | |
102 smbw->size = sizeof (smbw->u.co); | |
103 break; | |
104 case SMBL_VC: | |
105 smbw->size = sizeof (smbw->u.vc); | |
106 break; | |
107 case SMBL_SHARE: | |
108 smbw->size = sizeof (smbw->u.ss); | |
109 break; | |
110 default: | |
111 smbw->size = sizeof (smbw->u); | |
112 break; | |
113 } | |
114 | |
115 /* | |
116 * Read in the parent object. Just need the | |
117 * invariant part (smb_connobj_t) so we can | |
118 * get the list of children below it. | |
119 */ | |
120 psz = sizeof (smbw->u.co); | |
121 if (mdb_vread(&smbw->u.co, psz, smbw->pp) != psz) { | |
122 mdb_warn("cannot read connobj from %p", smbw->pp); | |
123 return (WALK_ERR); | |
124 } | |
125 | |
126 /* | |
127 * Finally, setup to walk the list of children. | |
128 */ | |
129 wsp->walk_addr = (uintptr_t)smbw->u.co.co_children.slh_first; | |
130 | |
131 return (WALK_NEXT); | |
132 } | |
133 | |
134 /* | |
135 * Walk the (global) VC list. | |
136 */ | |
137 int | |
138 smb_vc_walk_init(mdb_walk_state_t *wsp) | |
139 { | |
140 GElf_Sym sym; | |
141 | |
142 if (wsp->walk_addr != NULL) { | |
143 mdb_warn("::walk smb_vc only supports global walks\n"); | |
144 return (WALK_ERR); | |
145 } | |
146 | |
147 /* Locate the VC list head. */ | |
148 if (mdb_lookup_by_obj("nsmb", "smb_vclist", &sym)) { | |
149 mdb_warn("failed to lookup `smb_vclist'\n"); | |
150 return (WALK_ERR); | |
151 } | |
152 wsp->walk_addr = sym.st_value; | |
153 | |
154 return (smb_co_walk_init(wsp, SMBL_VC)); | |
155 } | |
156 | |
157 /* | |
158 * Walk the share list below some VC. | |
159 */ | |
160 int | |
161 smb_ss_walk_init(mdb_walk_state_t *wsp) | |
162 { | |
163 | |
164 /* | |
165 * Initial walk_addr is address of parent (VC) | |
166 */ | |
167 if (wsp->walk_addr == 0) { | |
168 mdb_warn("::walk smb_ss does not support global walks\n"); | |
169 return (WALK_ERR); | |
170 } | |
171 | |
172 return (smb_co_walk_init(wsp, SMBL_SHARE)); | |
173 } | |
174 | |
175 /* | |
176 * Common walk_step for walking structs inherited | |
177 * from smb_connobj_t (smb_vc_t, smb_share_t) | |
178 */ | |
179 int | |
180 smb_co_walk_step(mdb_walk_state_t *wsp) | |
181 { | |
182 smb_co_walk_data_t *smbw = wsp->walk_data; | |
183 int status; | |
184 | |
185 if (wsp->walk_addr == NULL) | |
186 return (WALK_DONE); | |
187 | |
188 if (mdb_vread(&smbw->u, smbw->size, wsp->walk_addr) | |
189 != smbw->size) { | |
190 mdb_warn("cannot read connobj from %p", wsp->walk_addr); | |
191 return (WALK_ERR); | |
192 } | |
193 | |
194 /* XXX: Sanity check level? parent pointer? */ | |
195 | |
196 status = wsp->walk_callback(wsp->walk_addr, &smbw->u, | |
197 wsp->walk_cbdata); | |
198 | |
199 wsp->walk_addr = (uintptr_t)smbw->u.co.co_next.sle_next; | |
200 | |
201 return (status); | |
202 } | |
203 | |
204 | |
205 /* | |
206 * Dcmd (and callback function) to print a summary of | |
207 * all VCs, and optionally all shares under each VC. | |
208 */ | |
209 | |
210 typedef struct smb_co_cbdata { | |
211 int flags; /* OPT_... */ | |
212 int printed_header; | |
213 } smb_co_cbdata_t; | |
214 | |
215 /* | |
216 * Call-back function for walking a share list. | |
217 */ | |
218 int | |
219 smb_ss_cb(uintptr_t addr, const void *data, void *arg) | |
220 { | |
221 const smb_share_t *ssp = data; | |
222 smb_co_cbdata_t *cbd = arg; | |
223 | |
224 mdb_printf(" %-p", addr); | |
225 print_str((uintptr_t)ssp->ss_name); | |
226 mdb_printf("\n"); | |
227 | |
228 if (cbd->flags & OPT_VERBOSE) { | |
229 mdb_inc_indent(2); | |
230 /* Anything wanted here? */ | |
231 mdb_dec_indent(2); | |
232 } | |
233 | |
234 return (WALK_NEXT); | |
235 } | |
236 | |
237 /* | |
238 * Call-back function for walking the VC list. | |
239 */ | |
240 int | |
241 smb_vc_cb(uintptr_t addr, const void *data, void *arg) | |
242 { | |
243 const smb_vc_t *vcp = data; | |
244 smb_co_cbdata_t *cbd = arg; | |
245 | |
246 if (cbd->printed_header == 0) { | |
247 cbd->printed_header = 1; | |
248 mdb_printf("// smb_vc_t uid server user\n"); | |
249 } | |
250 | |
251 mdb_printf("%-p", addr); | |
252 mdb_printf(" %d", vcp->vc_uid); | |
253 print_str((uintptr_t)vcp->vc_srvname); | |
254 print_str((uintptr_t)vcp->vc_username); | |
255 mdb_printf("\n"); | |
256 | |
257 if (cbd->flags & OPT_RECURSE) { | |
258 mdb_inc_indent(2); | |
259 if (mdb_pwalk("nsmb_ss", smb_ss_cb, cbd, addr) < 0) { | |
260 mdb_warn("failed to walk 'nsmb_ss'"); | |
261 /* Don't: return (WALK_ERR); */ | |
262 } | |
263 mdb_dec_indent(2); | |
264 } | |
265 | |
266 return (WALK_NEXT); | |
267 } | |
268 | |
269 int | |
270 smb_vc_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) | |
271 { | |
272 smb_co_cbdata_t cbd; | |
273 smb_vc_t *vcp; | |
274 size_t vcsz; | |
275 | |
276 memset(&cbd, 0, sizeof (cbd)); | |
277 | |
278 if (mdb_getopts(argc, argv, | |
279 'r', MDB_OPT_SETBITS, OPT_RECURSE, &cbd.flags, | |
280 'v', MDB_OPT_SETBITS, OPT_VERBOSE, &cbd.flags, | |
281 NULL) != argc) { | |
282 return (DCMD_USAGE); | |
283 } | |
284 | |
285 if (!(flags & DCMD_ADDRSPEC)) { | |
286 if (mdb_walk("nsmb_vc", smb_vc_cb, &cbd) == -1) { | |
287 mdb_warn("failed to walk 'nsmb_vc'"); | |
288 return (DCMD_ERR); | |
289 } | |
290 return (DCMD_OK); | |
291 } | |
292 | |
293 vcsz = sizeof (*vcp); | |
294 vcp = mdb_alloc(vcsz, UM_SLEEP | UM_GC); | |
295 if (mdb_vread(vcp, vcsz, addr) != vcsz) { | |
296 mdb_warn("cannot read VC from %p", addr); | |
297 return (DCMD_ERR); | |
298 } | |
299 smb_vc_cb(addr, vcp, &cbd); | |
300 | |
301 return (DCMD_OK); | |
302 } | |
303 | |
304 void | |
305 smb_vc_help(void) | |
306 { | |
307 mdb_printf("Options:\n" | |
308 " -r recursive display of share lists\n" | |
309 " -v be verbose when displaying smb_vc\n"); | |
310 } | |
311 | |
312 /* | |
313 * Walker for the request list on a VC, | |
314 * and dcmd to show a summary. | |
315 */ | |
316 int | |
317 rqlist_walk_init(mdb_walk_state_t *wsp) | |
318 { | |
319 struct smb_rqhead rqh; | |
320 uintptr_t addr; | |
321 | |
322 /* | |
323 * Initial walk_addr is the address of the VC. | |
324 * Add offsetof(iod_rqlist) to get the rqhead. | |
325 */ | |
326 if (wsp->walk_addr == 0) { | |
327 mdb_warn("::walk smb_ss does not support global walks\n"); | |
328 return (WALK_ERR); | |
329 } | |
330 addr = wsp->walk_addr; | |
331 addr += OFFSETOF(smb_vc_t, iod_rqlist); | |
332 | |
333 if (mdb_vread(&rqh, sizeof (rqh), addr) == -1) { | |
334 mdb_warn("failed to read smb_rqhead at %p", addr); | |
335 return (WALK_ERR); | |
336 } | |
337 wsp->walk_addr = (uintptr_t)rqh.tqh_first; | |
338 | |
339 return (WALK_NEXT); | |
340 } | |
341 | |
342 int | |
343 rqlist_walk_step(mdb_walk_state_t *wsp) | |
344 { | |
345 smb_rq_t rq; | |
346 int status; | |
347 | |
348 if (wsp->walk_addr == NULL) | |
349 return (WALK_DONE); | |
350 | |
351 if (mdb_vread(&rq, sizeof (rq), wsp->walk_addr) == -1) { | |
352 mdb_warn("cannot read smb_rq from %p", wsp->walk_addr); | |
353 return (WALK_ERR); | |
354 } | |
355 | |
356 status = wsp->walk_callback(wsp->walk_addr, &rq, | |
357 wsp->walk_cbdata); | |
358 | |
359 wsp->walk_addr = (uintptr_t)rq.sr_link.tqe_next; | |
360 | |
361 return (status); | |
362 } | |
363 | |
364 typedef struct rqlist_cbdata { | |
365 int printed_header; | |
366 uintptr_t uid; /* optional filtering by UID */ | |
367 } rqlist_cbdata_t; | |
368 | |
369 int | |
370 rqlist_cb(uintptr_t addr, const void *data, void *arg) | |
371 { | |
372 const smb_rq_t *rq = data; | |
373 rqlist_cbdata_t *cbd = arg; | |
374 | |
375 if (cbd->printed_header == 0) { | |
376 cbd->printed_header = 1; | |
377 mdb_printf("// smb_rq_t MID cmd sr_state sr_flags\n"); | |
378 } | |
379 | |
380 mdb_printf(" %-p", addr); /* smb_rq_t */ | |
381 mdb_printf(" x%04x", rq->sr_mid); | |
382 mdb_printf(" x%02x", rq->sr_cmd); | |
383 mdb_printf(" %d", rq->sr_state); | |
384 mdb_printf(" x%x", rq->sr_flags); | |
385 mdb_printf("\n"); | |
386 | |
387 return (WALK_NEXT); | |
388 } | |
389 | |
390 /*ARGSUSED*/ | |
391 int | |
392 rqlist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) | |
393 { | |
394 rqlist_cbdata_t cbd; | |
395 | |
396 memset(&cbd, 0, sizeof (cbd)); | |
397 | |
398 /* | |
399 * Initial walk_addr is address of parent (VC) | |
400 */ | |
401 if (!(flags & DCMD_ADDRSPEC)) { | |
402 mdb_warn("address required\n"); | |
403 return (DCMD_ERR); | |
404 } | |
405 | |
406 if (mdb_pwalk("nsmb_rqlist", rqlist_cb, &cbd, addr) == -1) { | |
407 mdb_warn("failed to walk 'nsmb_rqlist'"); | |
408 return (DCMD_ERR); | |
409 } | |
410 | |
411 return (DCMD_OK); | |
412 } | |
413 | |
414 | |
415 /* | |
416 * AVL walker for the passwords AVL tree, | |
417 * and dcmd to show a summary. | |
418 */ | |
419 static int | |
420 pwtree_walk_init(mdb_walk_state_t *wsp) | |
421 { | |
422 GElf_Sym sym; | |
423 | |
424 if (wsp->walk_addr != NULL) { | |
425 mdb_warn("pwtree walk only supports global walks\n"); | |
426 return (WALK_ERR); | |
427 } | |
428 | |
429 if (mdb_lookup_by_obj("nsmb", "smb_ptd", &sym) == -1) { | |
430 mdb_warn("failed to find symbol 'smb_ptd'"); | |
431 return (WALK_ERR); | |
432 } | |
433 | |
434 wsp->walk_addr = (uintptr_t)sym.st_value; | |
435 | |
436 if (mdb_layered_walk("avl", wsp) == -1) { | |
437 mdb_warn("failed to walk 'avl'\n"); | |
438 return (WALK_ERR); | |
439 } | |
440 | |
441 return (WALK_NEXT); | |
442 } | |
443 | |
444 static int | |
445 pwtree_walk_step(mdb_walk_state_t *wsp) | |
446 { | |
447 smb_passid_t ptnode; | |
448 | |
449 if (mdb_vread(&ptnode, sizeof (ptnode), wsp->walk_addr) == -1) { | |
450 mdb_warn("failed to read smb_passid_t at %p", wsp->walk_addr); | |
451 return (WALK_ERR); | |
452 } | |
453 | |
454 return (wsp->walk_callback(wsp->walk_addr, &ptnode, wsp->walk_cbdata)); | |
455 } | |
456 | |
457 typedef struct pwtree_cbdata { | |
458 int printed_header; | |
459 uid_t uid; /* optional filtering by UID */ | |
460 } pwtree_cbdata_t; | |
461 | |
462 int | |
463 pwtree_cb(uintptr_t addr, const void *data, void *arg) | |
464 { | |
465 const smb_passid_t *ptn = data; | |
466 pwtree_cbdata_t *cbd = arg; | |
467 | |
468 /* Optional filtering by UID. */ | |
469 if (cbd->uid != (uid_t)-1 && cbd->uid != ptn->uid) { | |
470 return (WALK_NEXT); | |
471 } | |
472 | |
473 if (cbd->printed_header == 0) { | |
474 cbd->printed_header = 1; | |
475 mdb_printf("// smb_passid_t UID domain user\n"); | |
476 } | |
477 | |
478 mdb_printf(" %-p", addr); /* smb_passid_t */ | |
479 mdb_printf(" %d", (uintptr_t)ptn->uid); | |
480 print_str((uintptr_t)ptn->srvdom); | |
481 print_str((uintptr_t)ptn->username); | |
482 mdb_printf("\n"); | |
483 | |
484 return (WALK_NEXT); | |
485 } | |
486 | |
487 /*ARGSUSED*/ | |
488 int | |
489 pwtree_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) | |
490 { | |
491 pwtree_cbdata_t cbd; | |
492 char *uid_str = NULL; | |
493 char buf[32]; | |
494 | |
495 memset(&cbd, 0, sizeof (cbd)); | |
496 | |
497 if (mdb_getopts(argc, argv, | |
498 'u', MDB_OPT_STR, &uid_str, NULL) != argc) { | |
499 return (DCMD_USAGE); | |
500 } | |
501 if (uid_str) { | |
502 /* | |
503 * Want the the default radix to be 10 here. | |
504 * If the string has some kind of radix prefix, | |
505 * just use that as-is, otherwise prepend "0t". | |
506 * Cheating on the "not a digit" test, but | |
507 * mdb_strtoull will do a real syntax check. | |
508 */ | |
509 if (uid_str[0] == '0' && uid_str[1] > '9') { | |
510 cbd.uid = (uid_t)mdb_strtoull(uid_str); | |
511 } else { | |
512 strcpy(buf, "0t"); | |
513 strlcat(buf, uid_str, sizeof (buf)); | |
514 cbd.uid = (uid_t)mdb_strtoull(buf); | |
515 } | |
516 } else | |
517 cbd.uid = (uid_t)-1; | |
518 | |
519 if (flags & DCMD_ADDRSPEC) { | |
520 mdb_warn("address not allowed\n"); | |
521 return (DCMD_ERR); | |
522 } | |
523 | |
524 if (mdb_pwalk("nsmb_pwtree", pwtree_cb, &cbd, 0) == -1) { | |
525 mdb_warn("failed to walk 'nsmb_pwtree'"); | |
526 return (DCMD_ERR); | |
527 } | |
528 | |
529 return (DCMD_OK); | |
530 } | |
531 | |
532 void | |
533 pwtree_help(void) | |
534 { | |
535 mdb_printf("Options:\n" | |
536 " -u uid show only entries belonging to uid (decimal)\n"); | |
537 } | |
538 | |
539 | |
540 static const mdb_dcmd_t dcmds[] = { | |
541 { "nsmb_vc", "?[-rv]", | |
542 "show smb_vc (or list)", | |
543 smb_vc_dcmd, smb_vc_help }, | |
544 { "nsmb_rqlist", ":", | |
545 "show smb_rq list on a VC", | |
546 rqlist_dcmd, NULL }, | |
547 { "nsmb_pwtree", "?[-u uid]", | |
548 "list smb_passid_t (password tree)", | |
549 pwtree_dcmd, pwtree_help }, | |
550 {NULL} | |
551 }; | |
552 | |
553 static const mdb_walker_t walkers[] = { | |
554 { "nsmb_vc", "walk nsmb VC list", | |
555 smb_vc_walk_init, smb_co_walk_step, NULL }, | |
556 { "nsmb_ss", "walk nsmb share list for some VC", | |
557 smb_ss_walk_init, smb_co_walk_step, NULL }, | |
558 { "nsmb_rqlist", "walk request list for some VC", | |
559 rqlist_walk_init, rqlist_walk_step, NULL }, | |
560 { "nsmb_pwtree", "walk passord AVL tree", | |
561 pwtree_walk_init, pwtree_walk_step, NULL }, | |
562 {NULL} | |
563 }; | |
564 | |
565 static const mdb_modinfo_t modinfo = { | |
566 MDB_API_VERSION, | |
567 dcmds, | |
568 walkers | |
569 }; | |
570 | |
571 const mdb_modinfo_t * | |
572 _mdb_init(void) | |
573 { | |
574 return (&modinfo); | |
575 } |