1*45916cd2Sjpk /*
2*45916cd2Sjpk * CDDL HEADER START
3*45916cd2Sjpk *
4*45916cd2Sjpk * The contents of this file are subject to the terms of the
5*45916cd2Sjpk * Common Development and Distribution License (the "License").
6*45916cd2Sjpk * You may not use this file except in compliance with the License.
7*45916cd2Sjpk *
8*45916cd2Sjpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*45916cd2Sjpk * or http://www.opensolaris.org/os/licensing.
10*45916cd2Sjpk * See the License for the specific language governing permissions
11*45916cd2Sjpk * and limitations under the License.
12*45916cd2Sjpk *
13*45916cd2Sjpk * When distributing Covered Code, include this CDDL HEADER in each
14*45916cd2Sjpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*45916cd2Sjpk * If applicable, add the following below this CDDL HEADER, with the
16*45916cd2Sjpk * fields enclosed by brackets "[]" replaced with your own identifying
17*45916cd2Sjpk * information: Portions Copyright [yyyy] [name of copyright owner]
18*45916cd2Sjpk *
19*45916cd2Sjpk * CDDL HEADER END
20*45916cd2Sjpk */
21*45916cd2Sjpk /*
22*45916cd2Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23*45916cd2Sjpk * Use is subject to license terms.
24*45916cd2Sjpk */
25*45916cd2Sjpk
26*45916cd2Sjpk #pragma ident "%Z%%M% %I% %E% SMI"
27*45916cd2Sjpk
28*45916cd2Sjpk #include <sys/types.h>
29*45916cd2Sjpk #include <sys/tsol/tndb.h>
30*45916cd2Sjpk #include <sys/modhash_impl.h>
31*45916cd2Sjpk
32*45916cd2Sjpk #include <mdb/mdb_modapi.h>
33*45916cd2Sjpk #include <mdb/mdb_ks.h>
34*45916cd2Sjpk
35*45916cd2Sjpk #include "tsol.h"
36*45916cd2Sjpk #include "modhash.h"
37*45916cd2Sjpk
38*45916cd2Sjpk /* ****************** tnrh ****************** */
39*45916cd2Sjpk
40*45916cd2Sjpk typedef struct tnrh_walk_s {
41*45916cd2Sjpk tnrhc_hash_t **hptr;
42*45916cd2Sjpk int idx;
43*45916cd2Sjpk tnrhc_hash_t *tnrhc_table[TSOL_MASK_TABLE_SIZE];
44*45916cd2Sjpk tnrhc_hash_t *tnrhc_table_v6[TSOL_MASK_TABLE_SIZE_V6];
45*45916cd2Sjpk } tnrh_walk_t;
46*45916cd2Sjpk
47*45916cd2Sjpk /*
48*45916cd2Sjpk * Free the mdb storage pointed to by the given per-prefix table.
49*45916cd2Sjpk */
50*45916cd2Sjpk static void
free_table(tnrhc_hash_t ** table,int ntable)51*45916cd2Sjpk free_table(tnrhc_hash_t **table, int ntable)
52*45916cd2Sjpk {
53*45916cd2Sjpk while (--ntable >= 0) {
54*45916cd2Sjpk if (*table != NULL)
55*45916cd2Sjpk mdb_free(*table, TNRHC_SIZE * sizeof (**table));
56*45916cd2Sjpk table++;
57*45916cd2Sjpk }
58*45916cd2Sjpk }
59*45916cd2Sjpk
60*45916cd2Sjpk /*
61*45916cd2Sjpk * Read in a list of per-prefix-length hash tables. Allocate storage for the
62*45916cd2Sjpk * hashes that are present. On successful return, the table will contain
63*45916cd2Sjpk * pointers to mdb-resident storage, not kernel addresses. On failure, the
64*45916cd2Sjpk * contents will not point to any mdb storage.
65*45916cd2Sjpk */
66*45916cd2Sjpk static int
read_table(const char * symname,tnrhc_hash_t ** table,int ntable)67*45916cd2Sjpk read_table(const char *symname, tnrhc_hash_t **table, int ntable)
68*45916cd2Sjpk {
69*45916cd2Sjpk GElf_Sym tnrhc_hash;
70*45916cd2Sjpk tnrhc_hash_t **hp;
71*45916cd2Sjpk uintptr_t addr;
72*45916cd2Sjpk
73*45916cd2Sjpk if (mdb_lookup_by_name(symname, &tnrhc_hash) == -1) {
74*45916cd2Sjpk mdb_warn("failed to read %s", symname);
75*45916cd2Sjpk return (-1);
76*45916cd2Sjpk }
77*45916cd2Sjpk if (mdb_vread(table, ntable * sizeof (*table),
78*45916cd2Sjpk tnrhc_hash.st_value) == -1) {
79*45916cd2Sjpk mdb_warn("can't read %s at %p", symname, tnrhc_hash.st_value);
80*45916cd2Sjpk return (-1);
81*45916cd2Sjpk }
82*45916cd2Sjpk for (hp = table; hp < table + ntable; hp++) {
83*45916cd2Sjpk if ((addr = (uintptr_t)*hp) != 0) {
84*45916cd2Sjpk *hp = mdb_alloc(TNRHC_SIZE * sizeof (**hp), UM_SLEEP);
85*45916cd2Sjpk if (mdb_vread(*hp, TNRHC_SIZE * sizeof (**hp),
86*45916cd2Sjpk addr) == -1) {
87*45916cd2Sjpk mdb_warn("can't read %s[%d] at %p", symname,
88*45916cd2Sjpk hp - table, addr);
89*45916cd2Sjpk free_table(table, (hp - table) + 1);
90*45916cd2Sjpk return (-1);
91*45916cd2Sjpk }
92*45916cd2Sjpk }
93*45916cd2Sjpk }
94*45916cd2Sjpk return (0);
95*45916cd2Sjpk }
96*45916cd2Sjpk
97*45916cd2Sjpk int
tnrh_walk_init(mdb_walk_state_t * wsp)98*45916cd2Sjpk tnrh_walk_init(mdb_walk_state_t *wsp)
99*45916cd2Sjpk {
100*45916cd2Sjpk tnrh_walk_t *twp;
101*45916cd2Sjpk
102*45916cd2Sjpk twp = mdb_alloc(sizeof (*twp), UM_SLEEP);
103*45916cd2Sjpk
104*45916cd2Sjpk if (read_table("tnrhc_table", twp->tnrhc_table,
105*45916cd2Sjpk TSOL_MASK_TABLE_SIZE) == -1) {
106*45916cd2Sjpk mdb_free(twp, sizeof (*twp));
107*45916cd2Sjpk return (WALK_ERR);
108*45916cd2Sjpk }
109*45916cd2Sjpk if (read_table("tnrhc_table_v6", twp->tnrhc_table_v6,
110*45916cd2Sjpk TSOL_MASK_TABLE_SIZE_V6) == -1) {
111*45916cd2Sjpk free_table(twp->tnrhc_table, TSOL_MASK_TABLE_SIZE);
112*45916cd2Sjpk mdb_free(twp, sizeof (*twp));
113*45916cd2Sjpk return (WALK_ERR);
114*45916cd2Sjpk }
115*45916cd2Sjpk
116*45916cd2Sjpk twp->hptr = twp->tnrhc_table;
117*45916cd2Sjpk twp->idx = 0;
118*45916cd2Sjpk wsp->walk_addr = 0;
119*45916cd2Sjpk wsp->walk_data = twp;
120*45916cd2Sjpk
121*45916cd2Sjpk return (WALK_NEXT);
122*45916cd2Sjpk }
123*45916cd2Sjpk
124*45916cd2Sjpk int
tnrh_walk_step(mdb_walk_state_t * wsp)125*45916cd2Sjpk tnrh_walk_step(mdb_walk_state_t *wsp)
126*45916cd2Sjpk {
127*45916cd2Sjpk tnrh_walk_t *twp = wsp->walk_data;
128*45916cd2Sjpk tsol_tnrhc_t tnrhc;
129*45916cd2Sjpk int status;
130*45916cd2Sjpk
131*45916cd2Sjpk while (wsp->walk_addr == NULL) {
132*45916cd2Sjpk if (*twp->hptr == NULL || twp->idx >= TNRHC_SIZE) {
133*45916cd2Sjpk twp->hptr++;
134*45916cd2Sjpk if (twp->hptr == twp->tnrhc_table +
135*45916cd2Sjpk TSOL_MASK_TABLE_SIZE)
136*45916cd2Sjpk twp->hptr = twp->tnrhc_table_v6;
137*45916cd2Sjpk else if (twp->hptr == twp->tnrhc_table_v6 +
138*45916cd2Sjpk TSOL_MASK_TABLE_SIZE_V6)
139*45916cd2Sjpk return (WALK_DONE);
140*45916cd2Sjpk twp->idx = 0;
141*45916cd2Sjpk } else {
142*45916cd2Sjpk wsp->walk_addr = (uintptr_t)(*twp->hptr)[twp->idx++].
143*45916cd2Sjpk tnrh_list;
144*45916cd2Sjpk }
145*45916cd2Sjpk }
146*45916cd2Sjpk
147*45916cd2Sjpk if (mdb_vread(&tnrhc, sizeof (tnrhc), wsp->walk_addr) == -1) {
148*45916cd2Sjpk mdb_warn("can't read tsol_tnrhc_t at %p", wsp->walk_addr);
149*45916cd2Sjpk return (WALK_ERR);
150*45916cd2Sjpk }
151*45916cd2Sjpk
152*45916cd2Sjpk status = wsp->walk_callback(wsp->walk_addr, &tnrhc,
153*45916cd2Sjpk wsp->walk_cbdata);
154*45916cd2Sjpk
155*45916cd2Sjpk wsp->walk_addr = (uintptr_t)tnrhc.rhc_next;
156*45916cd2Sjpk return (status);
157*45916cd2Sjpk }
158*45916cd2Sjpk
159*45916cd2Sjpk void
tnrh_walk_fini(mdb_walk_state_t * wsp)160*45916cd2Sjpk tnrh_walk_fini(mdb_walk_state_t *wsp)
161*45916cd2Sjpk {
162*45916cd2Sjpk tnrh_walk_t *twp = wsp->walk_data;
163*45916cd2Sjpk
164*45916cd2Sjpk free_table(twp->tnrhc_table, TSOL_MASK_TABLE_SIZE);
165*45916cd2Sjpk free_table(twp->tnrhc_table_v6, TSOL_MASK_TABLE_SIZE_V6);
166*45916cd2Sjpk mdb_free(twp, sizeof (*twp));
167*45916cd2Sjpk }
168*45916cd2Sjpk
169*45916cd2Sjpk /* ****************** tnrhtp ****************** */
170*45916cd2Sjpk
171*45916cd2Sjpk typedef struct tnrhtp_walk_data_s {
172*45916cd2Sjpk int (*old_callback)(uintptr_t, const void *, void *);
173*45916cd2Sjpk void *old_cbdata;
174*45916cd2Sjpk } tnrhtp_walk_data_t;
175*45916cd2Sjpk
176*45916cd2Sjpk /* ARGSUSED */
177*45916cd2Sjpk static int
tnrhtp_walk_callback(uintptr_t addr,const void * data,void * private)178*45916cd2Sjpk tnrhtp_walk_callback(uintptr_t addr, const void *data, void *private)
179*45916cd2Sjpk {
180*45916cd2Sjpk const struct mod_hash_entry *mhe = data;
181*45916cd2Sjpk tnrhtp_walk_data_t *twd = private;
182*45916cd2Sjpk tsol_tpc_t tpc;
183*45916cd2Sjpk
184*45916cd2Sjpk if (mdb_vread(&tpc, sizeof (tpc), (uintptr_t)mhe->mhe_val) == -1) {
185*45916cd2Sjpk mdb_warn("failed to read tsol_tpc_t at %p", mhe->mhe_val);
186*45916cd2Sjpk return (WALK_ERR);
187*45916cd2Sjpk } else {
188*45916cd2Sjpk return (twd->old_callback((uintptr_t)mhe->mhe_val, &tpc,
189*45916cd2Sjpk twd->old_cbdata));
190*45916cd2Sjpk }
191*45916cd2Sjpk }
192*45916cd2Sjpk
193*45916cd2Sjpk int
tnrhtp_walk_init(mdb_walk_state_t * wsp)194*45916cd2Sjpk tnrhtp_walk_init(mdb_walk_state_t *wsp)
195*45916cd2Sjpk {
196*45916cd2Sjpk mod_hash_t *tpc_name_hash;
197*45916cd2Sjpk
198*45916cd2Sjpk if (mdb_readvar(&tpc_name_hash, "tpc_name_hash") == -1) {
199*45916cd2Sjpk mdb_warn("failed to read tpc_name_hash");
200*45916cd2Sjpk return (WALK_ERR);
201*45916cd2Sjpk }
202*45916cd2Sjpk
203*45916cd2Sjpk wsp->walk_addr = (uintptr_t)tpc_name_hash;
204*45916cd2Sjpk
205*45916cd2Sjpk return (modent_walk_init(wsp));
206*45916cd2Sjpk }
207*45916cd2Sjpk
208*45916cd2Sjpk int
tnrhtp_walk_step(mdb_walk_state_t * wsp)209*45916cd2Sjpk tnrhtp_walk_step(mdb_walk_state_t *wsp)
210*45916cd2Sjpk {
211*45916cd2Sjpk tnrhtp_walk_data_t twd;
212*45916cd2Sjpk int retv;
213*45916cd2Sjpk
214*45916cd2Sjpk twd.old_callback = wsp->walk_callback;
215*45916cd2Sjpk twd.old_cbdata = wsp->walk_cbdata;
216*45916cd2Sjpk wsp->walk_callback = tnrhtp_walk_callback;
217*45916cd2Sjpk wsp->walk_cbdata = &twd;
218*45916cd2Sjpk
219*45916cd2Sjpk retv = modent_walk_step(wsp);
220*45916cd2Sjpk
221*45916cd2Sjpk wsp->walk_callback = twd.old_callback;
222*45916cd2Sjpk wsp->walk_cbdata = twd.old_cbdata;
223*45916cd2Sjpk
224*45916cd2Sjpk return (retv);
225*45916cd2Sjpk }
226*45916cd2Sjpk
227*45916cd2Sjpk void
tnrhtp_walk_fini(mdb_walk_state_t * wsp)228*45916cd2Sjpk tnrhtp_walk_fini(mdb_walk_state_t *wsp)
229*45916cd2Sjpk {
230*45916cd2Sjpk modent_walk_fini(wsp);
231*45916cd2Sjpk }
232