12958Sdr146992 /*
22958Sdr146992 * CDDL HEADER START
32958Sdr146992 *
42958Sdr146992 * The contents of this file are subject to the terms of the
52958Sdr146992 * Common Development and Distribution License (the "License").
62958Sdr146992 * You may not use this file except in compliance with the License.
72958Sdr146992 *
82958Sdr146992 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92958Sdr146992 * or http://www.opensolaris.org/os/licensing.
102958Sdr146992 * See the License for the specific language governing permissions
112958Sdr146992 * and limitations under the License.
122958Sdr146992 *
132958Sdr146992 * When distributing Covered Code, include this CDDL HEADER in each
142958Sdr146992 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152958Sdr146992 * If applicable, add the following below this CDDL HEADER, with the
162958Sdr146992 * fields enclosed by brackets "[]" replaced with your own identifying
172958Sdr146992 * information: Portions Copyright [yyyy] [name of copyright owner]
182958Sdr146992 *
192958Sdr146992 * CDDL HEADER END
202958Sdr146992 */
212958Sdr146992 /*
22*7513SDarren.Reed@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
232958Sdr146992 * Use is subject to license terms.
242958Sdr146992 */
252958Sdr146992
262958Sdr146992 #include <sys/types.h>
272958Sdr146992 #include <sys/rwlock.h>
282958Sdr146992 #include <mdb/mdb_modapi.h>
292958Sdr146992 #include <sys/queue.h>
303448Sdh155122 #include <inet/ip.h>
312958Sdr146992 #include <sys/hook.h>
322958Sdr146992 #include <sys/hook_impl.h>
332958Sdr146992
342958Sdr146992 #define MAX_LENGTH 64
352958Sdr146992
362958Sdr146992 /*
372958Sdr146992 * List pfhooks hook list information.
382958Sdr146992 */
392958Sdr146992 /*ARGSUSED*/
402958Sdr146992 int
hooklist(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)412958Sdr146992 hooklist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
422958Sdr146992 {
432958Sdr146992 hook_event_int_t hr;
442958Sdr146992 hook_int_t hl, *hlp;
452958Sdr146992 char hrstr[MAX_LENGTH];
462958Sdr146992 GElf_Sym sym;
472958Sdr146992 char buf[MDB_SYM_NAMLEN + 1];
48*7513SDarren.Reed@Sun.COM char *hintname;
49*7513SDarren.Reed@Sun.COM hook_t *h;
502958Sdr146992
512958Sdr146992 if (argc)
522958Sdr146992 return (DCMD_USAGE);
532958Sdr146992
542958Sdr146992 if (mdb_vread((void *)&hr, sizeof (hr), (uintptr_t)addr) == -1) {
552958Sdr146992 mdb_warn("couldn't read hook register at %p", addr);
562958Sdr146992 return (DCMD_ERR);
572958Sdr146992 }
582958Sdr146992
59*7513SDarren.Reed@Sun.COM mdb_printf("%<u>%?s %8s %20s %4s %24s %24s%</u>\n",
60*7513SDarren.Reed@Sun.COM "ADDR", "FLAG", "FUNC", "HINT", "NAME", "HINTVALUE");
61*7513SDarren.Reed@Sun.COM h = &hl.hi_hook;
622958Sdr146992 hlp = TAILQ_FIRST(&hr.hei_head);
632958Sdr146992 while (hlp) {
642958Sdr146992 if (mdb_vread((void *)&hl, sizeof (hl),
652958Sdr146992 (uintptr_t)hlp) == -1) {
662958Sdr146992 mdb_warn("couldn't read hook list at %p",
672958Sdr146992 hlp);
682958Sdr146992 return (DCMD_ERR);
692958Sdr146992 }
70*7513SDarren.Reed@Sun.COM if (!h->h_name) {
71*7513SDarren.Reed@Sun.COM mdb_warn("hook list at %p has null role", h);
722958Sdr146992 return (DCMD_ERR);
732958Sdr146992 }
742958Sdr146992 if (mdb_readstr((char *)hrstr, sizeof (hrstr),
75*7513SDarren.Reed@Sun.COM (uintptr_t)h->h_name) == -1) {
76*7513SDarren.Reed@Sun.COM mdb_warn("couldn't read list role at %p", h->h_name);
772958Sdr146992 return (DCMD_ERR);
782958Sdr146992 }
79*7513SDarren.Reed@Sun.COM switch (h->h_hint) {
80*7513SDarren.Reed@Sun.COM case HH_BEFORE :
81*7513SDarren.Reed@Sun.COM case HH_AFTER :
82*7513SDarren.Reed@Sun.COM hintname = h->h_hintvalue ?
83*7513SDarren.Reed@Sun.COM (char *)h->h_hintvalue : "";
84*7513SDarren.Reed@Sun.COM break;
85*7513SDarren.Reed@Sun.COM default :
86*7513SDarren.Reed@Sun.COM hintname = "";
87*7513SDarren.Reed@Sun.COM break;
88*7513SDarren.Reed@Sun.COM }
89*7513SDarren.Reed@Sun.COM if (mdb_lookup_by_addr((uintptr_t)h->h_func,
902958Sdr146992 MDB_SYM_EXACT, buf, sizeof (buf), &sym) == -1)
91*7513SDarren.Reed@Sun.COM mdb_printf("%0?p %8x %0?p %4d %24s %24s\n",
92*7513SDarren.Reed@Sun.COM hlp, h->h_flags, h->h_func,
93*7513SDarren.Reed@Sun.COM h->h_hint, hrstr, hintname);
942958Sdr146992 else
95*7513SDarren.Reed@Sun.COM mdb_printf("%0?p %8x %20s %4d %24s %24s\n",
96*7513SDarren.Reed@Sun.COM hlp, h->h_flags, buf,
97*7513SDarren.Reed@Sun.COM h->h_hint, hrstr, hintname);
982958Sdr146992 hlp = TAILQ_NEXT(&hl, hi_entry);
992958Sdr146992 }
1002958Sdr146992 return (DCMD_OK);
1012958Sdr146992 }
1022958Sdr146992
1032958Sdr146992 /*
1042958Sdr146992 * List pfhooks event information.
1052958Sdr146992 * List the hooks information in verbose mode as well.
1062958Sdr146992 */
1072958Sdr146992 /*ARGSUSED*/
1082958Sdr146992 int
hookeventlist(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1092958Sdr146992 hookeventlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1102958Sdr146992 {
1112958Sdr146992 hook_family_int_t hf;
1122958Sdr146992 hook_event_int_t hr, *hrp;
1132958Sdr146992 hook_event_t hp;
1142958Sdr146992 char hprstr[MAX_LENGTH];
1152958Sdr146992
1162958Sdr146992 if (argc)
1172958Sdr146992 return (DCMD_USAGE);
1182958Sdr146992
1192958Sdr146992 if (mdb_vread((void *)&hf, sizeof (hf), (uintptr_t)addr) == -1) {
1202958Sdr146992 mdb_warn("couldn't read hook family at %p", addr);
1212958Sdr146992 return (DCMD_ERR);
1222958Sdr146992 }
1232958Sdr146992
1242958Sdr146992 mdb_printf("%<u>%?s %10s %20s%</u>\n", "ADDR", "FLAG", "NAME");
1252958Sdr146992 hrp = SLIST_FIRST(&hf.hfi_head);
1262958Sdr146992 while (hrp) {
1272958Sdr146992 if (mdb_vread((void *)&hr, sizeof (hr), (uintptr_t)hrp) == -1) {
1282958Sdr146992 mdb_warn("couldn't read hook register at %p", hrp);
1292958Sdr146992 return (DCMD_ERR);
1302958Sdr146992 }
1312958Sdr146992 if (!hr.hei_event) {
1322958Sdr146992 mdb_warn("hook register at %p has no hook provider",
1332958Sdr146992 hrp);
1342958Sdr146992 return (DCMD_ERR);
1352958Sdr146992 }
1362958Sdr146992 if (mdb_vread((void *)&hp, sizeof (hp),
1372958Sdr146992 (uintptr_t)hr.hei_event) == -1) {
1382958Sdr146992 mdb_warn("hook provider at %p has null role",
1392958Sdr146992 hr.hei_event);
1402958Sdr146992 return (DCMD_ERR);
1412958Sdr146992 }
1422958Sdr146992 if (!hp.he_name) {
1432958Sdr146992 mdb_warn("hook provider at %p has null role",
1442958Sdr146992 hr.hei_event);
1452958Sdr146992 return (DCMD_ERR);
1462958Sdr146992 }
1472958Sdr146992 if (mdb_readstr((char *)hprstr, sizeof (hprstr),
1482958Sdr146992 (uintptr_t)hp.he_name) == -1) {
1492958Sdr146992 mdb_warn("couldn't read provider role at %p",
1502958Sdr146992 hp.he_name);
1512958Sdr146992 return (DCMD_ERR);
1522958Sdr146992 }
1532958Sdr146992 mdb_printf("%0?p %10x %20s\n", hrp, hp.he_flags, hprstr);
1542958Sdr146992 hrp = SLIST_NEXT(&hr, hei_entry);
1552958Sdr146992 }
1562958Sdr146992
1572958Sdr146992 return (DCMD_OK);
1582958Sdr146992 }
1592958Sdr146992
1602958Sdr146992 /*
1612958Sdr146992 * List pfhooks family information.
1622958Sdr146992 */
1632958Sdr146992 /*ARGSUSED*/
1642958Sdr146992 int
hookrootlist(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1652958Sdr146992 hookrootlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1662958Sdr146992 {
1673448Sdh155122 struct hook_stack *hks;
1682958Sdr146992 hook_family_int_head_t hfh;
1692958Sdr146992 hook_family_int_t hf, *hfp;
1702958Sdr146992 char hrrstr[MAX_LENGTH];
1712958Sdr146992
1722958Sdr146992 if (argc)
1732958Sdr146992 return (DCMD_USAGE);
1742958Sdr146992
1753448Sdh155122 if (mdb_vread((void *)&hks, sizeof (hks),
1763448Sdh155122 (uintptr_t)(addr + OFFSETOF(netstack_t, netstack_hook))) == -1) {
1773448Sdh155122 mdb_warn("couldn't read netstack_hook");
1783448Sdh155122 return (DCMD_ERR);
1793448Sdh155122 }
1803448Sdh155122
1813448Sdh155122 if (mdb_vread((void *)&hfh, sizeof (hfh), (uintptr_t)((uintptr_t)hks +
1823448Sdh155122 OFFSETOF(hook_stack_t, hks_familylist))) == -1) {
1833448Sdh155122 mdb_warn("couldn't read hook family head");
1842958Sdr146992 return (DCMD_ERR);
1852958Sdr146992 }
1862958Sdr146992
1872958Sdr146992 mdb_printf("%<u>%?s %10s%</u>\n", "ADDR", "FAMILY");
1882958Sdr146992 hfp = SLIST_FIRST(&hfh);
1892958Sdr146992 while (hfp) {
1902958Sdr146992 if (mdb_vread((void *)&hf, sizeof (hf), (uintptr_t)hfp) == -1) {
1912958Sdr146992 mdb_warn("couldn't read hook family at %p", hfp);
1922958Sdr146992 return (DCMD_ERR);
1932958Sdr146992 }
1942958Sdr146992 if (!hf.hfi_family.hf_name) {
1952958Sdr146992 mdb_warn("hook root at %p has null role",
1962958Sdr146992 hf.hfi_family);
1972958Sdr146992 return (DCMD_ERR);
1982958Sdr146992 }
1992958Sdr146992 if (mdb_readstr((char *)hrrstr, sizeof (hrrstr),
2002958Sdr146992 (uintptr_t)hf.hfi_family.hf_name) == -1) {
2012958Sdr146992 mdb_warn("couldn't read root role at %p",
2022958Sdr146992 hf.hfi_family.hf_name);
2032958Sdr146992 return (DCMD_ERR);
2042958Sdr146992 }
2052958Sdr146992 mdb_printf("%0?p %10s\n", hfp, hrrstr);
2062958Sdr146992 hfp = SLIST_NEXT(&hf, hfi_entry);
2072958Sdr146992 }
2082958Sdr146992
2092958Sdr146992 return (DCMD_OK);
2102958Sdr146992 }
2112958Sdr146992
2122958Sdr146992
2132958Sdr146992 static int
hookevent_stack_walk_init(mdb_walk_state_t * wsp)2143448Sdh155122 hookevent_stack_walk_init(mdb_walk_state_t *wsp)
2152958Sdr146992 {
2162958Sdr146992 hook_family_int_t hf;
2172958Sdr146992
2182958Sdr146992 if (wsp->walk_addr == NULL) {
2192958Sdr146992 mdb_warn("global walk not supported\n");
2202958Sdr146992 return (WALK_ERR);
2212958Sdr146992 }
2222958Sdr146992
2232958Sdr146992 if (mdb_vread((void *)&hf, sizeof (hf),
2242958Sdr146992 (uintptr_t)wsp->walk_addr) == -1) {
2252958Sdr146992 mdb_warn("couldn't read hook family at %p", wsp->walk_addr);
2262958Sdr146992 return (DCMD_ERR);
2272958Sdr146992 }
2282958Sdr146992 wsp->walk_addr = (uintptr_t)SLIST_FIRST(&hf.hfi_head);
2292958Sdr146992 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
230*7513SDarren.Reed@Sun.COM wsp->walk_cbdata));
2312958Sdr146992 }
2322958Sdr146992
2332958Sdr146992 static int
hookevent_stack_walk_step(mdb_walk_state_t * wsp)2343448Sdh155122 hookevent_stack_walk_step(mdb_walk_state_t *wsp)
2352958Sdr146992 {
2362958Sdr146992 hook_event_int_t hr;
2372958Sdr146992
2382958Sdr146992 if (mdb_vread((void *)&hr, sizeof (hr),
2392958Sdr146992 (uintptr_t)wsp->walk_addr) == -1) {
2402958Sdr146992 mdb_warn("couldn't read hook event at %p", wsp->walk_addr);
2412958Sdr146992 return (DCMD_ERR);
2422958Sdr146992 }
2432958Sdr146992 wsp->walk_addr = (uintptr_t)SLIST_NEXT(&hr, hei_entry);
2442958Sdr146992 if (wsp->walk_addr == NULL)
2452958Sdr146992 return (WALK_DONE);
2462958Sdr146992 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
247*7513SDarren.Reed@Sun.COM wsp->walk_cbdata));
2482958Sdr146992 }
2492958Sdr146992
2502958Sdr146992 static const mdb_dcmd_t dcmds[] = {
2512958Sdr146992 { "hookrootlist", "", "display hook family information", hookrootlist },
2522958Sdr146992 { "hookeventlist", "", "display hook event information",
2532958Sdr146992 hookeventlist, NULL },
2542958Sdr146992 { "hooklist", "", "display hooks", hooklist },
2552958Sdr146992 { NULL }
2562958Sdr146992 };
2572958Sdr146992
2582958Sdr146992 static const mdb_walker_t walkers[] = {
2593448Sdh155122 { "hookevent_stack", "walk list of hooks",
2603448Sdh155122 hookevent_stack_walk_init, hookevent_stack_walk_step, NULL },
2612958Sdr146992 { NULL }
2622958Sdr146992 };
2632958Sdr146992
2642958Sdr146992 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
2652958Sdr146992
2662958Sdr146992 const mdb_modinfo_t *
_mdb_init(void)2672958Sdr146992 _mdb_init(void)
2682958Sdr146992 {
2692958Sdr146992 return (&modinfo);
2702958Sdr146992 }
271