xref: /titanic_50/usr/src/cmd/mdb/common/modules/hook/hook.c (revision 7ddc9b1afd18f260b9fb78ec7732facd91769131)
1381a2a9aSdr146992 /*
2381a2a9aSdr146992  * CDDL HEADER START
3381a2a9aSdr146992  *
4381a2a9aSdr146992  * The contents of this file are subject to the terms of the
5381a2a9aSdr146992  * Common Development and Distribution License (the "License").
6381a2a9aSdr146992  * You may not use this file except in compliance with the License.
7381a2a9aSdr146992  *
8381a2a9aSdr146992  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9381a2a9aSdr146992  * or http://www.opensolaris.org/os/licensing.
10381a2a9aSdr146992  * See the License for the specific language governing permissions
11381a2a9aSdr146992  * and limitations under the License.
12381a2a9aSdr146992  *
13381a2a9aSdr146992  * When distributing Covered Code, include this CDDL HEADER in each
14381a2a9aSdr146992  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15381a2a9aSdr146992  * If applicable, add the following below this CDDL HEADER, with the
16381a2a9aSdr146992  * fields enclosed by brackets "[]" replaced with your own identifying
17381a2a9aSdr146992  * information: Portions Copyright [yyyy] [name of copyright owner]
18381a2a9aSdr146992  *
19381a2a9aSdr146992  * CDDL HEADER END
20381a2a9aSdr146992  */
21381a2a9aSdr146992 /*
22*7ddc9b1aSDarren Reed  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23381a2a9aSdr146992  * Use is subject to license terms.
24381a2a9aSdr146992  */
25381a2a9aSdr146992 
26381a2a9aSdr146992 #include <sys/types.h>
27381a2a9aSdr146992 #include <sys/rwlock.h>
28381a2a9aSdr146992 #include <mdb/mdb_modapi.h>
29381a2a9aSdr146992 #include <sys/queue.h>
30f4b3ec61Sdh155122 #include <inet/ip.h>
31381a2a9aSdr146992 #include <sys/hook.h>
32381a2a9aSdr146992 #include <sys/hook_impl.h>
33381a2a9aSdr146992 
34381a2a9aSdr146992 #define	MAX_LENGTH 64
35381a2a9aSdr146992 
36381a2a9aSdr146992 /*
37381a2a9aSdr146992  * List pfhooks hook list information.
38381a2a9aSdr146992  */
39381a2a9aSdr146992 /*ARGSUSED*/
40381a2a9aSdr146992 int
hooklist(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)41381a2a9aSdr146992 hooklist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
42381a2a9aSdr146992 {
43381a2a9aSdr146992 	hook_event_int_t hr;
44381a2a9aSdr146992 	hook_int_t hl, *hlp;
45381a2a9aSdr146992 	char hrstr[MAX_LENGTH];
46381a2a9aSdr146992 	GElf_Sym sym;
47381a2a9aSdr146992 	char buf[MDB_SYM_NAMLEN + 1];
48*7ddc9b1aSDarren Reed 	char *hintname;
49*7ddc9b1aSDarren Reed 	hook_t *h;
50381a2a9aSdr146992 
51381a2a9aSdr146992 	if (argc)
52381a2a9aSdr146992 		return (DCMD_USAGE);
53381a2a9aSdr146992 
54381a2a9aSdr146992 	if (mdb_vread((void *)&hr, sizeof (hr), (uintptr_t)addr) == -1) {
55381a2a9aSdr146992 		mdb_warn("couldn't read hook register at %p", addr);
56381a2a9aSdr146992 		return (DCMD_ERR);
57381a2a9aSdr146992 	}
58381a2a9aSdr146992 
59*7ddc9b1aSDarren Reed 	mdb_printf("%<u>%?s %8s %20s %4s %24s %24s%</u>\n",
60*7ddc9b1aSDarren Reed 	    "ADDR", "FLAG", "FUNC", "HINT", "NAME", "HINTVALUE");
61*7ddc9b1aSDarren Reed 	h = &hl.hi_hook;
62381a2a9aSdr146992 	hlp = TAILQ_FIRST(&hr.hei_head);
63381a2a9aSdr146992 	while (hlp) {
64381a2a9aSdr146992 		if (mdb_vread((void *)&hl, sizeof (hl),
65381a2a9aSdr146992 		    (uintptr_t)hlp) == -1) {
66381a2a9aSdr146992 			mdb_warn("couldn't read hook list at %p",
67381a2a9aSdr146992 			    hlp);
68381a2a9aSdr146992 			return (DCMD_ERR);
69381a2a9aSdr146992 		}
70*7ddc9b1aSDarren Reed 		if (!h->h_name) {
71*7ddc9b1aSDarren Reed 			mdb_warn("hook list at %p has null role", h);
72381a2a9aSdr146992 			return (DCMD_ERR);
73381a2a9aSdr146992 		}
74381a2a9aSdr146992 		if (mdb_readstr((char *)hrstr, sizeof (hrstr),
75*7ddc9b1aSDarren Reed 		    (uintptr_t)h->h_name) == -1) {
76*7ddc9b1aSDarren Reed 			mdb_warn("couldn't read list role at %p", h->h_name);
77381a2a9aSdr146992 			return (DCMD_ERR);
78381a2a9aSdr146992 		}
79*7ddc9b1aSDarren Reed 		switch (h->h_hint) {
80*7ddc9b1aSDarren Reed 		case HH_BEFORE :
81*7ddc9b1aSDarren Reed 		case HH_AFTER :
82*7ddc9b1aSDarren Reed 			hintname =  h->h_hintvalue ?
83*7ddc9b1aSDarren Reed 			    (char *)h->h_hintvalue : "";
84*7ddc9b1aSDarren Reed 			break;
85*7ddc9b1aSDarren Reed 		default :
86*7ddc9b1aSDarren Reed 			hintname = "";
87*7ddc9b1aSDarren Reed 			break;
88*7ddc9b1aSDarren Reed 		}
89*7ddc9b1aSDarren Reed 		if (mdb_lookup_by_addr((uintptr_t)h->h_func,
90381a2a9aSdr146992 		    MDB_SYM_EXACT, buf, sizeof (buf), &sym) == -1)
91*7ddc9b1aSDarren Reed 			mdb_printf("%0?p %8x %0?p %4d %24s %24s\n",
92*7ddc9b1aSDarren Reed 			    hlp, h->h_flags, h->h_func,
93*7ddc9b1aSDarren Reed 			    h->h_hint, hrstr, hintname);
94381a2a9aSdr146992 		else
95*7ddc9b1aSDarren Reed 			mdb_printf("%0?p %8x %20s %4d %24s %24s\n",
96*7ddc9b1aSDarren Reed 			    hlp, h->h_flags, buf,
97*7ddc9b1aSDarren Reed 			    h->h_hint, hrstr, hintname);
98381a2a9aSdr146992 		hlp = TAILQ_NEXT(&hl, hi_entry);
99381a2a9aSdr146992 	}
100381a2a9aSdr146992 	return (DCMD_OK);
101381a2a9aSdr146992 }
102381a2a9aSdr146992 
103381a2a9aSdr146992 /*
104381a2a9aSdr146992  * List pfhooks event information.
105381a2a9aSdr146992  * List the hooks information in verbose mode as well.
106381a2a9aSdr146992  */
107381a2a9aSdr146992 /*ARGSUSED*/
108381a2a9aSdr146992 int
hookeventlist(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)109381a2a9aSdr146992 hookeventlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
110381a2a9aSdr146992 {
111381a2a9aSdr146992 	hook_family_int_t hf;
112381a2a9aSdr146992 	hook_event_int_t hr, *hrp;
113381a2a9aSdr146992 	hook_event_t hp;
114381a2a9aSdr146992 	char hprstr[MAX_LENGTH];
115381a2a9aSdr146992 
116381a2a9aSdr146992 	if (argc)
117381a2a9aSdr146992 		return (DCMD_USAGE);
118381a2a9aSdr146992 
119381a2a9aSdr146992 	if (mdb_vread((void *)&hf, sizeof (hf), (uintptr_t)addr) == -1) {
120381a2a9aSdr146992 		mdb_warn("couldn't read hook family at %p", addr);
121381a2a9aSdr146992 		return (DCMD_ERR);
122381a2a9aSdr146992 	}
123381a2a9aSdr146992 
124381a2a9aSdr146992 	mdb_printf("%<u>%?s %10s %20s%</u>\n", "ADDR", "FLAG", "NAME");
125381a2a9aSdr146992 	hrp = SLIST_FIRST(&hf.hfi_head);
126381a2a9aSdr146992 	while (hrp) {
127381a2a9aSdr146992 		if (mdb_vread((void *)&hr, sizeof (hr), (uintptr_t)hrp) == -1) {
128381a2a9aSdr146992 			mdb_warn("couldn't read hook register at %p", hrp);
129381a2a9aSdr146992 			return (DCMD_ERR);
130381a2a9aSdr146992 		}
131381a2a9aSdr146992 		if (!hr.hei_event) {
132381a2a9aSdr146992 			mdb_warn("hook register at %p has no hook provider",
133381a2a9aSdr146992 			    hrp);
134381a2a9aSdr146992 			return (DCMD_ERR);
135381a2a9aSdr146992 		}
136381a2a9aSdr146992 		if (mdb_vread((void *)&hp, sizeof (hp),
137381a2a9aSdr146992 		    (uintptr_t)hr.hei_event) == -1) {
138381a2a9aSdr146992 			mdb_warn("hook provider at %p has null role",
139381a2a9aSdr146992 			    hr.hei_event);
140381a2a9aSdr146992 			return (DCMD_ERR);
141381a2a9aSdr146992 		}
142381a2a9aSdr146992 		if (!hp.he_name) {
143381a2a9aSdr146992 			mdb_warn("hook provider at %p has null role",
144381a2a9aSdr146992 			    hr.hei_event);
145381a2a9aSdr146992 			return (DCMD_ERR);
146381a2a9aSdr146992 		}
147381a2a9aSdr146992 		if (mdb_readstr((char *)hprstr, sizeof (hprstr),
148381a2a9aSdr146992 		    (uintptr_t)hp.he_name) == -1) {
149381a2a9aSdr146992 			mdb_warn("couldn't read provider role at %p",
150381a2a9aSdr146992 			    hp.he_name);
151381a2a9aSdr146992 			return (DCMD_ERR);
152381a2a9aSdr146992 		}
153381a2a9aSdr146992 		mdb_printf("%0?p %10x %20s\n", hrp, hp.he_flags, hprstr);
154381a2a9aSdr146992 		hrp = SLIST_NEXT(&hr, hei_entry);
155381a2a9aSdr146992 	}
156381a2a9aSdr146992 
157381a2a9aSdr146992 	return (DCMD_OK);
158381a2a9aSdr146992 }
159381a2a9aSdr146992 
160381a2a9aSdr146992 /*
161381a2a9aSdr146992  * List pfhooks family information.
162381a2a9aSdr146992  */
163381a2a9aSdr146992 /*ARGSUSED*/
164381a2a9aSdr146992 int
hookrootlist(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)165381a2a9aSdr146992 hookrootlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
166381a2a9aSdr146992 {
167f4b3ec61Sdh155122 	struct hook_stack *hks;
168381a2a9aSdr146992 	hook_family_int_head_t hfh;
169381a2a9aSdr146992 	hook_family_int_t hf, *hfp;
170381a2a9aSdr146992 	char hrrstr[MAX_LENGTH];
171381a2a9aSdr146992 
172381a2a9aSdr146992 	if (argc)
173381a2a9aSdr146992 		return (DCMD_USAGE);
174381a2a9aSdr146992 
175f4b3ec61Sdh155122 	if (mdb_vread((void *)&hks, sizeof (hks),
176f4b3ec61Sdh155122 	    (uintptr_t)(addr + OFFSETOF(netstack_t, netstack_hook))) == -1) {
177f4b3ec61Sdh155122 		mdb_warn("couldn't read netstack_hook");
178f4b3ec61Sdh155122 		return (DCMD_ERR);
179f4b3ec61Sdh155122 	}
180f4b3ec61Sdh155122 
181f4b3ec61Sdh155122 	if (mdb_vread((void *)&hfh, sizeof (hfh), (uintptr_t)((uintptr_t)hks +
182f4b3ec61Sdh155122 	    OFFSETOF(hook_stack_t, hks_familylist))) == -1) {
183f4b3ec61Sdh155122 		mdb_warn("couldn't read hook family head");
184381a2a9aSdr146992 		return (DCMD_ERR);
185381a2a9aSdr146992 	}
186381a2a9aSdr146992 
187381a2a9aSdr146992 	mdb_printf("%<u>%?s %10s%</u>\n", "ADDR", "FAMILY");
188381a2a9aSdr146992 	hfp = SLIST_FIRST(&hfh);
189381a2a9aSdr146992 	while (hfp) {
190381a2a9aSdr146992 		if (mdb_vread((void *)&hf, sizeof (hf), (uintptr_t)hfp) == -1) {
191381a2a9aSdr146992 			mdb_warn("couldn't read hook family at %p", hfp);
192381a2a9aSdr146992 			return (DCMD_ERR);
193381a2a9aSdr146992 		}
194381a2a9aSdr146992 		if (!hf.hfi_family.hf_name) {
195381a2a9aSdr146992 			mdb_warn("hook root at %p has null role",
196381a2a9aSdr146992 			    hf.hfi_family);
197381a2a9aSdr146992 			return (DCMD_ERR);
198381a2a9aSdr146992 		}
199381a2a9aSdr146992 		if (mdb_readstr((char *)hrrstr, sizeof (hrrstr),
200381a2a9aSdr146992 		    (uintptr_t)hf.hfi_family.hf_name) == -1) {
201381a2a9aSdr146992 			mdb_warn("couldn't read root role at %p",
202381a2a9aSdr146992 			    hf.hfi_family.hf_name);
203381a2a9aSdr146992 			return (DCMD_ERR);
204381a2a9aSdr146992 		}
205381a2a9aSdr146992 		mdb_printf("%0?p %10s\n", hfp, hrrstr);
206381a2a9aSdr146992 		hfp = SLIST_NEXT(&hf, hfi_entry);
207381a2a9aSdr146992 	}
208381a2a9aSdr146992 
209381a2a9aSdr146992 	return (DCMD_OK);
210381a2a9aSdr146992 }
211381a2a9aSdr146992 
212381a2a9aSdr146992 
213381a2a9aSdr146992 static int
hookevent_stack_walk_init(mdb_walk_state_t * wsp)214f4b3ec61Sdh155122 hookevent_stack_walk_init(mdb_walk_state_t *wsp)
215381a2a9aSdr146992 {
216381a2a9aSdr146992 	hook_family_int_t hf;
217381a2a9aSdr146992 
218381a2a9aSdr146992 	if (wsp->walk_addr == NULL) {
219381a2a9aSdr146992 		mdb_warn("global walk not supported\n");
220381a2a9aSdr146992 		return (WALK_ERR);
221381a2a9aSdr146992 	}
222381a2a9aSdr146992 
223381a2a9aSdr146992 	if (mdb_vread((void *)&hf, sizeof (hf),
224381a2a9aSdr146992 	    (uintptr_t)wsp->walk_addr) == -1) {
225381a2a9aSdr146992 		mdb_warn("couldn't read hook family at %p", wsp->walk_addr);
226381a2a9aSdr146992 		return (DCMD_ERR);
227381a2a9aSdr146992 	}
228381a2a9aSdr146992 	wsp->walk_addr = (uintptr_t)SLIST_FIRST(&hf.hfi_head);
229381a2a9aSdr146992 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
230381a2a9aSdr146992 	    wsp->walk_cbdata));
231381a2a9aSdr146992 }
232381a2a9aSdr146992 
233381a2a9aSdr146992 static int
hookevent_stack_walk_step(mdb_walk_state_t * wsp)234f4b3ec61Sdh155122 hookevent_stack_walk_step(mdb_walk_state_t *wsp)
235381a2a9aSdr146992 {
236381a2a9aSdr146992 	hook_event_int_t hr;
237381a2a9aSdr146992 
238381a2a9aSdr146992 	if (mdb_vread((void *)&hr, sizeof (hr),
239381a2a9aSdr146992 	    (uintptr_t)wsp->walk_addr) == -1) {
240381a2a9aSdr146992 		mdb_warn("couldn't read hook event at %p", wsp->walk_addr);
241381a2a9aSdr146992 		return (DCMD_ERR);
242381a2a9aSdr146992 	}
243381a2a9aSdr146992 	wsp->walk_addr = (uintptr_t)SLIST_NEXT(&hr, hei_entry);
244381a2a9aSdr146992 	if (wsp->walk_addr == NULL)
245381a2a9aSdr146992 		return (WALK_DONE);
246381a2a9aSdr146992 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
247381a2a9aSdr146992 	    wsp->walk_cbdata));
248381a2a9aSdr146992 }
249381a2a9aSdr146992 
250381a2a9aSdr146992 static const mdb_dcmd_t dcmds[] = {
251381a2a9aSdr146992 	{ "hookrootlist", "", "display hook family information", hookrootlist },
252381a2a9aSdr146992 	{ "hookeventlist", "", "display hook event information",
253381a2a9aSdr146992 		hookeventlist, NULL },
254381a2a9aSdr146992 	{ "hooklist", "", "display hooks", hooklist },
255381a2a9aSdr146992 	{ NULL }
256381a2a9aSdr146992 };
257381a2a9aSdr146992 
258381a2a9aSdr146992 static const mdb_walker_t walkers[] = {
259f4b3ec61Sdh155122 	{ "hookevent_stack", "walk list of hooks",
260f4b3ec61Sdh155122 		hookevent_stack_walk_init, hookevent_stack_walk_step, NULL },
261381a2a9aSdr146992 	{ NULL }
262381a2a9aSdr146992 };
263381a2a9aSdr146992 
264381a2a9aSdr146992 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
265381a2a9aSdr146992 
266381a2a9aSdr146992 const mdb_modinfo_t *
_mdb_init(void)267381a2a9aSdr146992 _mdb_init(void)
268381a2a9aSdr146992 {
269381a2a9aSdr146992 	return (&modinfo);
270381a2a9aSdr146992 }
271