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 2005 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 <sys/avl_impl.h> 34*0Sstevel@tonic-gate #include <net/if.h> 35*0Sstevel@tonic-gate #include <net/route.h> 36*0Sstevel@tonic-gate #include <netinet/in.h> 37*0Sstevel@tonic-gate #include <netinet/ip6.h> 38*0Sstevel@tonic-gate #include <netinet/udp.h> 39*0Sstevel@tonic-gate #include <netinet/sctp.h> 40*0Sstevel@tonic-gate #include <inet/mib2.h> 41*0Sstevel@tonic-gate #include <inet/common.h> 42*0Sstevel@tonic-gate #include <inet/ip.h> 43*0Sstevel@tonic-gate #include <inet/ip_ire.h> 44*0Sstevel@tonic-gate #include <inet/ip6.h> 45*0Sstevel@tonic-gate #include <inet/ipclassifier.h> 46*0Sstevel@tonic-gate #include <inet/mi.h> 47*0Sstevel@tonic-gate #include <sys/squeue_impl.h> 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 50*0Sstevel@tonic-gate #include <mdb/mdb_ks.h> 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate #define ADDR_WIDTH 11 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate typedef struct { 55*0Sstevel@tonic-gate const char *bit_name; /* name of bit */ 56*0Sstevel@tonic-gate const char *bit_descr; /* description of bit's purpose */ 57*0Sstevel@tonic-gate } bitname_t; 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate static const bitname_t squeue_states[] = { 60*0Sstevel@tonic-gate { "SQS_PROC", "being processed" }, 61*0Sstevel@tonic-gate { "SQS_WORKER", "... by a worker thread" }, 62*0Sstevel@tonic-gate { "SQS_ENTER", "... by an squeue_enter() thread" }, 63*0Sstevel@tonic-gate { "SQS_FAST", "... in fast-path mode" }, 64*0Sstevel@tonic-gate { "SQS_USER", "A non interrupt user" }, 65*0Sstevel@tonic-gate { "SQS_BOUND", "worker thread bound to CPU" }, 66*0Sstevel@tonic-gate { "SQS_PROFILE", "profiling enabled" }, 67*0Sstevel@tonic-gate { "SQS_REENTER", "re-entered thred" }, 68*0Sstevel@tonic-gate { NULL } 69*0Sstevel@tonic-gate }; 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate typedef struct illif_walk_data { 72*0Sstevel@tonic-gate ill_g_head_t ill_g_heads[MAX_G_HEADS]; 73*0Sstevel@tonic-gate int ill_list; 74*0Sstevel@tonic-gate ill_if_t ill_if; 75*0Sstevel@tonic-gate } illif_walk_data_t; 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate static int iphdr(uintptr_t, uint_t, int, const mdb_arg_t *); 78*0Sstevel@tonic-gate static int ip6hdr(uintptr_t, uint_t, int, const mdb_arg_t *); 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate int 81*0Sstevel@tonic-gate illif_walk_init(mdb_walk_state_t *wsp) 82*0Sstevel@tonic-gate { 83*0Sstevel@tonic-gate illif_walk_data_t *iw; 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate if (wsp->walk_addr != NULL) { 86*0Sstevel@tonic-gate mdb_warn("illif supports only global walks\n"); 87*0Sstevel@tonic-gate return (WALK_ERR); 88*0Sstevel@tonic-gate } 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate iw = mdb_alloc(sizeof (illif_walk_data_t), UM_SLEEP); 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate if (mdb_readsym(iw->ill_g_heads, MAX_G_HEADS * sizeof (ill_g_head_t), 93*0Sstevel@tonic-gate "ill_g_heads") == -1) { 94*0Sstevel@tonic-gate mdb_warn("failed to read 'ill_g_heads'"); 95*0Sstevel@tonic-gate mdb_free(iw, sizeof (illif_walk_data_t)); 96*0Sstevel@tonic-gate return (WALK_ERR); 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate iw->ill_list = 0; 100*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)iw->IP_VX_ILL_G_LIST(0); 101*0Sstevel@tonic-gate wsp->walk_data = iw; 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate return (WALK_NEXT); 104*0Sstevel@tonic-gate } 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate int 107*0Sstevel@tonic-gate illif_walk_step(mdb_walk_state_t *wsp) 108*0Sstevel@tonic-gate { 109*0Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr; 110*0Sstevel@tonic-gate illif_walk_data_t *iw = wsp->walk_data; 111*0Sstevel@tonic-gate int list = iw->ill_list; 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate if (mdb_vread(&iw->ill_if, sizeof (ill_if_t), addr) == -1) { 114*0Sstevel@tonic-gate mdb_warn("failed to read ill_if_t at %p", addr); 115*0Sstevel@tonic-gate return (WALK_ERR); 116*0Sstevel@tonic-gate } 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)iw->ill_if.illif_next; 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate if (wsp->walk_addr == (uintptr_t)iw->IP_VX_ILL_G_LIST(list)) { 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate if (++list >= MAX_G_HEADS) 123*0Sstevel@tonic-gate return (WALK_DONE); 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate iw->ill_list = list; 126*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)iw->IP_VX_ILL_G_LIST(list); 127*0Sstevel@tonic-gate return (WALK_NEXT); 128*0Sstevel@tonic-gate } 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate return (wsp->walk_callback(addr, iw, wsp->walk_cbdata)); 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate void 134*0Sstevel@tonic-gate illif_walk_fini(mdb_walk_state_t *wsp) 135*0Sstevel@tonic-gate { 136*0Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (illif_walk_data_t)); 137*0Sstevel@tonic-gate } 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate typedef struct illif_cbdata { 140*0Sstevel@tonic-gate uint_t ill_flags; 141*0Sstevel@tonic-gate uintptr_t ill_addr; 142*0Sstevel@tonic-gate int ill_printlist; /* list to be printed (MAX_G_HEADS for all) */ 143*0Sstevel@tonic-gate boolean_t ill_printed; 144*0Sstevel@tonic-gate } illif_cbdata_t; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate static int 147*0Sstevel@tonic-gate illif_cb(uintptr_t addr, const illif_walk_data_t *iw, illif_cbdata_t *id) 148*0Sstevel@tonic-gate { 149*0Sstevel@tonic-gate const char *version; 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate if (id->ill_printlist < MAX_G_HEADS && 152*0Sstevel@tonic-gate id->ill_printlist != iw->ill_list) 153*0Sstevel@tonic-gate return (WALK_NEXT); 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate if (id->ill_flags & DCMD_ADDRSPEC && id->ill_addr != addr) 156*0Sstevel@tonic-gate return (WALK_NEXT); 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate if (id->ill_flags & DCMD_PIPE_OUT) { 159*0Sstevel@tonic-gate mdb_printf("%p\n", addr); 160*0Sstevel@tonic-gate return (WALK_NEXT); 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate switch (iw->ill_list) { 164*0Sstevel@tonic-gate case IP_V4_G_HEAD: version = "v4"; break; 165*0Sstevel@tonic-gate case IP_V6_G_HEAD: version = "v6"; break; 166*0Sstevel@tonic-gate default: version = "??"; break; 167*0Sstevel@tonic-gate } 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate mdb_printf("%?p %2s %?p %10d %?p %s\n", 170*0Sstevel@tonic-gate addr, version, addr + offsetof(ill_if_t, illif_avl_by_ppa), 171*0Sstevel@tonic-gate iw->ill_if.illif_avl_by_ppa.avl_numnodes, 172*0Sstevel@tonic-gate iw->ill_if.illif_ppa_arena, iw->ill_if.illif_name); 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate id->ill_printed = TRUE; 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate return (WALK_NEXT); 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate int 180*0Sstevel@tonic-gate illif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 181*0Sstevel@tonic-gate { 182*0Sstevel@tonic-gate illif_cbdata_t id; 183*0Sstevel@tonic-gate ill_if_t ill_if; 184*0Sstevel@tonic-gate const char *opt_P = NULL; 185*0Sstevel@tonic-gate int printlist = MAX_G_HEADS; 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 188*0Sstevel@tonic-gate 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 189*0Sstevel@tonic-gate return (DCMD_USAGE); 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate if (opt_P != NULL) { 192*0Sstevel@tonic-gate if (strcmp("v4", opt_P) == 0) { 193*0Sstevel@tonic-gate printlist = IP_V4_G_HEAD; 194*0Sstevel@tonic-gate } else if (strcmp("v6", opt_P) == 0) { 195*0Sstevel@tonic-gate printlist = IP_V6_G_HEAD; 196*0Sstevel@tonic-gate } else { 197*0Sstevel@tonic-gate mdb_warn("invalid protocol '%s'\n", opt_P); 198*0Sstevel@tonic-gate return (DCMD_USAGE); 199*0Sstevel@tonic-gate } 200*0Sstevel@tonic-gate } 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) { 203*0Sstevel@tonic-gate mdb_printf("%<u>%?s %2s %?s %10s %?s %-10s%</u>\n", 204*0Sstevel@tonic-gate "ADDR", "IP", "AVLADDR", "NUMNODES", "ARENA", "NAME"); 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate id.ill_flags = flags; 208*0Sstevel@tonic-gate id.ill_addr = addr; 209*0Sstevel@tonic-gate id.ill_printlist = printlist; 210*0Sstevel@tonic-gate id.ill_printed = FALSE; 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate if (mdb_walk("illif", (mdb_walk_cb_t)illif_cb, &id) == -1) { 213*0Sstevel@tonic-gate mdb_warn("can't walk ill_if_t structures"); 214*0Sstevel@tonic-gate return (DCMD_ERR); 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || opt_P != NULL || id.ill_printed) 218*0Sstevel@tonic-gate return (DCMD_OK); 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate /* 221*0Sstevel@tonic-gate * If an address is specified and the walk doesn't find it, 222*0Sstevel@tonic-gate * print it anyway. 223*0Sstevel@tonic-gate */ 224*0Sstevel@tonic-gate if (mdb_vread(&ill_if, sizeof (ill_if_t), addr) == -1) { 225*0Sstevel@tonic-gate mdb_warn("failed to read ill_if_t at %p", addr); 226*0Sstevel@tonic-gate return (DCMD_ERR); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate mdb_printf("%?p %2s %?p %10d %?p %s\n", 230*0Sstevel@tonic-gate addr, "??", addr + offsetof(ill_if_t, illif_avl_by_ppa), 231*0Sstevel@tonic-gate ill_if.illif_avl_by_ppa.avl_numnodes, 232*0Sstevel@tonic-gate ill_if.illif_ppa_arena, ill_if.illif_name); 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate return (DCMD_OK); 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate static void 238*0Sstevel@tonic-gate illif_help(void) 239*0Sstevel@tonic-gate { 240*0Sstevel@tonic-gate mdb_printf("Options:\n"); 241*0Sstevel@tonic-gate mdb_printf("\t-P v4 | v6" 242*0Sstevel@tonic-gate "\tfilter interface structures for the specified protocol\n"); 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate int 246*0Sstevel@tonic-gate ire_walk_init(mdb_walk_state_t *wsp) 247*0Sstevel@tonic-gate { 248*0Sstevel@tonic-gate if (mdb_layered_walk("ire_cache", wsp) == -1) { 249*0Sstevel@tonic-gate mdb_warn("can't walk 'ire_cache'"); 250*0Sstevel@tonic-gate return (WALK_ERR); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate return (WALK_NEXT); 254*0Sstevel@tonic-gate } 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate int 257*0Sstevel@tonic-gate ire_walk_step(mdb_walk_state_t *wsp) 258*0Sstevel@tonic-gate { 259*0Sstevel@tonic-gate ire_t ire; 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) { 262*0Sstevel@tonic-gate mdb_warn("can't read ire at %p", wsp->walk_addr); 263*0Sstevel@tonic-gate return (WALK_ERR); 264*0Sstevel@tonic-gate } 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate return (wsp->walk_callback(wsp->walk_addr, &ire, wsp->walk_cbdata)); 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate static int 270*0Sstevel@tonic-gate ire_format(uintptr_t addr, const ire_t *irep, uint_t *verbose) 271*0Sstevel@tonic-gate { 272*0Sstevel@tonic-gate static const mdb_bitmask_t tmasks[] = { 273*0Sstevel@tonic-gate { "BROADCAST", IRE_BROADCAST, IRE_BROADCAST }, 274*0Sstevel@tonic-gate { "DEFAULT", IRE_DEFAULT, IRE_DEFAULT }, 275*0Sstevel@tonic-gate { "LOCAL", IRE_LOCAL, IRE_LOCAL }, 276*0Sstevel@tonic-gate { "LOOPBACK", IRE_LOOPBACK, IRE_LOOPBACK }, 277*0Sstevel@tonic-gate { "PREFIX", IRE_PREFIX, IRE_PREFIX }, 278*0Sstevel@tonic-gate { "CACHE", IRE_CACHE, IRE_CACHE }, 279*0Sstevel@tonic-gate { "IF_NORESOLVER", IRE_IF_NORESOLVER, IRE_IF_NORESOLVER }, 280*0Sstevel@tonic-gate { "IF_RESOLVER", IRE_IF_RESOLVER, IRE_IF_RESOLVER }, 281*0Sstevel@tonic-gate { "HOST", IRE_HOST, IRE_HOST }, 282*0Sstevel@tonic-gate { "HOST_REDIRECT", IRE_HOST_REDIRECT, IRE_HOST_REDIRECT }, 283*0Sstevel@tonic-gate { "MIPRTUN", IRE_MIPRTUN, IRE_MIPRTUN }, 284*0Sstevel@tonic-gate { NULL, 0, 0 } 285*0Sstevel@tonic-gate }; 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate static const mdb_bitmask_t mmasks[] = { 288*0Sstevel@tonic-gate { "CONDEMNED", IRE_MARK_CONDEMNED, IRE_MARK_CONDEMNED }, 289*0Sstevel@tonic-gate { "NORECV", IRE_MARK_NORECV, IRE_MARK_NORECV }, 290*0Sstevel@tonic-gate { "HIDDEN", IRE_MARK_HIDDEN, IRE_MARK_HIDDEN }, 291*0Sstevel@tonic-gate { "NOADD", IRE_MARK_NOADD, IRE_MARK_NOADD }, 292*0Sstevel@tonic-gate { "TEMPORARY", IRE_MARK_TEMPORARY, IRE_MARK_TEMPORARY }, 293*0Sstevel@tonic-gate { NULL, 0, 0 } 294*0Sstevel@tonic-gate }; 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate static const mdb_bitmask_t fmasks[] = { 297*0Sstevel@tonic-gate { "UP", RTF_UP, RTF_UP }, 298*0Sstevel@tonic-gate { "GATEWAY", RTF_GATEWAY, RTF_GATEWAY }, 299*0Sstevel@tonic-gate { "HOST", RTF_HOST, RTF_HOST }, 300*0Sstevel@tonic-gate { "REJECT", RTF_REJECT, RTF_REJECT }, 301*0Sstevel@tonic-gate { "DYNAMIC", RTF_DYNAMIC, RTF_DYNAMIC }, 302*0Sstevel@tonic-gate { "MODIFIED", RTF_MODIFIED, RTF_MODIFIED }, 303*0Sstevel@tonic-gate { "DONE", RTF_DONE, RTF_DONE }, 304*0Sstevel@tonic-gate { "MASK", RTF_MASK, RTF_MASK }, 305*0Sstevel@tonic-gate { "CLONING", RTF_CLONING, RTF_CLONING }, 306*0Sstevel@tonic-gate { "XRESOLVE", RTF_XRESOLVE, RTF_XRESOLVE }, 307*0Sstevel@tonic-gate { "LLINFO", RTF_LLINFO, RTF_LLINFO }, 308*0Sstevel@tonic-gate { "STATIC", RTF_STATIC, RTF_STATIC }, 309*0Sstevel@tonic-gate { "BLACKHOLE", RTF_BLACKHOLE, RTF_BLACKHOLE }, 310*0Sstevel@tonic-gate { "PRIVATE", RTF_PRIVATE, RTF_PRIVATE }, 311*0Sstevel@tonic-gate { "PROTO2", RTF_PROTO2, RTF_PROTO2 }, 312*0Sstevel@tonic-gate { "PROTO1", RTF_PROTO1, RTF_PROTO1 }, 313*0Sstevel@tonic-gate { "MULTIRT", RTF_MULTIRT, RTF_MULTIRT }, 314*0Sstevel@tonic-gate { "SETSRC", RTF_SETSRC, RTF_SETSRC }, 315*0Sstevel@tonic-gate { NULL, 0, 0 } 316*0Sstevel@tonic-gate }; 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate if (irep->ire_ipversion == 6 && *verbose) { 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate mdb_printf("%<b>%?p%</b> %40N <%hb>\n" 321*0Sstevel@tonic-gate "%?s %40N <%hb>\n" 322*0Sstevel@tonic-gate "%?s %40d <%hb>\n", 323*0Sstevel@tonic-gate addr, &irep->ire_src_addr_v6, irep->ire_type, tmasks, 324*0Sstevel@tonic-gate "", &irep->ire_addr_v6, (ushort_t)irep->ire_marks, mmasks, 325*0Sstevel@tonic-gate "", irep->ire_zoneid, irep->ire_flags, fmasks); 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate } else if (irep->ire_ipversion == 6) { 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate mdb_printf("%?p %30N %30N %4d\n", addr, &irep->ire_src_addr_v6, 330*0Sstevel@tonic-gate &irep->ire_addr_v6, irep->ire_zoneid); 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate } else if (*verbose) { 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate mdb_printf("%<b>%?p%</b> %40I <%hb>\n" 335*0Sstevel@tonic-gate "%?s %40I <%hb>\n" 336*0Sstevel@tonic-gate "%?s %40d <%hb>\n", 337*0Sstevel@tonic-gate addr, irep->ire_src_addr, irep->ire_type, tmasks, 338*0Sstevel@tonic-gate "", irep->ire_addr, (ushort_t)irep->ire_marks, mmasks, 339*0Sstevel@tonic-gate "", irep->ire_zoneid, irep->ire_flags, fmasks); 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate } else { 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate mdb_printf("%?p %30I %30I %4d\n", addr, irep->ire_src_addr, 344*0Sstevel@tonic-gate irep->ire_addr, irep->ire_zoneid); 345*0Sstevel@tonic-gate } 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate return (WALK_NEXT); 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate /* 351*0Sstevel@tonic-gate * There are faster ways to do this. Given the interactive nature of this 352*0Sstevel@tonic-gate * use I don't think its worth much effort. 353*0Sstevel@tonic-gate */ 354*0Sstevel@tonic-gate static unsigned short 355*0Sstevel@tonic-gate ipcksum(void *p, int len) 356*0Sstevel@tonic-gate { 357*0Sstevel@tonic-gate int32_t sum = 0; 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate while (len > 1) { 360*0Sstevel@tonic-gate /* alignment */ 361*0Sstevel@tonic-gate sum += *(uint16_t *)p; 362*0Sstevel@tonic-gate p = (char *)p + sizeof (uint16_t); 363*0Sstevel@tonic-gate if (sum & 0x80000000) 364*0Sstevel@tonic-gate sum = (sum & 0xFFFF) + (sum >> 16); 365*0Sstevel@tonic-gate len -= 2; 366*0Sstevel@tonic-gate } 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate if (len) 369*0Sstevel@tonic-gate sum += (uint16_t)*(unsigned char *)p; 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate while (sum >> 16) 372*0Sstevel@tonic-gate sum = (sum & 0xFFFF) + (sum >> 16); 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate return (~sum); 375*0Sstevel@tonic-gate } 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate static const mdb_bitmask_t tcp_flags[] = { 378*0Sstevel@tonic-gate { "SYN", TH_SYN, TH_SYN }, 379*0Sstevel@tonic-gate { "ACK", TH_ACK, TH_ACK }, 380*0Sstevel@tonic-gate { "FIN", TH_FIN, TH_FIN }, 381*0Sstevel@tonic-gate { "RST", TH_RST, TH_RST }, 382*0Sstevel@tonic-gate { "PSH", TH_PUSH, TH_PUSH }, 383*0Sstevel@tonic-gate { "ECE", TH_ECE, TH_ECE }, 384*0Sstevel@tonic-gate { "CWR", TH_CWR, TH_CWR }, 385*0Sstevel@tonic-gate { NULL, 0, 0 } 386*0Sstevel@tonic-gate }; 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate static void 389*0Sstevel@tonic-gate tcphdr_print(struct tcphdr *tcph) 390*0Sstevel@tonic-gate { 391*0Sstevel@tonic-gate in_port_t sport, dport; 392*0Sstevel@tonic-gate tcp_seq seq, ack; 393*0Sstevel@tonic-gate uint16_t win, urp; 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate mdb_printf("%<b>TCP header%</b>\n"); 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate mdb_nhconvert(&sport, &tcph->th_sport, sizeof (sport)); 398*0Sstevel@tonic-gate mdb_nhconvert(&dport, &tcph->th_dport, sizeof (dport)); 399*0Sstevel@tonic-gate mdb_nhconvert(&seq, &tcph->th_seq, sizeof (seq)); 400*0Sstevel@tonic-gate mdb_nhconvert(&ack, &tcph->th_ack, sizeof (ack)); 401*0Sstevel@tonic-gate mdb_nhconvert(&win, &tcph->th_win, sizeof (win)); 402*0Sstevel@tonic-gate mdb_nhconvert(&urp, &tcph->th_urp, sizeof (urp)); 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate mdb_printf("%<u>%6s %6s %10s %10s %4s %5s %5s %5s %-15s%</u>\n", 405*0Sstevel@tonic-gate "SPORT", "DPORT", "SEQ", "ACK", "HLEN", "WIN", "CSUM", "URP", 406*0Sstevel@tonic-gate "FLAGS"); 407*0Sstevel@tonic-gate mdb_printf("%6hu %6hu %10u %10u %4d %5hu %5hu %5hu <%b>\n", 408*0Sstevel@tonic-gate sport, dport, seq, ack, tcph->th_off << 2, win, 409*0Sstevel@tonic-gate tcph->th_sum, urp, tcph->th_flags, tcp_flags); 410*0Sstevel@tonic-gate mdb_printf("0x%04x 0x%04x 0x%08x 0x%08x\n\n", 411*0Sstevel@tonic-gate sport, dport, seq, ack); 412*0Sstevel@tonic-gate } 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate /* ARGSUSED */ 415*0Sstevel@tonic-gate static int 416*0Sstevel@tonic-gate tcphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 417*0Sstevel@tonic-gate { 418*0Sstevel@tonic-gate struct tcphdr tcph; 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 421*0Sstevel@tonic-gate return (DCMD_USAGE); 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) { 424*0Sstevel@tonic-gate mdb_warn("failed to read TCP header at %p", addr); 425*0Sstevel@tonic-gate return (DCMD_ERR); 426*0Sstevel@tonic-gate } 427*0Sstevel@tonic-gate tcphdr_print(&tcph); 428*0Sstevel@tonic-gate return (DCMD_OK); 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate static void 432*0Sstevel@tonic-gate udphdr_print(struct udphdr *udph) 433*0Sstevel@tonic-gate { 434*0Sstevel@tonic-gate in_port_t sport, dport; 435*0Sstevel@tonic-gate uint16_t hlen; 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate mdb_printf("%<b>UDP header%</b>\n"); 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate mdb_nhconvert(&sport, &udph->uh_sport, sizeof (sport)); 440*0Sstevel@tonic-gate mdb_nhconvert(&dport, &udph->uh_dport, sizeof (dport)); 441*0Sstevel@tonic-gate mdb_nhconvert(&hlen, &udph->uh_ulen, sizeof (hlen)); 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate mdb_printf("%<u>%14s %14s %5s %6s%</u>\n", 444*0Sstevel@tonic-gate "SPORT", "DPORT", "LEN", "CSUM"); 445*0Sstevel@tonic-gate mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %5hu 0x%04hx\n\n", sport, sport, 446*0Sstevel@tonic-gate dport, dport, hlen, udph->uh_sum); 447*0Sstevel@tonic-gate } 448*0Sstevel@tonic-gate 449*0Sstevel@tonic-gate /* ARGSUSED */ 450*0Sstevel@tonic-gate static int 451*0Sstevel@tonic-gate udphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 452*0Sstevel@tonic-gate { 453*0Sstevel@tonic-gate struct udphdr udph; 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 456*0Sstevel@tonic-gate return (DCMD_USAGE); 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate if (mdb_vread(&udph, sizeof (udph), addr) == -1) { 459*0Sstevel@tonic-gate mdb_warn("failed to read UDP header at %p", addr); 460*0Sstevel@tonic-gate return (DCMD_ERR); 461*0Sstevel@tonic-gate } 462*0Sstevel@tonic-gate udphdr_print(&udph); 463*0Sstevel@tonic-gate return (DCMD_OK); 464*0Sstevel@tonic-gate } 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate static void 467*0Sstevel@tonic-gate sctphdr_print(sctp_hdr_t *sctph) 468*0Sstevel@tonic-gate { 469*0Sstevel@tonic-gate in_port_t sport, dport; 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate mdb_printf("%<b>SCTP header%</b>\n"); 472*0Sstevel@tonic-gate mdb_nhconvert(&sport, &sctph->sh_sport, sizeof (sport)); 473*0Sstevel@tonic-gate mdb_nhconvert(&dport, &sctph->sh_dport, sizeof (dport)); 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate mdb_printf("%<u>%14s %14s %10s %10s%</u>\n", 476*0Sstevel@tonic-gate "SPORT", "DPORT", "VTAG", "CHKSUM"); 477*0Sstevel@tonic-gate mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %10u 0x%08x\n\n", sport, sport, 478*0Sstevel@tonic-gate dport, dport, sctph->sh_verf, sctph->sh_chksum); 479*0Sstevel@tonic-gate } 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate /* ARGSUSED */ 482*0Sstevel@tonic-gate static int 483*0Sstevel@tonic-gate sctphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 484*0Sstevel@tonic-gate { 485*0Sstevel@tonic-gate sctp_hdr_t sctph; 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 488*0Sstevel@tonic-gate return (DCMD_USAGE); 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) { 491*0Sstevel@tonic-gate mdb_warn("failed to read SCTP header at %p", addr); 492*0Sstevel@tonic-gate return (DCMD_ERR); 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate sctphdr_print(&sctph); 496*0Sstevel@tonic-gate return (DCMD_OK); 497*0Sstevel@tonic-gate } 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate static int 500*0Sstevel@tonic-gate transport_hdr(int proto, uintptr_t addr) 501*0Sstevel@tonic-gate { 502*0Sstevel@tonic-gate mdb_printf("\n"); 503*0Sstevel@tonic-gate switch (proto) { 504*0Sstevel@tonic-gate case IPPROTO_TCP: { 505*0Sstevel@tonic-gate struct tcphdr tcph; 506*0Sstevel@tonic-gate 507*0Sstevel@tonic-gate if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) { 508*0Sstevel@tonic-gate mdb_warn("failed to read TCP header at %p", addr); 509*0Sstevel@tonic-gate return (DCMD_ERR); 510*0Sstevel@tonic-gate } 511*0Sstevel@tonic-gate tcphdr_print(&tcph); 512*0Sstevel@tonic-gate break; 513*0Sstevel@tonic-gate } 514*0Sstevel@tonic-gate case IPPROTO_UDP: { 515*0Sstevel@tonic-gate struct udphdr udph; 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate if (mdb_vread(&udph, sizeof (udph), addr) == -1) { 518*0Sstevel@tonic-gate mdb_warn("failed to read UDP header at %p", addr); 519*0Sstevel@tonic-gate return (DCMD_ERR); 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate udphdr_print(&udph); 522*0Sstevel@tonic-gate break; 523*0Sstevel@tonic-gate } 524*0Sstevel@tonic-gate case IPPROTO_SCTP: { 525*0Sstevel@tonic-gate sctp_hdr_t sctph; 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) { 528*0Sstevel@tonic-gate mdb_warn("failed to read SCTP header at %p", addr); 529*0Sstevel@tonic-gate return (DCMD_ERR); 530*0Sstevel@tonic-gate } 531*0Sstevel@tonic-gate sctphdr_print(&sctph); 532*0Sstevel@tonic-gate break; 533*0Sstevel@tonic-gate } 534*0Sstevel@tonic-gate default: 535*0Sstevel@tonic-gate break; 536*0Sstevel@tonic-gate } 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate return (DCMD_OK); 539*0Sstevel@tonic-gate } 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate static const mdb_bitmask_t ip_flags[] = { 542*0Sstevel@tonic-gate { "DF", IPH_DF, IPH_DF }, 543*0Sstevel@tonic-gate { "MF", IPH_MF, IPH_MF }, 544*0Sstevel@tonic-gate { NULL, 0, 0 } 545*0Sstevel@tonic-gate }; 546*0Sstevel@tonic-gate 547*0Sstevel@tonic-gate /* ARGSUSED */ 548*0Sstevel@tonic-gate static int 549*0Sstevel@tonic-gate iphdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 550*0Sstevel@tonic-gate { 551*0Sstevel@tonic-gate uint_t verbose = FALSE, force = FALSE; 552*0Sstevel@tonic-gate ipha_t iph[1]; 553*0Sstevel@tonic-gate uint16_t ver, totlen, hdrlen, ipid, off, csum; 554*0Sstevel@tonic-gate uintptr_t nxt_proto; 555*0Sstevel@tonic-gate char exp_csum[8]; 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 558*0Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose, 559*0Sstevel@tonic-gate 'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc) 560*0Sstevel@tonic-gate return (DCMD_USAGE); 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate if (mdb_vread(iph, sizeof (*iph), addr) == -1) { 563*0Sstevel@tonic-gate mdb_warn("failed to read IPv4 header at %p", addr); 564*0Sstevel@tonic-gate return (DCMD_ERR); 565*0Sstevel@tonic-gate } 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate ver = (iph->ipha_version_and_hdr_length & 0xf0) >> 4; 568*0Sstevel@tonic-gate if (ver != IPV4_VERSION) { 569*0Sstevel@tonic-gate if (ver == IPV6_VERSION) { 570*0Sstevel@tonic-gate return (ip6hdr(addr, flags, argc, argv)); 571*0Sstevel@tonic-gate } else if (!force) { 572*0Sstevel@tonic-gate mdb_warn("unknown IP version: %d\n", ver); 573*0Sstevel@tonic-gate return (DCMD_ERR); 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate mdb_printf("%<b>IPv4 header%</b>\n"); 578*0Sstevel@tonic-gate mdb_printf("%-34s %-34s\n" 579*0Sstevel@tonic-gate "%<u>%-4s %-4s %-5s %-5s %-6s %-5s %-5s %-6s %-8s %-6s%</u>\n", 580*0Sstevel@tonic-gate "SRC", "DST", 581*0Sstevel@tonic-gate "HLEN", "TOS", "LEN", "ID", "OFFSET", "TTL", "PROTO", "CHKSUM", 582*0Sstevel@tonic-gate "EXP-CSUM", "FLGS"); 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate hdrlen = (iph->ipha_version_and_hdr_length & 0x0f) << 2; 585*0Sstevel@tonic-gate mdb_nhconvert(&totlen, &iph->ipha_length, sizeof (totlen)); 586*0Sstevel@tonic-gate mdb_nhconvert(&ipid, &iph->ipha_ident, sizeof (ipid)); 587*0Sstevel@tonic-gate mdb_nhconvert(&off, &iph->ipha_fragment_offset_and_flags, sizeof (off)); 588*0Sstevel@tonic-gate if (hdrlen == IP_SIMPLE_HDR_LENGTH) { 589*0Sstevel@tonic-gate if ((csum = ipcksum(iph, sizeof (*iph))) != 0) 590*0Sstevel@tonic-gate csum = ~(~csum + ~iph->ipha_hdr_checksum); 591*0Sstevel@tonic-gate else 592*0Sstevel@tonic-gate csum = iph->ipha_hdr_checksum; 593*0Sstevel@tonic-gate mdb_snprintf(exp_csum, 8, "%u", csum); 594*0Sstevel@tonic-gate } else { 595*0Sstevel@tonic-gate mdb_snprintf(exp_csum, 8, "<n/a>"); 596*0Sstevel@tonic-gate } 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate mdb_printf("%-34I %-34I%\n" 599*0Sstevel@tonic-gate "%-4d %-4d %-5hu %-5hu %-6hu %-5hu %-5hu %-6u %-8s <%5hb>\n", 600*0Sstevel@tonic-gate iph->ipha_src, iph->ipha_dst, 601*0Sstevel@tonic-gate hdrlen, iph->ipha_type_of_service, totlen, ipid, 602*0Sstevel@tonic-gate (off << 3) & 0xffff, iph->ipha_ttl, iph->ipha_protocol, 603*0Sstevel@tonic-gate iph->ipha_hdr_checksum, exp_csum, off, ip_flags); 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate if (verbose) { 606*0Sstevel@tonic-gate nxt_proto = addr + hdrlen; 607*0Sstevel@tonic-gate return (transport_hdr(iph->ipha_protocol, nxt_proto)); 608*0Sstevel@tonic-gate } else { 609*0Sstevel@tonic-gate return (DCMD_OK); 610*0Sstevel@tonic-gate } 611*0Sstevel@tonic-gate } 612*0Sstevel@tonic-gate 613*0Sstevel@tonic-gate /* ARGSUSED */ 614*0Sstevel@tonic-gate static int 615*0Sstevel@tonic-gate ip6hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 616*0Sstevel@tonic-gate { 617*0Sstevel@tonic-gate uint_t verbose = FALSE, force = FALSE; 618*0Sstevel@tonic-gate ip6_t iph[1]; 619*0Sstevel@tonic-gate int ver, class, flow; 620*0Sstevel@tonic-gate uint16_t plen; 621*0Sstevel@tonic-gate uintptr_t nxt_proto; 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 624*0Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose, 625*0Sstevel@tonic-gate 'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc) 626*0Sstevel@tonic-gate return (DCMD_USAGE); 627*0Sstevel@tonic-gate 628*0Sstevel@tonic-gate if (mdb_vread(iph, sizeof (*iph), addr) == -1) { 629*0Sstevel@tonic-gate mdb_warn("failed to read IPv6 header at %p", addr); 630*0Sstevel@tonic-gate return (DCMD_ERR); 631*0Sstevel@tonic-gate } 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gate ver = (iph->ip6_vfc & 0xf0) >> 4; 634*0Sstevel@tonic-gate if (ver != IPV6_VERSION) { 635*0Sstevel@tonic-gate if (ver == IPV4_VERSION) { 636*0Sstevel@tonic-gate return (iphdr(addr, flags, argc, argv)); 637*0Sstevel@tonic-gate } else if (!force) { 638*0Sstevel@tonic-gate mdb_warn("unknown IP version: %d\n", ver); 639*0Sstevel@tonic-gate return (DCMD_ERR); 640*0Sstevel@tonic-gate } 641*0Sstevel@tonic-gate } 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate mdb_printf("%<b>IPv6 header%</b>\n"); 644*0Sstevel@tonic-gate mdb_printf("%<u>%-26s %-26s %4s %7s %5s %3s %3s%</u>\n", 645*0Sstevel@tonic-gate "SRC", "DST", "TCLS", "FLOW-ID", "PLEN", "NXT", "HOP"); 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate class = (iph->ip6_vcf & IPV6_FLOWINFO_TCLASS) >> 20; 648*0Sstevel@tonic-gate mdb_nhconvert(&class, &class, sizeof (class)); 649*0Sstevel@tonic-gate flow = iph->ip6_vcf & IPV6_FLOWINFO_FLOWLABEL; 650*0Sstevel@tonic-gate mdb_nhconvert(&flow, &flow, sizeof (flow)); 651*0Sstevel@tonic-gate mdb_nhconvert(&plen, &iph->ip6_plen, sizeof (plen)); 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate mdb_printf("%-26N %-26N %4d %7d %5hu %3d %3d\n", 654*0Sstevel@tonic-gate &iph->ip6_src, &iph->ip6_dst, 655*0Sstevel@tonic-gate class, flow, plen, iph->ip6_nxt, iph->ip6_hlim); 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate if (verbose) { 658*0Sstevel@tonic-gate nxt_proto = addr + sizeof (ip6_t); 659*0Sstevel@tonic-gate return (transport_hdr(iph->ip6_nxt, nxt_proto)); 660*0Sstevel@tonic-gate } else { 661*0Sstevel@tonic-gate return (DCMD_OK); 662*0Sstevel@tonic-gate } 663*0Sstevel@tonic-gate } 664*0Sstevel@tonic-gate 665*0Sstevel@tonic-gate int 666*0Sstevel@tonic-gate ire(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 667*0Sstevel@tonic-gate { 668*0Sstevel@tonic-gate uint_t verbose = FALSE; 669*0Sstevel@tonic-gate ire_t ire; 670*0Sstevel@tonic-gate 671*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 672*0Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) 673*0Sstevel@tonic-gate return (DCMD_USAGE); 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 676*0Sstevel@tonic-gate 677*0Sstevel@tonic-gate if (verbose) { 678*0Sstevel@tonic-gate mdb_printf("%?s %40s %-20s%\n" 679*0Sstevel@tonic-gate "%?s %40s %-20s%\n" 680*0Sstevel@tonic-gate "%<u>%?s %40s %-20s%</u>\n", 681*0Sstevel@tonic-gate "ADDR", "SRC", "TYPE", 682*0Sstevel@tonic-gate "", "DST", "MARKS", 683*0Sstevel@tonic-gate "", "ZONE", "FLAGS"); 684*0Sstevel@tonic-gate } else { 685*0Sstevel@tonic-gate mdb_printf("%<u>%?s %30s %30s %4s%</u>\n", 686*0Sstevel@tonic-gate "ADDR", "SRC", "DST", "ZONE"); 687*0Sstevel@tonic-gate } 688*0Sstevel@tonic-gate } 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC) { 691*0Sstevel@tonic-gate (void) mdb_vread(&ire, sizeof (ire_t), addr); 692*0Sstevel@tonic-gate (void) ire_format(addr, &ire, &verbose); 693*0Sstevel@tonic-gate } else if (mdb_walk("ire", (mdb_walk_cb_t)ire_format, &verbose) == -1) { 694*0Sstevel@tonic-gate mdb_warn("failed to walk ire table"); 695*0Sstevel@tonic-gate return (DCMD_ERR); 696*0Sstevel@tonic-gate } 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gate return (DCMD_OK); 699*0Sstevel@tonic-gate } 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate static size_t 702*0Sstevel@tonic-gate mi_osize(const queue_t *q) 703*0Sstevel@tonic-gate { 704*0Sstevel@tonic-gate /* 705*0Sstevel@tonic-gate * The code in common/inet/mi.c allocates an extra word to store the 706*0Sstevel@tonic-gate * size of the allocation. An mi_o_s is thus a size_t plus an mi_o_s. 707*0Sstevel@tonic-gate */ 708*0Sstevel@tonic-gate struct mi_block { 709*0Sstevel@tonic-gate size_t mi_nbytes; 710*0Sstevel@tonic-gate struct mi_o_s mi_o; 711*0Sstevel@tonic-gate } m; 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate if (mdb_vread(&m, sizeof (m), (uintptr_t)q->q_ptr - 714*0Sstevel@tonic-gate sizeof (m)) == sizeof (m)) 715*0Sstevel@tonic-gate return (m.mi_nbytes - sizeof (m)); 716*0Sstevel@tonic-gate 717*0Sstevel@tonic-gate return (0); 718*0Sstevel@tonic-gate } 719*0Sstevel@tonic-gate 720*0Sstevel@tonic-gate static void 721*0Sstevel@tonic-gate ip_ill_qinfo(const queue_t *q, char *buf, size_t nbytes) 722*0Sstevel@tonic-gate { 723*0Sstevel@tonic-gate char name[32]; 724*0Sstevel@tonic-gate ill_t ill; 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate if (mdb_vread(&ill, sizeof (ill), 727*0Sstevel@tonic-gate (uintptr_t)q->q_ptr) == sizeof (ill) && 728*0Sstevel@tonic-gate mdb_readstr(name, sizeof (name), (uintptr_t)ill.ill_name) > 0) 729*0Sstevel@tonic-gate (void) mdb_snprintf(buf, nbytes, "if: %s", name); 730*0Sstevel@tonic-gate } 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate void 733*0Sstevel@tonic-gate ip_qinfo(const queue_t *q, char *buf, size_t nbytes) 734*0Sstevel@tonic-gate { 735*0Sstevel@tonic-gate size_t size = mi_osize(q); 736*0Sstevel@tonic-gate 737*0Sstevel@tonic-gate if (size == sizeof (ill_t)) 738*0Sstevel@tonic-gate ip_ill_qinfo(q, buf, nbytes); 739*0Sstevel@tonic-gate } 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate uintptr_t 742*0Sstevel@tonic-gate ip_rnext(const queue_t *q) 743*0Sstevel@tonic-gate { 744*0Sstevel@tonic-gate size_t size = mi_osize(q); 745*0Sstevel@tonic-gate ill_t ill; 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill), 748*0Sstevel@tonic-gate (uintptr_t)q->q_ptr) == sizeof (ill)) 749*0Sstevel@tonic-gate return ((uintptr_t)ill.ill_rq); 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate return (NULL); 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate uintptr_t 755*0Sstevel@tonic-gate ip_wnext(const queue_t *q) 756*0Sstevel@tonic-gate { 757*0Sstevel@tonic-gate size_t size = mi_osize(q); 758*0Sstevel@tonic-gate ill_t ill; 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill), 761*0Sstevel@tonic-gate (uintptr_t)q->q_ptr) == sizeof (ill)) 762*0Sstevel@tonic-gate return ((uintptr_t)ill.ill_wq); 763*0Sstevel@tonic-gate 764*0Sstevel@tonic-gate return (NULL); 765*0Sstevel@tonic-gate } 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate /* 768*0Sstevel@tonic-gate * Print the core fields in an squeue_t. With the "-v" argument, 769*0Sstevel@tonic-gate * provide more verbose output. 770*0Sstevel@tonic-gate */ 771*0Sstevel@tonic-gate static int 772*0Sstevel@tonic-gate squeue(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 773*0Sstevel@tonic-gate { 774*0Sstevel@tonic-gate unsigned int i; 775*0Sstevel@tonic-gate unsigned int verbose = FALSE; 776*0Sstevel@tonic-gate const int SQUEUE_STATEDELT = (int)(sizeof (uintptr_t) + 9); 777*0Sstevel@tonic-gate boolean_t arm; 778*0Sstevel@tonic-gate squeue_t squeue; 779*0Sstevel@tonic-gate 780*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 781*0Sstevel@tonic-gate if (mdb_walk_dcmd("genunix`squeue_cache", "ip`squeue", 782*0Sstevel@tonic-gate argc, argv) == -1) { 783*0Sstevel@tonic-gate mdb_warn("failed to walk squeue cache"); 784*0Sstevel@tonic-gate return (DCMD_ERR); 785*0Sstevel@tonic-gate } 786*0Sstevel@tonic-gate return (DCMD_OK); 787*0Sstevel@tonic-gate } 788*0Sstevel@tonic-gate 789*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) 790*0Sstevel@tonic-gate != argc) 791*0Sstevel@tonic-gate return (DCMD_USAGE); 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate if (!DCMD_HDRSPEC(flags) && verbose) 794*0Sstevel@tonic-gate mdb_printf("\n\n"); 795*0Sstevel@tonic-gate 796*0Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) || verbose) { 797*0Sstevel@tonic-gate mdb_printf("%?s %-5s %-3s %?s %?s %?s\n", 798*0Sstevel@tonic-gate "ADDR", "STATE", "CPU", 799*0Sstevel@tonic-gate "FIRST", "LAST", "WORKER"); 800*0Sstevel@tonic-gate } 801*0Sstevel@tonic-gate 802*0Sstevel@tonic-gate if (mdb_vread(&squeue, sizeof (squeue_t), addr) == -1) { 803*0Sstevel@tonic-gate mdb_warn("cannot read squeue_t at %p", addr); 804*0Sstevel@tonic-gate return (DCMD_ERR); 805*0Sstevel@tonic-gate } 806*0Sstevel@tonic-gate 807*0Sstevel@tonic-gate mdb_printf("%0?p %05x %3d %0?p %0?p %0?p\n", 808*0Sstevel@tonic-gate addr, squeue.sq_state, squeue.sq_bind, 809*0Sstevel@tonic-gate squeue.sq_first, squeue.sq_last, squeue.sq_worker); 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate if (!verbose) 812*0Sstevel@tonic-gate return (DCMD_OK); 813*0Sstevel@tonic-gate 814*0Sstevel@tonic-gate arm = B_TRUE; 815*0Sstevel@tonic-gate for (i = 0; squeue_states[i].bit_name != NULL; i++) { 816*0Sstevel@tonic-gate if (((squeue.sq_state) & (1 << i)) == 0) 817*0Sstevel@tonic-gate continue; 818*0Sstevel@tonic-gate 819*0Sstevel@tonic-gate if (arm) { 820*0Sstevel@tonic-gate mdb_printf("%*s|\n", SQUEUE_STATEDELT, ""); 821*0Sstevel@tonic-gate mdb_printf("%*s+--> ", SQUEUE_STATEDELT, ""); 822*0Sstevel@tonic-gate arm = B_FALSE; 823*0Sstevel@tonic-gate } else 824*0Sstevel@tonic-gate mdb_printf("%*s ", SQUEUE_STATEDELT, ""); 825*0Sstevel@tonic-gate 826*0Sstevel@tonic-gate mdb_printf("%-12s %s\n", squeue_states[i].bit_name, 827*0Sstevel@tonic-gate squeue_states[i].bit_descr); 828*0Sstevel@tonic-gate } 829*0Sstevel@tonic-gate 830*0Sstevel@tonic-gate return (DCMD_OK); 831*0Sstevel@tonic-gate } 832*0Sstevel@tonic-gate 833*0Sstevel@tonic-gate static void 834*0Sstevel@tonic-gate ip_squeue_help(void) 835*0Sstevel@tonic-gate { 836*0Sstevel@tonic-gate mdb_printf("Print the core information for a given NCA squeue_t.\n\n"); 837*0Sstevel@tonic-gate mdb_printf("Options:\n"); 838*0Sstevel@tonic-gate mdb_printf("\t-v\tbe verbose (more descriptive)\n"); 839*0Sstevel@tonic-gate } 840*0Sstevel@tonic-gate 841*0Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = { 842*0Sstevel@tonic-gate { "illif", "?[-P v4 | v6]", 843*0Sstevel@tonic-gate "display or filter IP Lower Level InterFace structures", illif, 844*0Sstevel@tonic-gate illif_help }, 845*0Sstevel@tonic-gate { "iphdr", ":[-vf]", "display an IPv4 header", iphdr }, 846*0Sstevel@tonic-gate { "ip6hdr", ":[-vf]", "display an IPv6 header", ip6hdr }, 847*0Sstevel@tonic-gate { "ire", "?[-v]", "display Internet Route Entry structures", ire }, 848*0Sstevel@tonic-gate { "squeue", ":[-v]", "print core squeue_t info", squeue, 849*0Sstevel@tonic-gate ip_squeue_help }, 850*0Sstevel@tonic-gate { "tcphdr", ":", "display a TCP header", tcphdr }, 851*0Sstevel@tonic-gate { "udphdr", ":", "display an UDP header", udphdr }, 852*0Sstevel@tonic-gate { "sctphdr", ":", "display an SCTP header", sctphdr }, 853*0Sstevel@tonic-gate { NULL } 854*0Sstevel@tonic-gate }; 855*0Sstevel@tonic-gate 856*0Sstevel@tonic-gate static const mdb_walker_t walkers[] = { 857*0Sstevel@tonic-gate { "illif", "walk list of ill interface types", 858*0Sstevel@tonic-gate illif_walk_init, illif_walk_step, illif_walk_fini }, 859*0Sstevel@tonic-gate { "ire", "walk active ire_t structures", 860*0Sstevel@tonic-gate ire_walk_init, ire_walk_step, NULL }, 861*0Sstevel@tonic-gate { NULL } 862*0Sstevel@tonic-gate }; 863*0Sstevel@tonic-gate 864*0Sstevel@tonic-gate static const mdb_qops_t ip_qops = { ip_qinfo, ip_rnext, ip_wnext }; 865*0Sstevel@tonic-gate static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 866*0Sstevel@tonic-gate 867*0Sstevel@tonic-gate const mdb_modinfo_t * 868*0Sstevel@tonic-gate _mdb_init(void) 869*0Sstevel@tonic-gate { 870*0Sstevel@tonic-gate GElf_Sym sym; 871*0Sstevel@tonic-gate 872*0Sstevel@tonic-gate if (mdb_lookup_by_obj("ip", "winit", &sym) == 0) 873*0Sstevel@tonic-gate mdb_qops_install(&ip_qops, (uintptr_t)sym.st_value); 874*0Sstevel@tonic-gate 875*0Sstevel@tonic-gate return (&modinfo); 876*0Sstevel@tonic-gate } 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate void 879*0Sstevel@tonic-gate _mdb_fini(void) 880*0Sstevel@tonic-gate { 881*0Sstevel@tonic-gate GElf_Sym sym; 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate if (mdb_lookup_by_obj("ip", "winit", &sym) == 0) 884*0Sstevel@tonic-gate mdb_qops_remove(&ip_qops, (uintptr_t)sym.st_value); 885*0Sstevel@tonic-gate } 886