1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/stropts.h> 31*0Sstevel@tonic-gate #include <sys/stream.h> 32*0Sstevel@tonic-gate #include <sys/socket.h> 33*0Sstevel@tonic-gate #include <net/if.h> 34*0Sstevel@tonic-gate #define SOL2 35*0Sstevel@tonic-gate #include <net/ppp_defs.h> 36*0Sstevel@tonic-gate #include <net/pppio.h> 37*0Sstevel@tonic-gate #include <net/sppptun.h> 38*0Sstevel@tonic-gate #include <netinet/in.h> 39*0Sstevel@tonic-gate #include <netinet/ip6.h> 40*0Sstevel@tonic-gate #include <inet/common.h> 41*0Sstevel@tonic-gate #include <inet/mib2.h> 42*0Sstevel@tonic-gate #include <inet/ip.h> 43*0Sstevel@tonic-gate #include <inet/ip6.h> 44*0Sstevel@tonic-gate #include <sppp/sppp.h> 45*0Sstevel@tonic-gate #include <sppptun/sppptun_impl.h> 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 48*0Sstevel@tonic-gate #include <mdb/mdb_ks.h> 49*0Sstevel@tonic-gate #include <stdio.h> 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate /* ****************** sppp ****************** */ 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate static int 54*0Sstevel@tonic-gate sppp_walk_init(mdb_walk_state_t *wsp) 55*0Sstevel@tonic-gate { 56*0Sstevel@tonic-gate if (mdb_readvar(&wsp->walk_addr, "sps_list") == -1) { 57*0Sstevel@tonic-gate mdb_warn("failed to read sps_list"); 58*0Sstevel@tonic-gate return (WALK_ERR); 59*0Sstevel@tonic-gate } 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate return (WALK_NEXT); 62*0Sstevel@tonic-gate } 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate static int 65*0Sstevel@tonic-gate sppp_walk_step(mdb_walk_state_t *wsp) 66*0Sstevel@tonic-gate { 67*0Sstevel@tonic-gate spppstr_t sps; 68*0Sstevel@tonic-gate int status; 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) 71*0Sstevel@tonic-gate return (WALK_DONE); 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate if (mdb_vread(&sps, sizeof (sps), wsp->walk_addr) == -1) { 74*0Sstevel@tonic-gate mdb_warn("can't read spppstr_t at %p", wsp->walk_addr); 75*0Sstevel@tonic-gate return (WALK_ERR); 76*0Sstevel@tonic-gate } 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate status = (wsp->walk_callback(wsp->walk_addr, &sps, wsp->walk_cbdata)); 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)sps.sps_nextmn; 81*0Sstevel@tonic-gate return (status); 82*0Sstevel@tonic-gate } 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate static int 85*0Sstevel@tonic-gate sps_format(uintptr_t addr, const spppstr_t *sps, uint_t *qfmt) 86*0Sstevel@tonic-gate { 87*0Sstevel@tonic-gate sppa_t ppa; 88*0Sstevel@tonic-gate queue_t upq; 89*0Sstevel@tonic-gate uintptr_t upaddr, illaddr; 90*0Sstevel@tonic-gate ill_t ill; 91*0Sstevel@tonic-gate ipif_t ipif; 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate mdb_printf("%?p ", addr); 94*0Sstevel@tonic-gate if (*qfmt) 95*0Sstevel@tonic-gate mdb_printf("%?p ", sps->sps_rq); 96*0Sstevel@tonic-gate if (sps->sps_ppa == NULL) { 97*0Sstevel@tonic-gate mdb_printf("unset "); 98*0Sstevel@tonic-gate } else if (mdb_vread(&ppa, sizeof (ppa), (uintptr_t)sps->sps_ppa) == 99*0Sstevel@tonic-gate -1) { 100*0Sstevel@tonic-gate mdb_printf("?%p ", sps->sps_ppa); 101*0Sstevel@tonic-gate } else { 102*0Sstevel@tonic-gate mdb_printf("sppp%-5d ", ppa.ppa_ppa_id); 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate if (IS_SPS_CONTROL(sps)) { 105*0Sstevel@tonic-gate mdb_printf("Control\n"); 106*0Sstevel@tonic-gate } else if (IS_SPS_PIOATTACH(sps)) { 107*0Sstevel@tonic-gate mdb_printf("Stats\n"); 108*0Sstevel@tonic-gate } else if (sps->sps_dlstate == DL_UNATTACHED) { 109*0Sstevel@tonic-gate mdb_printf("Unknown\n"); 110*0Sstevel@tonic-gate } else if (sps->sps_dlstate != DL_IDLE) { 111*0Sstevel@tonic-gate mdb_printf("DLPI Unbound\n"); 112*0Sstevel@tonic-gate } else { 113*0Sstevel@tonic-gate upaddr = (uintptr_t)sps->sps_rq; 114*0Sstevel@tonic-gate upq.q_ptr = NULL; 115*0Sstevel@tonic-gate illaddr = 0; 116*0Sstevel@tonic-gate while (upaddr != NULL) { 117*0Sstevel@tonic-gate if (mdb_vread(&upq, sizeof (upq), upaddr) == -1) { 118*0Sstevel@tonic-gate upq.q_ptr = NULL; 119*0Sstevel@tonic-gate break; 120*0Sstevel@tonic-gate } 121*0Sstevel@tonic-gate if ((upaddr = (uintptr_t)upq.q_next) != 0) 122*0Sstevel@tonic-gate illaddr = (uintptr_t)upq.q_ptr; 123*0Sstevel@tonic-gate } 124*0Sstevel@tonic-gate if (illaddr != 0) { 125*0Sstevel@tonic-gate if (mdb_vread(&ill, sizeof (ill), illaddr) == -1 || 126*0Sstevel@tonic-gate mdb_vread(&ipif, sizeof (ipif), 127*0Sstevel@tonic-gate (uintptr_t)ill.ill_ipif) == -1) { 128*0Sstevel@tonic-gate illaddr = 0; 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate } 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate switch (sps->sps_req_sap) { 133*0Sstevel@tonic-gate case ETHERTYPE_IP: 134*0Sstevel@tonic-gate mdb_printf("DLPI IPv4 "); 135*0Sstevel@tonic-gate if (*qfmt) { 136*0Sstevel@tonic-gate mdb_printf("\n"); 137*0Sstevel@tonic-gate } else if (illaddr == 0) { 138*0Sstevel@tonic-gate mdb_printf("(no addresses)\n"); 139*0Sstevel@tonic-gate } else { 140*0Sstevel@tonic-gate /* 141*0Sstevel@tonic-gate * SCCS oddity here -- % <capital> % 142*0Sstevel@tonic-gate * suffers from keyword replacement. 143*0Sstevel@tonic-gate * Avoid that by using ANSI string 144*0Sstevel@tonic-gate * pasting. 145*0Sstevel@tonic-gate */ 146*0Sstevel@tonic-gate mdb_printf("%I:%I" "%s\n", 147*0Sstevel@tonic-gate ipif.ipif_lcl_addr, ipif.ipif_pp_dst_addr, 148*0Sstevel@tonic-gate (ipif.ipif_next ? " ..." : "")); 149*0Sstevel@tonic-gate } 150*0Sstevel@tonic-gate break; 151*0Sstevel@tonic-gate case ETHERTYPE_IPV6: 152*0Sstevel@tonic-gate mdb_printf("DLPI IPv6 "); 153*0Sstevel@tonic-gate if (*qfmt) { 154*0Sstevel@tonic-gate mdb_printf("\n"); 155*0Sstevel@tonic-gate break; 156*0Sstevel@tonic-gate } 157*0Sstevel@tonic-gate if (illaddr == 0) { 158*0Sstevel@tonic-gate mdb_printf("(no addresses)\n"); 159*0Sstevel@tonic-gate break; 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate mdb_printf("%N\n%?s%21s", &ipif.ipif_v6lcl_addr, 162*0Sstevel@tonic-gate "", ""); 163*0Sstevel@tonic-gate mdb_printf("%N\n", &ipif.ipif_v6pp_dst_addr); 164*0Sstevel@tonic-gate break; 165*0Sstevel@tonic-gate case ETHERTYPE_ALLSAP: 166*0Sstevel@tonic-gate mdb_printf("DLPI Snoop\n"); 167*0Sstevel@tonic-gate break; 168*0Sstevel@tonic-gate default: 169*0Sstevel@tonic-gate mdb_printf("DLPI SAP 0x%04X\n", sps->sps_req_sap); 170*0Sstevel@tonic-gate break; 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate return (WALK_NEXT); 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate static int 178*0Sstevel@tonic-gate sppp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 179*0Sstevel@tonic-gate { 180*0Sstevel@tonic-gate uint_t qfmt = FALSE; 181*0Sstevel@tonic-gate spppstr_t sps; 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 'q', MDB_OPT_SETBITS, TRUE, &qfmt, NULL) != 184*0Sstevel@tonic-gate argc) 185*0Sstevel@tonic-gate return (DCMD_USAGE); 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 188*0Sstevel@tonic-gate if (qfmt) { 189*0Sstevel@tonic-gate mdb_printf("%<u>%?s %?s %9s %s%</u>\n", "Address", 190*0Sstevel@tonic-gate "RecvQ", "Interface", "Type"); 191*0Sstevel@tonic-gate } else { 192*0Sstevel@tonic-gate mdb_printf("%<u>%?s %9s %s%</u>\n", "Address", 193*0Sstevel@tonic-gate "Interface", "Type"); 194*0Sstevel@tonic-gate } 195*0Sstevel@tonic-gate } 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC) { 198*0Sstevel@tonic-gate (void) mdb_vread(&sps, sizeof (sps), addr); 199*0Sstevel@tonic-gate (void) sps_format(addr, &sps, &qfmt); 200*0Sstevel@tonic-gate } else if (mdb_walk("sppp", (mdb_walk_cb_t)sps_format, &qfmt) == -1) { 201*0Sstevel@tonic-gate mdb_warn("failed to walk sps_list"); 202*0Sstevel@tonic-gate return (DCMD_ERR); 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate return (DCMD_OK); 206*0Sstevel@tonic-gate } 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate static int 209*0Sstevel@tonic-gate sppa_walk_init(mdb_walk_state_t *wsp) 210*0Sstevel@tonic-gate { 211*0Sstevel@tonic-gate if (mdb_readvar(&wsp->walk_addr, "ppa_list") == -1) { 212*0Sstevel@tonic-gate mdb_warn("failed to read ppa_list"); 213*0Sstevel@tonic-gate return (WALK_ERR); 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate return (WALK_NEXT); 217*0Sstevel@tonic-gate } 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate static int 220*0Sstevel@tonic-gate sppa_walk_step(mdb_walk_state_t *wsp) 221*0Sstevel@tonic-gate { 222*0Sstevel@tonic-gate sppa_t ppa; 223*0Sstevel@tonic-gate int status; 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) 226*0Sstevel@tonic-gate return (WALK_DONE); 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate if (mdb_vread(&ppa, sizeof (ppa), wsp->walk_addr) == -1) { 229*0Sstevel@tonic-gate mdb_warn("can't read spppstr_t at %p", wsp->walk_addr); 230*0Sstevel@tonic-gate return (WALK_ERR); 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate status = (wsp->walk_callback(wsp->walk_addr, &ppa, wsp->walk_cbdata)); 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)ppa.ppa_nextppa; 236*0Sstevel@tonic-gate return (status); 237*0Sstevel@tonic-gate } 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate /* ARGSUSED */ 240*0Sstevel@tonic-gate static int 241*0Sstevel@tonic-gate ppa_format(uintptr_t addr, const sppa_t *ppa, uint_t *qfmt) 242*0Sstevel@tonic-gate { 243*0Sstevel@tonic-gate mdb_printf("%?p sppp%-5d %?p %?p\n", addr, ppa->ppa_ppa_id, 244*0Sstevel@tonic-gate ppa->ppa_ctl, ppa->ppa_lower_wq); 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate return (WALK_NEXT); 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate /* ARGSUSED */ 250*0Sstevel@tonic-gate static int 251*0Sstevel@tonic-gate sppa(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 252*0Sstevel@tonic-gate { 253*0Sstevel@tonic-gate uint_t qfmt = FALSE; 254*0Sstevel@tonic-gate sppa_t ppa; 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 257*0Sstevel@tonic-gate mdb_printf("%<u>%?s %9s %?s %?s%</u>\n", "Address", 258*0Sstevel@tonic-gate "Interface", "Control", "LowerQ"); 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC) { 262*0Sstevel@tonic-gate (void) mdb_vread(&ppa, sizeof (ppa), addr); 263*0Sstevel@tonic-gate (void) ppa_format(addr, &ppa, &qfmt); 264*0Sstevel@tonic-gate } else if (mdb_walk("sppa", (mdb_walk_cb_t)ppa_format, &qfmt) == -1) { 265*0Sstevel@tonic-gate mdb_warn("failed to walk ppa_list"); 266*0Sstevel@tonic-gate return (DCMD_ERR); 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate return (DCMD_OK); 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate static void 273*0Sstevel@tonic-gate sppp_qinfo(const queue_t *q, char *buf, size_t nbytes) 274*0Sstevel@tonic-gate { 275*0Sstevel@tonic-gate spppstr_t sps; 276*0Sstevel@tonic-gate sppa_t ppa; 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate if (mdb_vread(&sps, sizeof (sps), (uintptr_t)q->q_ptr) == 279*0Sstevel@tonic-gate sizeof (sps)) { 280*0Sstevel@tonic-gate if (sps.sps_ppa == NULL || 281*0Sstevel@tonic-gate mdb_vread(&ppa, sizeof (ppa), (uintptr_t)sps.sps_ppa) == 282*0Sstevel@tonic-gate -1) { 283*0Sstevel@tonic-gate (void) mdb_snprintf(buf, nbytes, "minor %d", 284*0Sstevel@tonic-gate sps.sps_mn_id); 285*0Sstevel@tonic-gate } else { 286*0Sstevel@tonic-gate (void) mdb_snprintf(buf, nbytes, "sppp%d", 287*0Sstevel@tonic-gate ppa.ppa_ppa_id); 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate } 290*0Sstevel@tonic-gate } 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate static uintptr_t 293*0Sstevel@tonic-gate sppp_rnext(const queue_t *q) 294*0Sstevel@tonic-gate { 295*0Sstevel@tonic-gate spppstr_t sps; 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate if (mdb_vread(&sps, sizeof (sps), (uintptr_t)q->q_ptr) == sizeof (sps)) 298*0Sstevel@tonic-gate return ((uintptr_t)sps.sps_rq); 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate return (NULL); 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate static uintptr_t 304*0Sstevel@tonic-gate sppp_wnext(const queue_t *q) 305*0Sstevel@tonic-gate { 306*0Sstevel@tonic-gate spppstr_t sps; 307*0Sstevel@tonic-gate sppa_t ppa; 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate if (mdb_vread(&sps, sizeof (sps), (uintptr_t)q->q_ptr) != sizeof (sps)) 310*0Sstevel@tonic-gate return (NULL); 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate if (sps.sps_ppa != NULL && 313*0Sstevel@tonic-gate mdb_vread(&ppa, sizeof (ppa), (uintptr_t)sps.sps_ppa) == 314*0Sstevel@tonic-gate sizeof (ppa)) 315*0Sstevel@tonic-gate return ((uintptr_t)ppa.ppa_lower_wq); 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate return (NULL); 318*0Sstevel@tonic-gate } 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate /* ****************** sppptun ****************** */ 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate struct tcl_walk_data { 323*0Sstevel@tonic-gate size_t tcl_nslots; 324*0Sstevel@tonic-gate size_t walkpos; 325*0Sstevel@tonic-gate tuncl_t *tcl_slots[1]; 326*0Sstevel@tonic-gate }; 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate static void 329*0Sstevel@tonic-gate tuncl_walk_fini(mdb_walk_state_t *wsp) 330*0Sstevel@tonic-gate { 331*0Sstevel@tonic-gate struct tcl_walk_data *twd; 332*0Sstevel@tonic-gate 333*0Sstevel@tonic-gate if (wsp != NULL && wsp->walk_addr != 0) { 334*0Sstevel@tonic-gate twd = (struct tcl_walk_data *)wsp->walk_addr; 335*0Sstevel@tonic-gate mdb_free(twd, sizeof (*twd) + ((twd->tcl_nslots - 1) * 336*0Sstevel@tonic-gate sizeof (twd->tcl_slots[0]))); 337*0Sstevel@tonic-gate wsp->walk_addr = 0; 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate } 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate static int 342*0Sstevel@tonic-gate tuncl_walk_init(mdb_walk_state_t *wsp) 343*0Sstevel@tonic-gate { 344*0Sstevel@tonic-gate size_t tcl_nslots; 345*0Sstevel@tonic-gate tuncl_t **tcl_slots; 346*0Sstevel@tonic-gate struct tcl_walk_data *twd; 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate if (wsp == NULL) 349*0Sstevel@tonic-gate return (WALK_ERR); 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate if (wsp->walk_addr != 0) 352*0Sstevel@tonic-gate tuncl_walk_fini(wsp); 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate if (mdb_readvar(&tcl_nslots, "tcl_nslots") == -1) { 355*0Sstevel@tonic-gate mdb_warn("failed to read tcl_nslots"); 356*0Sstevel@tonic-gate return (WALK_ERR); 357*0Sstevel@tonic-gate } 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate if (tcl_nslots == 0) 360*0Sstevel@tonic-gate return (WALK_DONE); 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate if (mdb_readvar(&tcl_slots, "tcl_slots") == -1) { 363*0Sstevel@tonic-gate mdb_warn("failed to read tcl_slots"); 364*0Sstevel@tonic-gate return (WALK_ERR); 365*0Sstevel@tonic-gate } 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate twd = (struct tcl_walk_data *)mdb_alloc(sizeof (*twd) + 368*0Sstevel@tonic-gate (tcl_nslots - 1) * sizeof (*tcl_slots), UM_NOSLEEP); 369*0Sstevel@tonic-gate if (twd == NULL) 370*0Sstevel@tonic-gate return (WALK_ERR); 371*0Sstevel@tonic-gate twd->tcl_nslots = tcl_nslots; 372*0Sstevel@tonic-gate twd->walkpos = 0; 373*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)twd; 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate if (mdb_vread(twd->tcl_slots, tcl_nslots * sizeof (twd->tcl_slots[0]), 376*0Sstevel@tonic-gate (uintptr_t)tcl_slots) == -1) { 377*0Sstevel@tonic-gate mdb_warn("can't read tcl_slots at %p", tcl_slots); 378*0Sstevel@tonic-gate tuncl_walk_fini(wsp); 379*0Sstevel@tonic-gate return (WALK_ERR); 380*0Sstevel@tonic-gate } 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate return (WALK_NEXT); 383*0Sstevel@tonic-gate } 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate static int 386*0Sstevel@tonic-gate tuncl_walk_step(mdb_walk_state_t *wsp) 387*0Sstevel@tonic-gate { 388*0Sstevel@tonic-gate tuncl_t tcl; 389*0Sstevel@tonic-gate int status; 390*0Sstevel@tonic-gate struct tcl_walk_data *twd; 391*0Sstevel@tonic-gate uintptr_t addr; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate if (wsp == NULL || wsp->walk_addr == NULL) 394*0Sstevel@tonic-gate return (WALK_DONE); 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate twd = (struct tcl_walk_data *)wsp->walk_addr; 397*0Sstevel@tonic-gate 398*0Sstevel@tonic-gate while (twd->walkpos < twd->tcl_nslots && 399*0Sstevel@tonic-gate twd->tcl_slots[twd->walkpos] == NULL) 400*0Sstevel@tonic-gate twd->walkpos++; 401*0Sstevel@tonic-gate if (twd->walkpos >= twd->tcl_nslots) 402*0Sstevel@tonic-gate return (WALK_DONE); 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate addr = (uintptr_t)twd->tcl_slots[twd->walkpos]; 405*0Sstevel@tonic-gate if (mdb_vread(&tcl, sizeof (tcl), addr) == -1) { 406*0Sstevel@tonic-gate mdb_warn("can't read tuncl_t at %p", addr); 407*0Sstevel@tonic-gate return (WALK_ERR); 408*0Sstevel@tonic-gate } 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate status = wsp->walk_callback(addr, &tcl, wsp->walk_cbdata); 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate twd->walkpos++; 413*0Sstevel@tonic-gate return (status); 414*0Sstevel@tonic-gate } 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate /* ARGSUSED */ 417*0Sstevel@tonic-gate static int 418*0Sstevel@tonic-gate tuncl_format(uintptr_t addr, const tuncl_t *tcl, uint_t *qfmt) 419*0Sstevel@tonic-gate { 420*0Sstevel@tonic-gate mdb_printf("%?p %?p %?p", addr, tcl->tcl_data_tll, tcl->tcl_ctrl_tll); 421*0Sstevel@tonic-gate mdb_printf(" %-2d %04X %04X ", tcl->tcl_style, 422*0Sstevel@tonic-gate tcl->tcl_lsessid, tcl->tcl_rsessid); 423*0Sstevel@tonic-gate if (tcl->tcl_flags & TCLF_DAEMON) { 424*0Sstevel@tonic-gate mdb_printf("<daemon>\n"); 425*0Sstevel@tonic-gate } else { 426*0Sstevel@tonic-gate mdb_printf("sppp%d\n", tcl->tcl_unit); 427*0Sstevel@tonic-gate } 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate return (WALK_NEXT); 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate /* ARGSUSED */ 433*0Sstevel@tonic-gate static int 434*0Sstevel@tonic-gate tuncl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 435*0Sstevel@tonic-gate { 436*0Sstevel@tonic-gate uint_t qfmt = FALSE; 437*0Sstevel@tonic-gate tuncl_t tcl; 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 440*0Sstevel@tonic-gate mdb_printf("%<u>%?s %?s %?s Ty LSes RSes %s%</u>\n", "Address", 441*0Sstevel@tonic-gate "Data", "Control", "Interface"); 442*0Sstevel@tonic-gate } 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC) { 445*0Sstevel@tonic-gate if (mdb_vread(&tcl, sizeof (tcl), addr) == -1) 446*0Sstevel@tonic-gate mdb_warn("failed to read tuncl_t at %p", addr); 447*0Sstevel@tonic-gate else 448*0Sstevel@tonic-gate tuncl_format(addr, &tcl, &qfmt); 449*0Sstevel@tonic-gate } else if (mdb_walk("tuncl", (mdb_walk_cb_t)tuncl_format, &qfmt) == 450*0Sstevel@tonic-gate -1) { 451*0Sstevel@tonic-gate mdb_warn("failed to walk tcl_slots"); 452*0Sstevel@tonic-gate return (DCMD_ERR); 453*0Sstevel@tonic-gate } 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate return (DCMD_OK); 456*0Sstevel@tonic-gate } 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate struct tll_walk_data { 459*0Sstevel@tonic-gate void *listhead; 460*0Sstevel@tonic-gate void *next; 461*0Sstevel@tonic-gate }; 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gate static void 464*0Sstevel@tonic-gate tunll_walk_fini(mdb_walk_state_t *wsp) 465*0Sstevel@tonic-gate { 466*0Sstevel@tonic-gate struct tll_walk_data *twd; 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate if (wsp != NULL && wsp->walk_addr != 0) { 469*0Sstevel@tonic-gate twd = (struct tll_walk_data *)wsp->walk_addr; 470*0Sstevel@tonic-gate mdb_free(twd, sizeof (*twd)); 471*0Sstevel@tonic-gate wsp->walk_addr = 0; 472*0Sstevel@tonic-gate } 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate static int 476*0Sstevel@tonic-gate tunll_walk_init(mdb_walk_state_t *wsp) 477*0Sstevel@tonic-gate { 478*0Sstevel@tonic-gate GElf_Sym sym; 479*0Sstevel@tonic-gate struct tll_walk_data *twd; 480*0Sstevel@tonic-gate struct qelem tunll_list; 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate if (wsp->walk_addr != 0) 483*0Sstevel@tonic-gate tunll_walk_fini(wsp); 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate if (mdb_lookup_by_obj("sppptun", "tunll_list", &sym) != 0) { 486*0Sstevel@tonic-gate mdb_warn("failed to find tunll_list"); 487*0Sstevel@tonic-gate return (WALK_ERR); 488*0Sstevel@tonic-gate } 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate if (mdb_vread(&tunll_list, sizeof (tunll_list), 491*0Sstevel@tonic-gate (uintptr_t)sym.st_value) == -1) { 492*0Sstevel@tonic-gate mdb_warn("can't read tunll_list at %p", 493*0Sstevel@tonic-gate (uintptr_t)sym.st_value); 494*0Sstevel@tonic-gate return (WALK_ERR); 495*0Sstevel@tonic-gate } 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate twd = (struct tll_walk_data *)mdb_alloc(sizeof (*twd), UM_NOSLEEP); 498*0Sstevel@tonic-gate if (twd == NULL) 499*0Sstevel@tonic-gate return (WALK_ERR); 500*0Sstevel@tonic-gate twd->listhead = (void *)(uintptr_t)sym.st_value; 501*0Sstevel@tonic-gate twd->next = (void *)tunll_list.q_forw; 502*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)twd; 503*0Sstevel@tonic-gate 504*0Sstevel@tonic-gate return (WALK_NEXT); 505*0Sstevel@tonic-gate } 506*0Sstevel@tonic-gate 507*0Sstevel@tonic-gate static int 508*0Sstevel@tonic-gate tunll_walk_step(mdb_walk_state_t *wsp) 509*0Sstevel@tonic-gate { 510*0Sstevel@tonic-gate struct tll_walk_data *twd; 511*0Sstevel@tonic-gate tunll_t tll; 512*0Sstevel@tonic-gate int status; 513*0Sstevel@tonic-gate uintptr_t addr; 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate if (wsp == NULL || wsp->walk_addr == 0) 516*0Sstevel@tonic-gate return (WALK_DONE); 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate twd = (struct tll_walk_data *)wsp->walk_addr; 519*0Sstevel@tonic-gate if (twd->next == NULL || twd->next == twd->listhead) 520*0Sstevel@tonic-gate return (WALK_DONE); 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate /* LINTED */ 523*0Sstevel@tonic-gate addr = (uintptr_t)TO_TLL(twd->next); 524*0Sstevel@tonic-gate if (mdb_vread(&tll, sizeof (tll), addr) == -1) { 525*0Sstevel@tonic-gate mdb_warn("can't read tunll_t at %p", addr); 526*0Sstevel@tonic-gate return (WALK_ERR); 527*0Sstevel@tonic-gate } 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate status = wsp->walk_callback(addr, &tll, wsp->walk_cbdata); 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate twd->next = (void *)tll.tll_next; 532*0Sstevel@tonic-gate return (status); 533*0Sstevel@tonic-gate } 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate /* ARGSUSED */ 536*0Sstevel@tonic-gate static int 537*0Sstevel@tonic-gate tunll_format(uintptr_t addr, const tunll_t *tll, uint_t *qfmt) 538*0Sstevel@tonic-gate { 539*0Sstevel@tonic-gate mdb_printf("%?p %-14s %?p", addr, tll->tll_name, tll->tll_defcl); 540*0Sstevel@tonic-gate if (tll->tll_style == PTS_PPPOE) { 541*0Sstevel@tonic-gate mdb_printf(" %x:%x:%x:%x:%x:%x", 542*0Sstevel@tonic-gate tll->tll_lcladdr.pta_pppoe.ptma_mac[0], 543*0Sstevel@tonic-gate tll->tll_lcladdr.pta_pppoe.ptma_mac[1], 544*0Sstevel@tonic-gate tll->tll_lcladdr.pta_pppoe.ptma_mac[2], 545*0Sstevel@tonic-gate tll->tll_lcladdr.pta_pppoe.ptma_mac[3], 546*0Sstevel@tonic-gate tll->tll_lcladdr.pta_pppoe.ptma_mac[4], 547*0Sstevel@tonic-gate tll->tll_lcladdr.pta_pppoe.ptma_mac[5]); 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate mdb_printf("\n"); 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gate return (WALK_NEXT); 552*0Sstevel@tonic-gate } 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate /* ARGSUSED */ 555*0Sstevel@tonic-gate static int 556*0Sstevel@tonic-gate tunll(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 557*0Sstevel@tonic-gate { 558*0Sstevel@tonic-gate uint_t qfmt = FALSE; 559*0Sstevel@tonic-gate tunll_t tll; 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 562*0Sstevel@tonic-gate mdb_printf("%<u>%?s %-14s %?s %s%</u>\n", "Address", 563*0Sstevel@tonic-gate "Interface Name", "Daemon", "Local Address"); 564*0Sstevel@tonic-gate } 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC) { 567*0Sstevel@tonic-gate if (mdb_vread(&tll, sizeof (tll), addr) == -1) 568*0Sstevel@tonic-gate mdb_warn("failed to read tunll_t at %p", addr); 569*0Sstevel@tonic-gate else 570*0Sstevel@tonic-gate tunll_format(addr, &tll, &qfmt); 571*0Sstevel@tonic-gate } else if (mdb_walk("tunll", (mdb_walk_cb_t)tunll_format, &qfmt) == 572*0Sstevel@tonic-gate -1) { 573*0Sstevel@tonic-gate mdb_warn("failed to walk tunll_list"); 574*0Sstevel@tonic-gate return (DCMD_ERR); 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate return (DCMD_OK); 578*0Sstevel@tonic-gate } 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate union tun_state { 581*0Sstevel@tonic-gate uint32_t tunflags; 582*0Sstevel@tonic-gate tuncl_t tcl; 583*0Sstevel@tonic-gate tunll_t tll; 584*0Sstevel@tonic-gate }; 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate static int 587*0Sstevel@tonic-gate tun_state_read(void *ptr, union tun_state *ts) 588*0Sstevel@tonic-gate { 589*0Sstevel@tonic-gate /* 590*0Sstevel@tonic-gate * First, get the flags on this structure. This is either a 591*0Sstevel@tonic-gate * tuncl_t or a tunll_t. 592*0Sstevel@tonic-gate */ 593*0Sstevel@tonic-gate if (mdb_vread(&ts->tunflags, sizeof (ts->tunflags), (uintptr_t)ptr) == 594*0Sstevel@tonic-gate sizeof (ts->tunflags)) { 595*0Sstevel@tonic-gate if (ts->tunflags & TCLF_ISCLIENT) { 596*0Sstevel@tonic-gate if (mdb_vread(&ts->tcl, sizeof (ts->tcl), 597*0Sstevel@tonic-gate (uintptr_t)ptr) == sizeof (ts->tcl)) { 598*0Sstevel@tonic-gate return (0); 599*0Sstevel@tonic-gate } 600*0Sstevel@tonic-gate } else { 601*0Sstevel@tonic-gate if (mdb_vread(&ts->tll, sizeof (ts->tll), 602*0Sstevel@tonic-gate (uintptr_t)ptr) == sizeof (ts->tll)) { 603*0Sstevel@tonic-gate return (0); 604*0Sstevel@tonic-gate } 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate } 607*0Sstevel@tonic-gate return (-1); 608*0Sstevel@tonic-gate } 609*0Sstevel@tonic-gate 610*0Sstevel@tonic-gate static void 611*0Sstevel@tonic-gate sppptun_qinfo(const queue_t *q, char *buf, size_t nbytes) 612*0Sstevel@tonic-gate { 613*0Sstevel@tonic-gate union tun_state ts; 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate if (tun_state_read(q->q_ptr, &ts) == -1) 616*0Sstevel@tonic-gate return; 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate if (ts.tcl.tcl_flags & TCLF_ISCLIENT) 619*0Sstevel@tonic-gate mdb_snprintf(buf, nbytes, "sppp%d client %04X", 620*0Sstevel@tonic-gate ts.tcl.tcl_unit, ts.tcl.tcl_lsessid); 621*0Sstevel@tonic-gate else 622*0Sstevel@tonic-gate mdb_snprintf(buf, nbytes, "%s", ts.tll.tll_name); 623*0Sstevel@tonic-gate } 624*0Sstevel@tonic-gate 625*0Sstevel@tonic-gate static uintptr_t 626*0Sstevel@tonic-gate sppptun_rnext(const queue_t *q) 627*0Sstevel@tonic-gate { 628*0Sstevel@tonic-gate union tun_state ts; 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate if (tun_state_read(q->q_ptr, &ts) == -1) 631*0Sstevel@tonic-gate return (NULL); 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gate if (ts.tcl.tcl_flags & TCLF_ISCLIENT) { 634*0Sstevel@tonic-gate return ((uintptr_t)ts.tcl.tcl_rq); 635*0Sstevel@tonic-gate } else { 636*0Sstevel@tonic-gate /* Not quite right, but ... */ 637*0Sstevel@tonic-gate return ((uintptr_t)ts.tll.tll_defcl); 638*0Sstevel@tonic-gate } 639*0Sstevel@tonic-gate } 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate static uintptr_t 642*0Sstevel@tonic-gate sppptun_wnext(const queue_t *q) 643*0Sstevel@tonic-gate { 644*0Sstevel@tonic-gate union tun_state ts; 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate if (tun_state_read(q->q_ptr, &ts) == -1) 647*0Sstevel@tonic-gate return (NULL); 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate if (ts.tcl.tcl_flags & TCLF_ISCLIENT) { 650*0Sstevel@tonic-gate if (ts.tcl.tcl_data_tll == NULL) 651*0Sstevel@tonic-gate return (NULL); 652*0Sstevel@tonic-gate if (mdb_vread(&ts.tll, sizeof (ts.tll), 653*0Sstevel@tonic-gate (uintptr_t)ts.tcl.tcl_data_tll) != sizeof (ts.tll)) { 654*0Sstevel@tonic-gate return (NULL); 655*0Sstevel@tonic-gate } 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate return ((uintptr_t)ts.tll.tll_wq); 658*0Sstevel@tonic-gate } 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = { 661*0Sstevel@tonic-gate { "sppp", "[-q]", "display PPP stream state structures", sppp }, 662*0Sstevel@tonic-gate { "sppa", "", "display PPP attachment state structures", sppa }, 663*0Sstevel@tonic-gate { "tuncl", "", "display sppptun client stream state structures", 664*0Sstevel@tonic-gate tuncl }, 665*0Sstevel@tonic-gate { "tunll", "", "display sppptun lower stream state structures", 666*0Sstevel@tonic-gate tunll }, 667*0Sstevel@tonic-gate { NULL } 668*0Sstevel@tonic-gate }; 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate static const mdb_walker_t walkers[] = { 671*0Sstevel@tonic-gate { "sppp", "walk active spppstr_t structures", 672*0Sstevel@tonic-gate sppp_walk_init, sppp_walk_step, NULL }, 673*0Sstevel@tonic-gate { "sppa", "walk active sppa_t structures", 674*0Sstevel@tonic-gate sppa_walk_init, sppa_walk_step, NULL }, 675*0Sstevel@tonic-gate { "tuncl", "walk active tuncl_t structures", 676*0Sstevel@tonic-gate tuncl_walk_init, tuncl_walk_step, tuncl_walk_fini }, 677*0Sstevel@tonic-gate { "tunll", "walk active tunll_t structures", 678*0Sstevel@tonic-gate tunll_walk_init, tunll_walk_step, tunll_walk_fini }, 679*0Sstevel@tonic-gate { NULL } 680*0Sstevel@tonic-gate }; 681*0Sstevel@tonic-gate 682*0Sstevel@tonic-gate static const mdb_qops_t sppp_qops = { sppp_qinfo, sppp_rnext, sppp_wnext }; 683*0Sstevel@tonic-gate static const mdb_qops_t sppptun_qops = { 684*0Sstevel@tonic-gate sppptun_qinfo, sppptun_rnext, sppptun_wnext 685*0Sstevel@tonic-gate }; 686*0Sstevel@tonic-gate static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 687*0Sstevel@tonic-gate 688*0Sstevel@tonic-gate const mdb_modinfo_t * 689*0Sstevel@tonic-gate _mdb_init(void) 690*0Sstevel@tonic-gate { 691*0Sstevel@tonic-gate GElf_Sym sym; 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate if (mdb_lookup_by_obj("sppp", "sppp_uwinit", &sym) == 0) 694*0Sstevel@tonic-gate mdb_qops_install(&sppp_qops, (uintptr_t)sym.st_value); 695*0Sstevel@tonic-gate 696*0Sstevel@tonic-gate if (mdb_lookup_by_obj("sppptun", "sppptun_uwinit", &sym) == 0) 697*0Sstevel@tonic-gate mdb_qops_install(&sppptun_qops, (uintptr_t)sym.st_value); 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate return (&modinfo); 700*0Sstevel@tonic-gate } 701*0Sstevel@tonic-gate 702*0Sstevel@tonic-gate void 703*0Sstevel@tonic-gate _mdb_fini(void) 704*0Sstevel@tonic-gate { 705*0Sstevel@tonic-gate GElf_Sym sym; 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate if (mdb_lookup_by_obj("sppptun", "sppptun_uwinit", &sym) == 0) 708*0Sstevel@tonic-gate mdb_qops_remove(&sppptun_qops, (uintptr_t)sym.st_value); 709*0Sstevel@tonic-gate 710*0Sstevel@tonic-gate if (mdb_lookup_by_obj("sppp", "sppp_uwinit", &sym) == 0) 711*0Sstevel@tonic-gate mdb_qops_remove(&sppp_qops, (uintptr_t)sym.st_value); 712*0Sstevel@tonic-gate } 713