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 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 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 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 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 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 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 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 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 228*45916cd2Sjpk tnrhtp_walk_fini(mdb_walk_state_t *wsp) 229*45916cd2Sjpk { 230*45916cd2Sjpk modent_walk_fini(wsp); 231*45916cd2Sjpk } 232