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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/types.h>
27 #include <sys/rwlock.h>
28 #include <mdb/mdb_modapi.h>
29 #include <sys/queue.h>
30 #include <inet/ip.h>
31 #include <sys/hook.h>
32 #include <sys/hook_impl.h>
33
34 #define MAX_LENGTH 64
35
36 /*
37 * List pfhooks hook list information.
38 */
39 /*ARGSUSED*/
40 int
hooklist(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)41 hooklist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
42 {
43 hook_event_int_t hr;
44 hook_int_t hl, *hlp;
45 char hrstr[MAX_LENGTH];
46 GElf_Sym sym;
47 char buf[MDB_SYM_NAMLEN + 1];
48 char *hintname;
49 hook_t *h;
50
51 if (argc)
52 return (DCMD_USAGE);
53
54 if (mdb_vread((void *)&hr, sizeof (hr), (uintptr_t)addr) == -1) {
55 mdb_warn("couldn't read hook register at %p", addr);
56 return (DCMD_ERR);
57 }
58
59 mdb_printf("%<u>%?s %8s %20s %4s %24s %24s%</u>\n",
60 "ADDR", "FLAG", "FUNC", "HINT", "NAME", "HINTVALUE");
61 h = &hl.hi_hook;
62 hlp = TAILQ_FIRST(&hr.hei_head);
63 while (hlp) {
64 if (mdb_vread((void *)&hl, sizeof (hl),
65 (uintptr_t)hlp) == -1) {
66 mdb_warn("couldn't read hook list at %p",
67 hlp);
68 return (DCMD_ERR);
69 }
70 if (!h->h_name) {
71 mdb_warn("hook list at %p has null role", h);
72 return (DCMD_ERR);
73 }
74 if (mdb_readstr((char *)hrstr, sizeof (hrstr),
75 (uintptr_t)h->h_name) == -1) {
76 mdb_warn("couldn't read list role at %p", h->h_name);
77 return (DCMD_ERR);
78 }
79 switch (h->h_hint) {
80 case HH_BEFORE :
81 case HH_AFTER :
82 hintname = h->h_hintvalue ?
83 (char *)h->h_hintvalue : "";
84 break;
85 default :
86 hintname = "";
87 break;
88 }
89 if (mdb_lookup_by_addr((uintptr_t)h->h_func,
90 MDB_SYM_EXACT, buf, sizeof (buf), &sym) == -1)
91 mdb_printf("%0?p %8x %0?p %4d %24s %24s\n",
92 hlp, h->h_flags, h->h_func,
93 h->h_hint, hrstr, hintname);
94 else
95 mdb_printf("%0?p %8x %20s %4d %24s %24s\n",
96 hlp, h->h_flags, buf,
97 h->h_hint, hrstr, hintname);
98 hlp = TAILQ_NEXT(&hl, hi_entry);
99 }
100 return (DCMD_OK);
101 }
102
103 /*
104 * List pfhooks event information.
105 * List the hooks information in verbose mode as well.
106 */
107 /*ARGSUSED*/
108 int
hookeventlist(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)109 hookeventlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
110 {
111 hook_family_int_t hf;
112 hook_event_int_t hr, *hrp;
113 hook_event_t hp;
114 char hprstr[MAX_LENGTH];
115
116 if (argc)
117 return (DCMD_USAGE);
118
119 if (mdb_vread((void *)&hf, sizeof (hf), (uintptr_t)addr) == -1) {
120 mdb_warn("couldn't read hook family at %p", addr);
121 return (DCMD_ERR);
122 }
123
124 mdb_printf("%<u>%?s %10s %20s%</u>\n", "ADDR", "FLAG", "NAME");
125 hrp = SLIST_FIRST(&hf.hfi_head);
126 while (hrp) {
127 if (mdb_vread((void *)&hr, sizeof (hr), (uintptr_t)hrp) == -1) {
128 mdb_warn("couldn't read hook register at %p", hrp);
129 return (DCMD_ERR);
130 }
131 if (!hr.hei_event) {
132 mdb_warn("hook register at %p has no hook provider",
133 hrp);
134 return (DCMD_ERR);
135 }
136 if (mdb_vread((void *)&hp, sizeof (hp),
137 (uintptr_t)hr.hei_event) == -1) {
138 mdb_warn("hook provider at %p has null role",
139 hr.hei_event);
140 return (DCMD_ERR);
141 }
142 if (!hp.he_name) {
143 mdb_warn("hook provider at %p has null role",
144 hr.hei_event);
145 return (DCMD_ERR);
146 }
147 if (mdb_readstr((char *)hprstr, sizeof (hprstr),
148 (uintptr_t)hp.he_name) == -1) {
149 mdb_warn("couldn't read provider role at %p",
150 hp.he_name);
151 return (DCMD_ERR);
152 }
153 mdb_printf("%0?p %10x %20s\n", hrp, hp.he_flags, hprstr);
154 hrp = SLIST_NEXT(&hr, hei_entry);
155 }
156
157 return (DCMD_OK);
158 }
159
160 /*
161 * List pfhooks family information.
162 */
163 /*ARGSUSED*/
164 int
hookrootlist(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)165 hookrootlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
166 {
167 struct hook_stack *hks;
168 hook_family_int_head_t hfh;
169 hook_family_int_t hf, *hfp;
170 char hrrstr[MAX_LENGTH];
171
172 if (argc)
173 return (DCMD_USAGE);
174
175 if (mdb_vread((void *)&hks, sizeof (hks),
176 (uintptr_t)(addr + OFFSETOF(netstack_t, netstack_hook))) == -1) {
177 mdb_warn("couldn't read netstack_hook");
178 return (DCMD_ERR);
179 }
180
181 if (mdb_vread((void *)&hfh, sizeof (hfh), (uintptr_t)((uintptr_t)hks +
182 OFFSETOF(hook_stack_t, hks_familylist))) == -1) {
183 mdb_warn("couldn't read hook family head");
184 return (DCMD_ERR);
185 }
186
187 mdb_printf("%<u>%?s %10s%</u>\n", "ADDR", "FAMILY");
188 hfp = SLIST_FIRST(&hfh);
189 while (hfp) {
190 if (mdb_vread((void *)&hf, sizeof (hf), (uintptr_t)hfp) == -1) {
191 mdb_warn("couldn't read hook family at %p", hfp);
192 return (DCMD_ERR);
193 }
194 if (!hf.hfi_family.hf_name) {
195 mdb_warn("hook root at %p has null role",
196 hf.hfi_family);
197 return (DCMD_ERR);
198 }
199 if (mdb_readstr((char *)hrrstr, sizeof (hrrstr),
200 (uintptr_t)hf.hfi_family.hf_name) == -1) {
201 mdb_warn("couldn't read root role at %p",
202 hf.hfi_family.hf_name);
203 return (DCMD_ERR);
204 }
205 mdb_printf("%0?p %10s\n", hfp, hrrstr);
206 hfp = SLIST_NEXT(&hf, hfi_entry);
207 }
208
209 return (DCMD_OK);
210 }
211
212
213 static int
hookevent_stack_walk_init(mdb_walk_state_t * wsp)214 hookevent_stack_walk_init(mdb_walk_state_t *wsp)
215 {
216 hook_family_int_t hf;
217
218 if (wsp->walk_addr == NULL) {
219 mdb_warn("global walk not supported\n");
220 return (WALK_ERR);
221 }
222
223 if (mdb_vread((void *)&hf, sizeof (hf),
224 (uintptr_t)wsp->walk_addr) == -1) {
225 mdb_warn("couldn't read hook family at %p", wsp->walk_addr);
226 return (DCMD_ERR);
227 }
228 wsp->walk_addr = (uintptr_t)SLIST_FIRST(&hf.hfi_head);
229 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
230 wsp->walk_cbdata));
231 }
232
233 static int
hookevent_stack_walk_step(mdb_walk_state_t * wsp)234 hookevent_stack_walk_step(mdb_walk_state_t *wsp)
235 {
236 hook_event_int_t hr;
237
238 if (mdb_vread((void *)&hr, sizeof (hr),
239 (uintptr_t)wsp->walk_addr) == -1) {
240 mdb_warn("couldn't read hook event at %p", wsp->walk_addr);
241 return (DCMD_ERR);
242 }
243 wsp->walk_addr = (uintptr_t)SLIST_NEXT(&hr, hei_entry);
244 if (wsp->walk_addr == NULL)
245 return (WALK_DONE);
246 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
247 wsp->walk_cbdata));
248 }
249
250 static const mdb_dcmd_t dcmds[] = {
251 { "hookrootlist", "", "display hook family information", hookrootlist },
252 { "hookeventlist", "", "display hook event information",
253 hookeventlist, NULL },
254 { "hooklist", "", "display hooks", hooklist },
255 { NULL }
256 };
257
258 static const mdb_walker_t walkers[] = {
259 { "hookevent_stack", "walk list of hooks",
260 hookevent_stack_walk_init, hookevent_stack_walk_step, NULL },
261 { NULL }
262 };
263
264 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
265
266 const mdb_modinfo_t *
_mdb_init(void)267 _mdb_init(void)
268 {
269 return (&modinfo);
270 }
271