1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
14  */
15 
16 /*
17  * walker for libsmb : smb_ht.c (hash tables)
18  */
19 
20 #include <mdb/mdb_modapi.h>
21 #include <mdb/mdb_ks.h>
22 #include <mdb/mdb_ctf.h>
23 
24 #include <smbsrv/hash_table.h>
25 
26 /* smb_ht_walk info */
27 struct hw_info {
28 	HT_HANDLE hw_handle;	/* struct ht_handle being walked */
29 	HT_TABLE_ENTRY hw_tblent;
30 	HT_ITEM hw_item;
31 	int hw_idx;
32 };
33 
34 /*
35  * Walker for libsmb/smb_ht.c code.  Calls the call-back function with
36  * each HT_ITEM object.  Top-level is HT_HANDLE, passed to _walk_init.
37  */
38 int
39 smb_ht_walk_init(mdb_walk_state_t *wsp)
40 {
41 	struct hw_info *hw;
42 	uintptr_t addr = wsp->walk_addr;
43 	HT_HANDLE *ht;
44 
45 	if (addr == 0) {
46 		mdb_printf("require address of an HT_HANDLE\n");
47 		return (WALK_ERR);
48 	}
49 
50 	/*
51 	 * allocate the AVL walk data
52 	 */
53 	wsp->walk_data = hw = mdb_zalloc(sizeof (*hw), UM_GC|UM_SLEEP);
54 
55 	/*
56 	 * get an mdb copy of the HT_HANDLE being walked
57 	 */
58 	ht = &hw->hw_handle;
59 	if (mdb_vread(ht, sizeof (*ht), wsp->walk_addr) == -1) {
60 		mdb_warn("failed to read %s at %#lx",
61 		    "HT_HANDLE", wsp->walk_addr);
62 		return (WALK_ERR);
63 	}
64 
65 	hw->hw_idx = -1;
66 	wsp->walk_addr = 0;
67 	wsp->walk_data = hw;
68 
69 	return (WALK_NEXT);
70 }
71 
72 int
73 smb_ht_walk_step(mdb_walk_state_t *wsp)
74 {
75 	struct hw_info *hw = wsp->walk_data;
76 	HT_TABLE_ENTRY *he = &hw->hw_tblent;
77 	HT_ITEM *hi = &hw->hw_item;
78 	uintptr_t he_addr;
79 	int rv;
80 
81 	while (wsp->walk_addr == 0) {
82 		if (++hw->hw_idx >= hw->hw_handle.ht_table_size)
83 			return (WALK_DONE);
84 		he_addr = (uintptr_t)hw->hw_handle.ht_table +
85 		    (hw->hw_idx * sizeof (HT_TABLE_ENTRY));
86 		if (mdb_vread(he, sizeof (*he), he_addr) == -1) {
87 			mdb_warn("failed to read %s at %p",
88 			    "HT_TABLE_ENTRY", wsp->walk_addr);
89 			return (WALK_ERR);
90 		}
91 		wsp->walk_addr = (uintptr_t)he->he_head;
92 	}
93 
94 	if (mdb_vread(hi, sizeof (*hi), wsp->walk_addr) == -1) {
95 		mdb_warn("failed to read %s at %p",
96 		    "HT_ITEM", wsp->walk_addr);
97 		return (WALK_ERR);
98 	}
99 
100 	rv = wsp->walk_callback(wsp->walk_addr, hi,
101 	    wsp->walk_cbdata);
102 
103 	wsp->walk_addr = (uintptr_t)hi->hi_next;
104 
105 	return (rv);
106 }
107