10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 52546Scarlsonj * Common Development and Distribution License (the "License"). 62546Scarlsonj * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 228485SPeter.Memishian@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #include <sys/types.h> 270Sstevel@tonic-gate #include <sys/stropts.h> 280Sstevel@tonic-gate #include <sys/stream.h> 290Sstevel@tonic-gate #include <sys/socket.h> 300Sstevel@tonic-gate #include <sys/avl_impl.h> 31*9089SVasumathi.Sundaram@Sun.COM #include <net/if_types.h> 320Sstevel@tonic-gate #include <net/if.h> 330Sstevel@tonic-gate #include <net/route.h> 340Sstevel@tonic-gate #include <netinet/in.h> 350Sstevel@tonic-gate #include <netinet/ip6.h> 360Sstevel@tonic-gate #include <netinet/udp.h> 370Sstevel@tonic-gate #include <netinet/sctp.h> 380Sstevel@tonic-gate #include <inet/mib2.h> 390Sstevel@tonic-gate #include <inet/common.h> 400Sstevel@tonic-gate #include <inet/ip.h> 410Sstevel@tonic-gate #include <inet/ip_ire.h> 420Sstevel@tonic-gate #include <inet/ip6.h> 430Sstevel@tonic-gate #include <inet/ipclassifier.h> 440Sstevel@tonic-gate #include <inet/mi.h> 450Sstevel@tonic-gate #include <sys/squeue_impl.h> 465023Scarlsonj #include <sys/modhash_impl.h> 475940Ssowmini #include <inet/ip_ndp.h> 485940Ssowmini #include <inet/ip_if.h> 495940Ssowmini #include <sys/dlpi.h> 500Sstevel@tonic-gate 510Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 520Sstevel@tonic-gate #include <mdb/mdb_ks.h> 530Sstevel@tonic-gate 540Sstevel@tonic-gate #define ADDR_WIDTH 11 555940Ssowmini #define L2MAXADDRSTRLEN 255 565940Ssowmini #define MAX_SAP_LEN 255 57*9089SVasumathi.Sundaram@Sun.COM #define DEFCOLS 80 580Sstevel@tonic-gate 590Sstevel@tonic-gate typedef struct { 600Sstevel@tonic-gate const char *bit_name; /* name of bit */ 610Sstevel@tonic-gate const char *bit_descr; /* description of bit's purpose */ 620Sstevel@tonic-gate } bitname_t; 630Sstevel@tonic-gate 640Sstevel@tonic-gate static const bitname_t squeue_states[] = { 650Sstevel@tonic-gate { "SQS_PROC", "being processed" }, 660Sstevel@tonic-gate { "SQS_WORKER", "... by a worker thread" }, 670Sstevel@tonic-gate { "SQS_ENTER", "... by an squeue_enter() thread" }, 680Sstevel@tonic-gate { "SQS_FAST", "... in fast-path mode" }, 690Sstevel@tonic-gate { "SQS_USER", "A non interrupt user" }, 700Sstevel@tonic-gate { "SQS_BOUND", "worker thread bound to CPU" }, 710Sstevel@tonic-gate { "SQS_PROFILE", "profiling enabled" }, 720Sstevel@tonic-gate { "SQS_REENTER", "re-entered thred" }, 730Sstevel@tonic-gate { NULL } 740Sstevel@tonic-gate }; 750Sstevel@tonic-gate 760Sstevel@tonic-gate typedef struct illif_walk_data { 770Sstevel@tonic-gate ill_g_head_t ill_g_heads[MAX_G_HEADS]; 780Sstevel@tonic-gate int ill_list; 790Sstevel@tonic-gate ill_if_t ill_if; 800Sstevel@tonic-gate } illif_walk_data_t; 810Sstevel@tonic-gate 825940Ssowmini typedef struct nce_walk_data_s { 835940Ssowmini struct ndp_g_s nce_ip_ndp; 845940Ssowmini int nce_hash_tbl_index; 855940Ssowmini nce_t nce; 865940Ssowmini } nce_walk_data_t; 875940Ssowmini 885940Ssowmini typedef struct nce_cbdata_s { 895940Ssowmini uintptr_t nce_addr; 905940Ssowmini int nce_ipversion; 915940Ssowmini } nce_cbdata_t; 925940Ssowmini 935940Ssowmini typedef struct ire_cbdata_s { 945940Ssowmini int ire_ipversion; 955940Ssowmini boolean_t verbose; 965940Ssowmini } ire_cbdata_t; 975940Ssowmini 985023Scarlsonj typedef struct th_walk_data { 995023Scarlsonj uint_t thw_non_zero_only; 1005023Scarlsonj boolean_t thw_match; 1015023Scarlsonj uintptr_t thw_matchkey; 1025023Scarlsonj uintptr_t thw_ipst; 1035023Scarlsonj clock_t thw_lbolt; 1045023Scarlsonj } th_walk_data_t; 1055023Scarlsonj 106*9089SVasumathi.Sundaram@Sun.COM typedef struct ipcl_hash_walk_data_s { 107*9089SVasumathi.Sundaram@Sun.COM conn_t *conn; 108*9089SVasumathi.Sundaram@Sun.COM int connf_tbl_index; 109*9089SVasumathi.Sundaram@Sun.COM uintptr_t hash_tbl; 110*9089SVasumathi.Sundaram@Sun.COM int hash_tbl_size; 111*9089SVasumathi.Sundaram@Sun.COM } ipcl_hash_walk_data_t; 112*9089SVasumathi.Sundaram@Sun.COM 113*9089SVasumathi.Sundaram@Sun.COM typedef struct ill_walk_data_s { 114*9089SVasumathi.Sundaram@Sun.COM ill_t ill; 115*9089SVasumathi.Sundaram@Sun.COM } ill_walk_data_t; 116*9089SVasumathi.Sundaram@Sun.COM 117*9089SVasumathi.Sundaram@Sun.COM typedef struct ill_cbdata_s { 118*9089SVasumathi.Sundaram@Sun.COM uintptr_t ill_addr; 119*9089SVasumathi.Sundaram@Sun.COM int ill_ipversion; 120*9089SVasumathi.Sundaram@Sun.COM boolean_t verbose; 121*9089SVasumathi.Sundaram@Sun.COM } ill_cbdata_t; 122*9089SVasumathi.Sundaram@Sun.COM 123*9089SVasumathi.Sundaram@Sun.COM typedef struct ipif_walk_data_s { 124*9089SVasumathi.Sundaram@Sun.COM ipif_t ipif; 125*9089SVasumathi.Sundaram@Sun.COM } ipif_walk_data_t; 126*9089SVasumathi.Sundaram@Sun.COM 127*9089SVasumathi.Sundaram@Sun.COM typedef struct ipif_cbdata_s { 128*9089SVasumathi.Sundaram@Sun.COM ill_t ill; 129*9089SVasumathi.Sundaram@Sun.COM int ipif_ipversion; 130*9089SVasumathi.Sundaram@Sun.COM boolean_t verbose; 131*9089SVasumathi.Sundaram@Sun.COM } ipif_cbdata_t; 132*9089SVasumathi.Sundaram@Sun.COM 133*9089SVasumathi.Sundaram@Sun.COM typedef struct hash_walk_arg_s { 134*9089SVasumathi.Sundaram@Sun.COM off_t tbl_off; 135*9089SVasumathi.Sundaram@Sun.COM off_t size_off; 136*9089SVasumathi.Sundaram@Sun.COM } hash_walk_arg_t; 137*9089SVasumathi.Sundaram@Sun.COM 138*9089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t udp_hash_arg = { 139*9089SVasumathi.Sundaram@Sun.COM OFFSETOF(ip_stack_t, ips_ipcl_udp_fanout), 140*9089SVasumathi.Sundaram@Sun.COM OFFSETOF(ip_stack_t, ips_ipcl_udp_fanout_size) 141*9089SVasumathi.Sundaram@Sun.COM }; 142*9089SVasumathi.Sundaram@Sun.COM 143*9089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t conn_hash_arg = { 144*9089SVasumathi.Sundaram@Sun.COM OFFSETOF(ip_stack_t, ips_ipcl_conn_fanout), 145*9089SVasumathi.Sundaram@Sun.COM OFFSETOF(ip_stack_t, ips_ipcl_conn_fanout_size) 146*9089SVasumathi.Sundaram@Sun.COM }; 147*9089SVasumathi.Sundaram@Sun.COM 148*9089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t bind_hash_arg = { 149*9089SVasumathi.Sundaram@Sun.COM OFFSETOF(ip_stack_t, ips_ipcl_bind_fanout), 150*9089SVasumathi.Sundaram@Sun.COM OFFSETOF(ip_stack_t, ips_ipcl_bind_fanout_size) 151*9089SVasumathi.Sundaram@Sun.COM }; 152*9089SVasumathi.Sundaram@Sun.COM 153*9089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t proto_hash_arg = { 154*9089SVasumathi.Sundaram@Sun.COM OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout), 155*9089SVasumathi.Sundaram@Sun.COM 0 156*9089SVasumathi.Sundaram@Sun.COM }; 157*9089SVasumathi.Sundaram@Sun.COM 158*9089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t proto_v6_hash_arg = { 159*9089SVasumathi.Sundaram@Sun.COM OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v6), 160*9089SVasumathi.Sundaram@Sun.COM 0 161*9089SVasumathi.Sundaram@Sun.COM }; 162*9089SVasumathi.Sundaram@Sun.COM 163*9089SVasumathi.Sundaram@Sun.COM typedef struct ip_list_walk_data_s { 164*9089SVasumathi.Sundaram@Sun.COM off_t nextoff; 165*9089SVasumathi.Sundaram@Sun.COM } ip_list_walk_data_t; 166*9089SVasumathi.Sundaram@Sun.COM 167*9089SVasumathi.Sundaram@Sun.COM typedef struct ip_list_walk_arg_s { 168*9089SVasumathi.Sundaram@Sun.COM off_t off; 169*9089SVasumathi.Sundaram@Sun.COM size_t size; 170*9089SVasumathi.Sundaram@Sun.COM off_t nextp_off; 171*9089SVasumathi.Sundaram@Sun.COM } ip_list_walk_arg_t; 172*9089SVasumathi.Sundaram@Sun.COM 173*9089SVasumathi.Sundaram@Sun.COM static ip_list_walk_arg_t ipif_walk_arg = { 174*9089SVasumathi.Sundaram@Sun.COM OFFSETOF(ill_t, ill_ipif), 175*9089SVasumathi.Sundaram@Sun.COM sizeof (ipif_t), 176*9089SVasumathi.Sundaram@Sun.COM OFFSETOF(ipif_t, ipif_next) 177*9089SVasumathi.Sundaram@Sun.COM }; 178*9089SVasumathi.Sundaram@Sun.COM 179*9089SVasumathi.Sundaram@Sun.COM static ip_list_walk_arg_t srcid_walk_arg = { 180*9089SVasumathi.Sundaram@Sun.COM OFFSETOF(ip_stack_t, ips_srcid_head), 181*9089SVasumathi.Sundaram@Sun.COM sizeof (srcid_map_t), 182*9089SVasumathi.Sundaram@Sun.COM OFFSETOF(srcid_map_t, sm_next) 183*9089SVasumathi.Sundaram@Sun.COM }; 184*9089SVasumathi.Sundaram@Sun.COM 1850Sstevel@tonic-gate static int iphdr(uintptr_t, uint_t, int, const mdb_arg_t *); 1860Sstevel@tonic-gate static int ip6hdr(uintptr_t, uint_t, int, const mdb_arg_t *); 1870Sstevel@tonic-gate 188*9089SVasumathi.Sundaram@Sun.COM static int ill(uintptr_t, uint_t, int, const mdb_arg_t *); 189*9089SVasumathi.Sundaram@Sun.COM static void ill_help(void); 190*9089SVasumathi.Sundaram@Sun.COM static int ill_walk_init(mdb_walk_state_t *); 191*9089SVasumathi.Sundaram@Sun.COM static int ill_walk_step(mdb_walk_state_t *); 192*9089SVasumathi.Sundaram@Sun.COM static int ill_format(uintptr_t, const void *, void *); 193*9089SVasumathi.Sundaram@Sun.COM static void ill_header(boolean_t); 194*9089SVasumathi.Sundaram@Sun.COM 195*9089SVasumathi.Sundaram@Sun.COM static int ipif(uintptr_t, uint_t, int, const mdb_arg_t *); 196*9089SVasumathi.Sundaram@Sun.COM static void ipif_help(void); 197*9089SVasumathi.Sundaram@Sun.COM static int ipif_walk_init(mdb_walk_state_t *); 198*9089SVasumathi.Sundaram@Sun.COM static int ipif_walk_step(mdb_walk_state_t *); 199*9089SVasumathi.Sundaram@Sun.COM static int ipif_format(uintptr_t, const void *, void *); 200*9089SVasumathi.Sundaram@Sun.COM static void ipif_header(boolean_t); 201*9089SVasumathi.Sundaram@Sun.COM 202*9089SVasumathi.Sundaram@Sun.COM static int ip_list_walk_init(mdb_walk_state_t *); 203*9089SVasumathi.Sundaram@Sun.COM static int ip_list_walk_step(mdb_walk_state_t *); 204*9089SVasumathi.Sundaram@Sun.COM static void ip_list_walk_fini(mdb_walk_state_t *); 205*9089SVasumathi.Sundaram@Sun.COM static int srcid_walk_step(mdb_walk_state_t *); 206*9089SVasumathi.Sundaram@Sun.COM 2075940Ssowmini static int ire_format(uintptr_t addr, const void *, void *); 2085940Ssowmini static int nce_format(uintptr_t addr, const nce_t *nce, int ipversion); 2095940Ssowmini static int nce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv); 2105940Ssowmini static int nce_walk_step(mdb_walk_state_t *wsp); 2115940Ssowmini static int nce_stack_walk_init(mdb_walk_state_t *wsp); 2125940Ssowmini static int nce_stack_walk_step(mdb_walk_state_t *wsp); 2135940Ssowmini static void nce_stack_walk_fini(mdb_walk_state_t *wsp); 2145940Ssowmini static int nce_cb(uintptr_t addr, const nce_walk_data_t *iw, nce_cbdata_t *id); 2153448Sdh155122 216*9089SVasumathi.Sundaram@Sun.COM static int ipcl_hash_walk_init(mdb_walk_state_t *); 217*9089SVasumathi.Sundaram@Sun.COM static int ipcl_hash_walk_step(mdb_walk_state_t *); 218*9089SVasumathi.Sundaram@Sun.COM static void ipcl_hash_walk_fini(mdb_walk_state_t *); 219*9089SVasumathi.Sundaram@Sun.COM 220*9089SVasumathi.Sundaram@Sun.COM static int conn_status_walk_step(mdb_walk_state_t *); 221*9089SVasumathi.Sundaram@Sun.COM static int conn_status(uintptr_t, uint_t, int, const mdb_arg_t *); 222*9089SVasumathi.Sundaram@Sun.COM static void conn_status_help(void); 223*9089SVasumathi.Sundaram@Sun.COM 224*9089SVasumathi.Sundaram@Sun.COM static int srcid_status(uintptr_t, uint_t, int, const mdb_arg_t *); 225*9089SVasumathi.Sundaram@Sun.COM 2263448Sdh155122 /* 2273448Sdh155122 * Given the kernel address of an ip_stack_t, return the stackid 2283448Sdh155122 */ 2293448Sdh155122 static int 2303448Sdh155122 ips_to_stackid(uintptr_t kaddr) 2313448Sdh155122 { 2323448Sdh155122 ip_stack_t ipss; 2333448Sdh155122 netstack_t nss; 2343448Sdh155122 2353448Sdh155122 if (mdb_vread(&ipss, sizeof (ipss), kaddr) == -1) { 2363448Sdh155122 mdb_warn("failed to read ip_stack_t %p", kaddr); 2373448Sdh155122 return (0); 2383448Sdh155122 } 2393448Sdh155122 kaddr = (uintptr_t)ipss.ips_netstack; 2403448Sdh155122 if (mdb_vread(&nss, sizeof (nss), kaddr) == -1) { 2413448Sdh155122 mdb_warn("failed to read netstack_t %p", kaddr); 2423448Sdh155122 return (0); 2433448Sdh155122 } 2443448Sdh155122 return (nss.netstack_stackid); 2453448Sdh155122 } 2463448Sdh155122 2470Sstevel@tonic-gate int 2483448Sdh155122 ip_stacks_walk_init(mdb_walk_state_t *wsp) 2493448Sdh155122 { 2503448Sdh155122 if (mdb_layered_walk("netstack", wsp) == -1) { 2513448Sdh155122 mdb_warn("can't walk 'netstack'"); 2523448Sdh155122 return (WALK_ERR); 2533448Sdh155122 } 2543448Sdh155122 return (WALK_NEXT); 2553448Sdh155122 } 2563448Sdh155122 2573448Sdh155122 int 2583448Sdh155122 ip_stacks_walk_step(mdb_walk_state_t *wsp) 2593448Sdh155122 { 2603448Sdh155122 uintptr_t kaddr; 2613448Sdh155122 netstack_t nss; 2623448Sdh155122 2633448Sdh155122 if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) { 2643448Sdh155122 mdb_warn("can't read netstack at %p", wsp->walk_addr); 2653448Sdh155122 return (WALK_ERR); 2663448Sdh155122 } 2673448Sdh155122 kaddr = (uintptr_t)nss.netstack_modules[NS_IP]; 2683448Sdh155122 2693448Sdh155122 return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata)); 2703448Sdh155122 } 2713448Sdh155122 2725023Scarlsonj int 2735023Scarlsonj th_hash_walk_init(mdb_walk_state_t *wsp) 2745023Scarlsonj { 2755023Scarlsonj GElf_Sym sym; 2765023Scarlsonj list_node_t *next; 2775023Scarlsonj 2785023Scarlsonj if (wsp->walk_addr == NULL) { 2795023Scarlsonj if (mdb_lookup_by_obj("ip", "ip_thread_list", &sym) == 0) { 2805023Scarlsonj wsp->walk_addr = sym.st_value; 2815023Scarlsonj } else { 2825023Scarlsonj mdb_warn("unable to locate ip_thread_list\n"); 2835023Scarlsonj return (WALK_ERR); 2845023Scarlsonj } 2855023Scarlsonj } 2865023Scarlsonj 2875023Scarlsonj if (mdb_vread(&next, sizeof (next), 2885023Scarlsonj wsp->walk_addr + offsetof(list_t, list_head) + 2895023Scarlsonj offsetof(list_node_t, list_next)) == -1 || 2905023Scarlsonj next == NULL) { 2915023Scarlsonj mdb_warn("non-DEBUG image; cannot walk th_hash list\n"); 2925023Scarlsonj return (WALK_ERR); 2935023Scarlsonj } 2945023Scarlsonj 2955023Scarlsonj if (mdb_layered_walk("list", wsp) == -1) { 2965023Scarlsonj mdb_warn("can't walk 'list'"); 2975023Scarlsonj return (WALK_ERR); 2985023Scarlsonj } else { 2995023Scarlsonj return (WALK_NEXT); 3005023Scarlsonj } 3015023Scarlsonj } 3025023Scarlsonj 3035023Scarlsonj int 3045023Scarlsonj th_hash_walk_step(mdb_walk_state_t *wsp) 3055023Scarlsonj { 3065023Scarlsonj return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 3075023Scarlsonj wsp->walk_cbdata)); 3085023Scarlsonj } 3095023Scarlsonj 3103448Sdh155122 /* 3113448Sdh155122 * Called with walk_addr being the address of ips_ill_g_heads 3123448Sdh155122 */ 3133448Sdh155122 int 3143448Sdh155122 illif_stack_walk_init(mdb_walk_state_t *wsp) 3150Sstevel@tonic-gate { 3160Sstevel@tonic-gate illif_walk_data_t *iw; 3170Sstevel@tonic-gate 3183448Sdh155122 if (wsp->walk_addr == NULL) { 3193448Sdh155122 mdb_warn("illif_stack supports only local walks\n"); 3200Sstevel@tonic-gate return (WALK_ERR); 3210Sstevel@tonic-gate } 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate iw = mdb_alloc(sizeof (illif_walk_data_t), UM_SLEEP); 3240Sstevel@tonic-gate 3253448Sdh155122 if (mdb_vread(iw->ill_g_heads, MAX_G_HEADS * sizeof (ill_g_head_t), 3263448Sdh155122 wsp->walk_addr) == -1) { 3273448Sdh155122 mdb_warn("failed to read 'ips_ill_g_heads' at %p", 3283448Sdh155122 wsp->walk_addr); 3290Sstevel@tonic-gate mdb_free(iw, sizeof (illif_walk_data_t)); 3300Sstevel@tonic-gate return (WALK_ERR); 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate iw->ill_list = 0; 3343448Sdh155122 wsp->walk_addr = (uintptr_t)iw->ill_g_heads[0].ill_g_list_head; 3350Sstevel@tonic-gate wsp->walk_data = iw; 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate return (WALK_NEXT); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate int 3413448Sdh155122 illif_stack_walk_step(mdb_walk_state_t *wsp) 3420Sstevel@tonic-gate { 3430Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr; 3440Sstevel@tonic-gate illif_walk_data_t *iw = wsp->walk_data; 3450Sstevel@tonic-gate int list = iw->ill_list; 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate if (mdb_vread(&iw->ill_if, sizeof (ill_if_t), addr) == -1) { 3480Sstevel@tonic-gate mdb_warn("failed to read ill_if_t at %p", addr); 3490Sstevel@tonic-gate return (WALK_ERR); 3500Sstevel@tonic-gate } 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)iw->ill_if.illif_next; 3530Sstevel@tonic-gate 3543448Sdh155122 if (wsp->walk_addr == 3553448Sdh155122 (uintptr_t)iw->ill_g_heads[list].ill_g_list_head) { 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate if (++list >= MAX_G_HEADS) 3580Sstevel@tonic-gate return (WALK_DONE); 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate iw->ill_list = list; 3613448Sdh155122 wsp->walk_addr = 3623448Sdh155122 (uintptr_t)iw->ill_g_heads[list].ill_g_list_head; 3630Sstevel@tonic-gate return (WALK_NEXT); 3640Sstevel@tonic-gate } 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate return (wsp->walk_callback(addr, iw, wsp->walk_cbdata)); 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate void 3703448Sdh155122 illif_stack_walk_fini(mdb_walk_state_t *wsp) 3710Sstevel@tonic-gate { 3720Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (illif_walk_data_t)); 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate typedef struct illif_cbdata { 3760Sstevel@tonic-gate uint_t ill_flags; 3770Sstevel@tonic-gate uintptr_t ill_addr; 3780Sstevel@tonic-gate int ill_printlist; /* list to be printed (MAX_G_HEADS for all) */ 3790Sstevel@tonic-gate boolean_t ill_printed; 3800Sstevel@tonic-gate } illif_cbdata_t; 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate static int 3830Sstevel@tonic-gate illif_cb(uintptr_t addr, const illif_walk_data_t *iw, illif_cbdata_t *id) 3840Sstevel@tonic-gate { 3850Sstevel@tonic-gate const char *version; 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate if (id->ill_printlist < MAX_G_HEADS && 3880Sstevel@tonic-gate id->ill_printlist != iw->ill_list) 3890Sstevel@tonic-gate return (WALK_NEXT); 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate if (id->ill_flags & DCMD_ADDRSPEC && id->ill_addr != addr) 3920Sstevel@tonic-gate return (WALK_NEXT); 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate if (id->ill_flags & DCMD_PIPE_OUT) { 3950Sstevel@tonic-gate mdb_printf("%p\n", addr); 3960Sstevel@tonic-gate return (WALK_NEXT); 3970Sstevel@tonic-gate } 3980Sstevel@tonic-gate 3990Sstevel@tonic-gate switch (iw->ill_list) { 4000Sstevel@tonic-gate case IP_V4_G_HEAD: version = "v4"; break; 4010Sstevel@tonic-gate case IP_V6_G_HEAD: version = "v6"; break; 4020Sstevel@tonic-gate default: version = "??"; break; 4030Sstevel@tonic-gate } 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate mdb_printf("%?p %2s %?p %10d %?p %s\n", 4060Sstevel@tonic-gate addr, version, addr + offsetof(ill_if_t, illif_avl_by_ppa), 4070Sstevel@tonic-gate iw->ill_if.illif_avl_by_ppa.avl_numnodes, 4080Sstevel@tonic-gate iw->ill_if.illif_ppa_arena, iw->ill_if.illif_name); 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate id->ill_printed = TRUE; 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate return (WALK_NEXT); 4130Sstevel@tonic-gate } 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate int 4165940Ssowmini ip_stacks_common_walk_init(mdb_walk_state_t *wsp) 4173448Sdh155122 { 4183448Sdh155122 if (mdb_layered_walk("ip_stacks", wsp) == -1) { 4193448Sdh155122 mdb_warn("can't walk 'ip_stacks'"); 4203448Sdh155122 return (WALK_ERR); 4213448Sdh155122 } 4223448Sdh155122 4233448Sdh155122 return (WALK_NEXT); 4243448Sdh155122 } 4253448Sdh155122 4263448Sdh155122 int 4273448Sdh155122 illif_walk_step(mdb_walk_state_t *wsp) 4283448Sdh155122 { 4293448Sdh155122 uintptr_t kaddr; 4303448Sdh155122 4313448Sdh155122 kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ill_g_heads); 4323448Sdh155122 4333448Sdh155122 if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) { 4343448Sdh155122 mdb_warn("can't read ips_ip_cache_table at %p", kaddr); 4353448Sdh155122 return (WALK_ERR); 4363448Sdh155122 } 4373448Sdh155122 4383448Sdh155122 if (mdb_pwalk("illif_stack", wsp->walk_callback, 4395023Scarlsonj wsp->walk_cbdata, kaddr) == -1) { 4403448Sdh155122 mdb_warn("couldn't walk 'illif_stack' for ips_ill_g_heads %p", 4413448Sdh155122 kaddr); 4423448Sdh155122 return (WALK_ERR); 4433448Sdh155122 } 4443448Sdh155122 return (WALK_NEXT); 4453448Sdh155122 } 4463448Sdh155122 4473448Sdh155122 int 4480Sstevel@tonic-gate illif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 4490Sstevel@tonic-gate { 4500Sstevel@tonic-gate illif_cbdata_t id; 4510Sstevel@tonic-gate ill_if_t ill_if; 4520Sstevel@tonic-gate const char *opt_P = NULL; 4530Sstevel@tonic-gate int printlist = MAX_G_HEADS; 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate if (mdb_getopts(argc, argv, 4560Sstevel@tonic-gate 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 4570Sstevel@tonic-gate return (DCMD_USAGE); 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate if (opt_P != NULL) { 4600Sstevel@tonic-gate if (strcmp("v4", opt_P) == 0) { 4610Sstevel@tonic-gate printlist = IP_V4_G_HEAD; 4620Sstevel@tonic-gate } else if (strcmp("v6", opt_P) == 0) { 4630Sstevel@tonic-gate printlist = IP_V6_G_HEAD; 4640Sstevel@tonic-gate } else { 4650Sstevel@tonic-gate mdb_warn("invalid protocol '%s'\n", opt_P); 4660Sstevel@tonic-gate return (DCMD_USAGE); 4670Sstevel@tonic-gate } 4680Sstevel@tonic-gate } 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) { 4710Sstevel@tonic-gate mdb_printf("%<u>%?s %2s %?s %10s %?s %-10s%</u>\n", 4720Sstevel@tonic-gate "ADDR", "IP", "AVLADDR", "NUMNODES", "ARENA", "NAME"); 4730Sstevel@tonic-gate } 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate id.ill_flags = flags; 4760Sstevel@tonic-gate id.ill_addr = addr; 4770Sstevel@tonic-gate id.ill_printlist = printlist; 4780Sstevel@tonic-gate id.ill_printed = FALSE; 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate if (mdb_walk("illif", (mdb_walk_cb_t)illif_cb, &id) == -1) { 4810Sstevel@tonic-gate mdb_warn("can't walk ill_if_t structures"); 4820Sstevel@tonic-gate return (DCMD_ERR); 4830Sstevel@tonic-gate } 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || opt_P != NULL || id.ill_printed) 4860Sstevel@tonic-gate return (DCMD_OK); 4870Sstevel@tonic-gate 4880Sstevel@tonic-gate /* 4890Sstevel@tonic-gate * If an address is specified and the walk doesn't find it, 4900Sstevel@tonic-gate * print it anyway. 4910Sstevel@tonic-gate */ 4920Sstevel@tonic-gate if (mdb_vread(&ill_if, sizeof (ill_if_t), addr) == -1) { 4930Sstevel@tonic-gate mdb_warn("failed to read ill_if_t at %p", addr); 4940Sstevel@tonic-gate return (DCMD_ERR); 4950Sstevel@tonic-gate } 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate mdb_printf("%?p %2s %?p %10d %?p %s\n", 4980Sstevel@tonic-gate addr, "??", addr + offsetof(ill_if_t, illif_avl_by_ppa), 4990Sstevel@tonic-gate ill_if.illif_avl_by_ppa.avl_numnodes, 5000Sstevel@tonic-gate ill_if.illif_ppa_arena, ill_if.illif_name); 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate return (DCMD_OK); 5030Sstevel@tonic-gate } 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate static void 5060Sstevel@tonic-gate illif_help(void) 5070Sstevel@tonic-gate { 5080Sstevel@tonic-gate mdb_printf("Options:\n"); 5090Sstevel@tonic-gate mdb_printf("\t-P v4 | v6" 5100Sstevel@tonic-gate "\tfilter interface structures for the specified protocol\n"); 5110Sstevel@tonic-gate } 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate int 5140Sstevel@tonic-gate ire_walk_init(mdb_walk_state_t *wsp) 5150Sstevel@tonic-gate { 5160Sstevel@tonic-gate if (mdb_layered_walk("ire_cache", wsp) == -1) { 5170Sstevel@tonic-gate mdb_warn("can't walk 'ire_cache'"); 5180Sstevel@tonic-gate return (WALK_ERR); 5190Sstevel@tonic-gate } 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate return (WALK_NEXT); 5220Sstevel@tonic-gate } 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate int 5250Sstevel@tonic-gate ire_walk_step(mdb_walk_state_t *wsp) 5260Sstevel@tonic-gate { 5270Sstevel@tonic-gate ire_t ire; 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) { 5300Sstevel@tonic-gate mdb_warn("can't read ire at %p", wsp->walk_addr); 5310Sstevel@tonic-gate return (WALK_ERR); 5320Sstevel@tonic-gate } 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate return (wsp->walk_callback(wsp->walk_addr, &ire, wsp->walk_cbdata)); 5350Sstevel@tonic-gate } 5360Sstevel@tonic-gate 5373448Sdh155122 5383448Sdh155122 int 5393448Sdh155122 ire_ctable_walk_step(mdb_walk_state_t *wsp) 5403448Sdh155122 { 5413448Sdh155122 uintptr_t kaddr; 5423448Sdh155122 irb_t *irb; 5433448Sdh155122 uint32_t cache_table_size; 5443448Sdh155122 int i; 5455940Ssowmini ire_cbdata_t ire_cb; 5463448Sdh155122 5475940Ssowmini ire_cb.verbose = B_FALSE; 5485940Ssowmini ire_cb.ire_ipversion = 0; 5495940Ssowmini 5503448Sdh155122 5513448Sdh155122 kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ip_cache_table_size); 5523448Sdh155122 5533448Sdh155122 if (mdb_vread(&cache_table_size, sizeof (uint32_t), kaddr) == -1) { 5543448Sdh155122 mdb_warn("can't read ips_ip_cache_table at %p", kaddr); 5553448Sdh155122 return (WALK_ERR); 5563448Sdh155122 } 5573448Sdh155122 5583448Sdh155122 kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ip_cache_table); 5593448Sdh155122 if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) { 5603448Sdh155122 mdb_warn("can't read ips_ip_cache_table at %p", kaddr); 5613448Sdh155122 return (WALK_ERR); 5623448Sdh155122 } 5633448Sdh155122 5643448Sdh155122 irb = mdb_alloc(sizeof (irb_t) * cache_table_size, UM_SLEEP|UM_GC); 5653448Sdh155122 if (mdb_vread(irb, sizeof (irb_t) * cache_table_size, kaddr) == -1) { 5663448Sdh155122 mdb_warn("can't read irb at %p", kaddr); 5673448Sdh155122 return (WALK_ERR); 5683448Sdh155122 } 5693448Sdh155122 for (i = 0; i < cache_table_size; i++) { 5703448Sdh155122 kaddr = (uintptr_t)irb[i].irb_ire; 5713448Sdh155122 5725940Ssowmini if (mdb_pwalk("ire_next", ire_format, &ire_cb, 5735023Scarlsonj kaddr) == -1) { 5743448Sdh155122 mdb_warn("can't walk 'ire_next' for ire %p", kaddr); 5753448Sdh155122 return (WALK_ERR); 5763448Sdh155122 } 5773448Sdh155122 } 5783448Sdh155122 return (WALK_NEXT); 5793448Sdh155122 } 5803448Sdh155122 5813448Sdh155122 /* ARGSUSED */ 5823448Sdh155122 int 5833448Sdh155122 ire_next_walk_init(mdb_walk_state_t *wsp) 5843448Sdh155122 { 5853448Sdh155122 return (WALK_NEXT); 5863448Sdh155122 } 5873448Sdh155122 5883448Sdh155122 int 5893448Sdh155122 ire_next_walk_step(mdb_walk_state_t *wsp) 5903448Sdh155122 { 5913448Sdh155122 ire_t ire; 5923448Sdh155122 int status; 5933448Sdh155122 5943448Sdh155122 5953448Sdh155122 if (wsp->walk_addr == NULL) 5963448Sdh155122 return (WALK_DONE); 5973448Sdh155122 5983448Sdh155122 if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) { 5993448Sdh155122 mdb_warn("can't read ire at %p", wsp->walk_addr); 6003448Sdh155122 return (WALK_ERR); 6013448Sdh155122 } 6023448Sdh155122 status = wsp->walk_callback(wsp->walk_addr, &ire, 6033448Sdh155122 wsp->walk_cbdata); 6043448Sdh155122 6053448Sdh155122 if (status != WALK_NEXT) 6063448Sdh155122 return (status); 6073448Sdh155122 6083448Sdh155122 wsp->walk_addr = (uintptr_t)ire.ire_next; 6093448Sdh155122 return (status); 6103448Sdh155122 } 6113448Sdh155122 6120Sstevel@tonic-gate static int 6135940Ssowmini ire_format(uintptr_t addr, const void *ire_arg, void *ire_cb_arg) 6140Sstevel@tonic-gate { 6155940Ssowmini const ire_t *irep = ire_arg; 6165940Ssowmini ire_cbdata_t *ire_cb = ire_cb_arg; 6175940Ssowmini boolean_t verbose = ire_cb->verbose; 6185940Ssowmini 6190Sstevel@tonic-gate static const mdb_bitmask_t tmasks[] = { 6200Sstevel@tonic-gate { "BROADCAST", IRE_BROADCAST, IRE_BROADCAST }, 6210Sstevel@tonic-gate { "DEFAULT", IRE_DEFAULT, IRE_DEFAULT }, 6220Sstevel@tonic-gate { "LOCAL", IRE_LOCAL, IRE_LOCAL }, 6230Sstevel@tonic-gate { "LOOPBACK", IRE_LOOPBACK, IRE_LOOPBACK }, 6240Sstevel@tonic-gate { "PREFIX", IRE_PREFIX, IRE_PREFIX }, 6250Sstevel@tonic-gate { "CACHE", IRE_CACHE, IRE_CACHE }, 6260Sstevel@tonic-gate { "IF_NORESOLVER", IRE_IF_NORESOLVER, IRE_IF_NORESOLVER }, 6270Sstevel@tonic-gate { "IF_RESOLVER", IRE_IF_RESOLVER, IRE_IF_RESOLVER }, 6280Sstevel@tonic-gate { "HOST", IRE_HOST, IRE_HOST }, 6290Sstevel@tonic-gate { "HOST_REDIRECT", IRE_HOST_REDIRECT, IRE_HOST_REDIRECT }, 6300Sstevel@tonic-gate { NULL, 0, 0 } 6310Sstevel@tonic-gate }; 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate static const mdb_bitmask_t mmasks[] = { 6340Sstevel@tonic-gate { "CONDEMNED", IRE_MARK_CONDEMNED, IRE_MARK_CONDEMNED }, 635*9089SVasumathi.Sundaram@Sun.COM { "TESTHIDDEN", IRE_MARK_TESTHIDDEN, IRE_MARK_TESTHIDDEN }, 6360Sstevel@tonic-gate { "NOADD", IRE_MARK_NOADD, IRE_MARK_NOADD }, 6370Sstevel@tonic-gate { "TEMPORARY", IRE_MARK_TEMPORARY, IRE_MARK_TEMPORARY }, 6385940Ssowmini { "USESRC", IRE_MARK_USESRC_CHECK, IRE_MARK_USESRC_CHECK }, 6395940Ssowmini { "PRIVATE", IRE_MARK_PRIVATE_ADDR, IRE_MARK_PRIVATE_ADDR }, 6405940Ssowmini { "UNCACHED", IRE_MARK_UNCACHED, IRE_MARK_UNCACHED }, 6410Sstevel@tonic-gate { NULL, 0, 0 } 6420Sstevel@tonic-gate }; 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate static const mdb_bitmask_t fmasks[] = { 6450Sstevel@tonic-gate { "UP", RTF_UP, RTF_UP }, 6460Sstevel@tonic-gate { "GATEWAY", RTF_GATEWAY, RTF_GATEWAY }, 6470Sstevel@tonic-gate { "HOST", RTF_HOST, RTF_HOST }, 6480Sstevel@tonic-gate { "REJECT", RTF_REJECT, RTF_REJECT }, 6490Sstevel@tonic-gate { "DYNAMIC", RTF_DYNAMIC, RTF_DYNAMIC }, 6500Sstevel@tonic-gate { "MODIFIED", RTF_MODIFIED, RTF_MODIFIED }, 6510Sstevel@tonic-gate { "DONE", RTF_DONE, RTF_DONE }, 6520Sstevel@tonic-gate { "MASK", RTF_MASK, RTF_MASK }, 6530Sstevel@tonic-gate { "CLONING", RTF_CLONING, RTF_CLONING }, 6540Sstevel@tonic-gate { "XRESOLVE", RTF_XRESOLVE, RTF_XRESOLVE }, 6550Sstevel@tonic-gate { "LLINFO", RTF_LLINFO, RTF_LLINFO }, 6560Sstevel@tonic-gate { "STATIC", RTF_STATIC, RTF_STATIC }, 6570Sstevel@tonic-gate { "BLACKHOLE", RTF_BLACKHOLE, RTF_BLACKHOLE }, 6580Sstevel@tonic-gate { "PRIVATE", RTF_PRIVATE, RTF_PRIVATE }, 6590Sstevel@tonic-gate { "PROTO2", RTF_PROTO2, RTF_PROTO2 }, 6600Sstevel@tonic-gate { "PROTO1", RTF_PROTO1, RTF_PROTO1 }, 6610Sstevel@tonic-gate { "MULTIRT", RTF_MULTIRT, RTF_MULTIRT }, 6620Sstevel@tonic-gate { "SETSRC", RTF_SETSRC, RTF_SETSRC }, 6630Sstevel@tonic-gate { NULL, 0, 0 } 6640Sstevel@tonic-gate }; 6650Sstevel@tonic-gate 6665940Ssowmini if (ire_cb->ire_ipversion != 0 && 6675940Ssowmini irep->ire_ipversion != ire_cb->ire_ipversion) 6685940Ssowmini return (WALK_NEXT); 6695940Ssowmini 6705940Ssowmini if (irep->ire_ipversion == IPV6_VERSION && verbose) { 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate mdb_printf("%<b>%?p%</b> %40N <%hb>\n" 6730Sstevel@tonic-gate "%?s %40N <%hb>\n" 6743448Sdh155122 "%?s %40d %4d <%hb>\n", 6750Sstevel@tonic-gate addr, &irep->ire_src_addr_v6, irep->ire_type, tmasks, 6760Sstevel@tonic-gate "", &irep->ire_addr_v6, (ushort_t)irep->ire_marks, mmasks, 6773448Sdh155122 "", ips_to_stackid((uintptr_t)irep->ire_ipst), 6783448Sdh155122 irep->ire_zoneid, 6793448Sdh155122 irep->ire_flags, fmasks); 6800Sstevel@tonic-gate 6815940Ssowmini } else if (irep->ire_ipversion == IPV6_VERSION) { 6820Sstevel@tonic-gate 6833448Sdh155122 mdb_printf("%?p %30N %30N %5d %4d\n", 6843448Sdh155122 addr, &irep->ire_src_addr_v6, 6853448Sdh155122 &irep->ire_addr_v6, 6863448Sdh155122 ips_to_stackid((uintptr_t)irep->ire_ipst), 6873448Sdh155122 irep->ire_zoneid); 6880Sstevel@tonic-gate 6895940Ssowmini } else if (verbose) { 6900Sstevel@tonic-gate 6910Sstevel@tonic-gate mdb_printf("%<b>%?p%</b> %40I <%hb>\n" 6920Sstevel@tonic-gate "%?s %40I <%hb>\n" 6935940Ssowmini "%?s %40d %4d <%hb>\n", 6940Sstevel@tonic-gate addr, irep->ire_src_addr, irep->ire_type, tmasks, 6950Sstevel@tonic-gate "", irep->ire_addr, (ushort_t)irep->ire_marks, mmasks, 6963448Sdh155122 "", ips_to_stackid((uintptr_t)irep->ire_ipst), 6973448Sdh155122 irep->ire_zoneid, irep->ire_flags, fmasks); 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate } else { 7000Sstevel@tonic-gate 7013448Sdh155122 mdb_printf("%?p %30I %30I %5d %4d\n", addr, irep->ire_src_addr, 7023448Sdh155122 irep->ire_addr, ips_to_stackid((uintptr_t)irep->ire_ipst), 7033448Sdh155122 irep->ire_zoneid); 7040Sstevel@tonic-gate } 7050Sstevel@tonic-gate 7060Sstevel@tonic-gate return (WALK_NEXT); 7070Sstevel@tonic-gate } 7080Sstevel@tonic-gate 7090Sstevel@tonic-gate /* 7100Sstevel@tonic-gate * There are faster ways to do this. Given the interactive nature of this 7110Sstevel@tonic-gate * use I don't think its worth much effort. 7120Sstevel@tonic-gate */ 7130Sstevel@tonic-gate static unsigned short 7140Sstevel@tonic-gate ipcksum(void *p, int len) 7150Sstevel@tonic-gate { 7160Sstevel@tonic-gate int32_t sum = 0; 7170Sstevel@tonic-gate 7180Sstevel@tonic-gate while (len > 1) { 7190Sstevel@tonic-gate /* alignment */ 7200Sstevel@tonic-gate sum += *(uint16_t *)p; 7210Sstevel@tonic-gate p = (char *)p + sizeof (uint16_t); 7220Sstevel@tonic-gate if (sum & 0x80000000) 7230Sstevel@tonic-gate sum = (sum & 0xFFFF) + (sum >> 16); 7240Sstevel@tonic-gate len -= 2; 7250Sstevel@tonic-gate } 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate if (len) 7280Sstevel@tonic-gate sum += (uint16_t)*(unsigned char *)p; 7290Sstevel@tonic-gate 7300Sstevel@tonic-gate while (sum >> 16) 7310Sstevel@tonic-gate sum = (sum & 0xFFFF) + (sum >> 16); 7320Sstevel@tonic-gate 7330Sstevel@tonic-gate return (~sum); 7340Sstevel@tonic-gate } 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate static const mdb_bitmask_t tcp_flags[] = { 7370Sstevel@tonic-gate { "SYN", TH_SYN, TH_SYN }, 7380Sstevel@tonic-gate { "ACK", TH_ACK, TH_ACK }, 7390Sstevel@tonic-gate { "FIN", TH_FIN, TH_FIN }, 7400Sstevel@tonic-gate { "RST", TH_RST, TH_RST }, 7410Sstevel@tonic-gate { "PSH", TH_PUSH, TH_PUSH }, 7420Sstevel@tonic-gate { "ECE", TH_ECE, TH_ECE }, 7430Sstevel@tonic-gate { "CWR", TH_CWR, TH_CWR }, 7440Sstevel@tonic-gate { NULL, 0, 0 } 7450Sstevel@tonic-gate }; 7460Sstevel@tonic-gate 7470Sstevel@tonic-gate static void 7480Sstevel@tonic-gate tcphdr_print(struct tcphdr *tcph) 7490Sstevel@tonic-gate { 7500Sstevel@tonic-gate in_port_t sport, dport; 7510Sstevel@tonic-gate tcp_seq seq, ack; 7520Sstevel@tonic-gate uint16_t win, urp; 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate mdb_printf("%<b>TCP header%</b>\n"); 7550Sstevel@tonic-gate 7560Sstevel@tonic-gate mdb_nhconvert(&sport, &tcph->th_sport, sizeof (sport)); 7570Sstevel@tonic-gate mdb_nhconvert(&dport, &tcph->th_dport, sizeof (dport)); 7580Sstevel@tonic-gate mdb_nhconvert(&seq, &tcph->th_seq, sizeof (seq)); 7590Sstevel@tonic-gate mdb_nhconvert(&ack, &tcph->th_ack, sizeof (ack)); 7600Sstevel@tonic-gate mdb_nhconvert(&win, &tcph->th_win, sizeof (win)); 7610Sstevel@tonic-gate mdb_nhconvert(&urp, &tcph->th_urp, sizeof (urp)); 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate mdb_printf("%<u>%6s %6s %10s %10s %4s %5s %5s %5s %-15s%</u>\n", 7640Sstevel@tonic-gate "SPORT", "DPORT", "SEQ", "ACK", "HLEN", "WIN", "CSUM", "URP", 7650Sstevel@tonic-gate "FLAGS"); 7660Sstevel@tonic-gate mdb_printf("%6hu %6hu %10u %10u %4d %5hu %5hu %5hu <%b>\n", 7670Sstevel@tonic-gate sport, dport, seq, ack, tcph->th_off << 2, win, 7680Sstevel@tonic-gate tcph->th_sum, urp, tcph->th_flags, tcp_flags); 7690Sstevel@tonic-gate mdb_printf("0x%04x 0x%04x 0x%08x 0x%08x\n\n", 7700Sstevel@tonic-gate sport, dport, seq, ack); 7710Sstevel@tonic-gate } 7720Sstevel@tonic-gate 7730Sstevel@tonic-gate /* ARGSUSED */ 7740Sstevel@tonic-gate static int 7750Sstevel@tonic-gate tcphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 7760Sstevel@tonic-gate { 7770Sstevel@tonic-gate struct tcphdr tcph; 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 7800Sstevel@tonic-gate return (DCMD_USAGE); 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) { 7830Sstevel@tonic-gate mdb_warn("failed to read TCP header at %p", addr); 7840Sstevel@tonic-gate return (DCMD_ERR); 7850Sstevel@tonic-gate } 7860Sstevel@tonic-gate tcphdr_print(&tcph); 7870Sstevel@tonic-gate return (DCMD_OK); 7880Sstevel@tonic-gate } 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate static void 7910Sstevel@tonic-gate udphdr_print(struct udphdr *udph) 7920Sstevel@tonic-gate { 7930Sstevel@tonic-gate in_port_t sport, dport; 7940Sstevel@tonic-gate uint16_t hlen; 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate mdb_printf("%<b>UDP header%</b>\n"); 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate mdb_nhconvert(&sport, &udph->uh_sport, sizeof (sport)); 7990Sstevel@tonic-gate mdb_nhconvert(&dport, &udph->uh_dport, sizeof (dport)); 8000Sstevel@tonic-gate mdb_nhconvert(&hlen, &udph->uh_ulen, sizeof (hlen)); 8010Sstevel@tonic-gate 8020Sstevel@tonic-gate mdb_printf("%<u>%14s %14s %5s %6s%</u>\n", 8030Sstevel@tonic-gate "SPORT", "DPORT", "LEN", "CSUM"); 8040Sstevel@tonic-gate mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %5hu 0x%04hx\n\n", sport, sport, 8050Sstevel@tonic-gate dport, dport, hlen, udph->uh_sum); 8060Sstevel@tonic-gate } 8070Sstevel@tonic-gate 8080Sstevel@tonic-gate /* ARGSUSED */ 8090Sstevel@tonic-gate static int 8100Sstevel@tonic-gate udphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 8110Sstevel@tonic-gate { 8120Sstevel@tonic-gate struct udphdr udph; 8130Sstevel@tonic-gate 8140Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 8150Sstevel@tonic-gate return (DCMD_USAGE); 8160Sstevel@tonic-gate 8170Sstevel@tonic-gate if (mdb_vread(&udph, sizeof (udph), addr) == -1) { 8180Sstevel@tonic-gate mdb_warn("failed to read UDP header at %p", addr); 8190Sstevel@tonic-gate return (DCMD_ERR); 8200Sstevel@tonic-gate } 8210Sstevel@tonic-gate udphdr_print(&udph); 8220Sstevel@tonic-gate return (DCMD_OK); 8230Sstevel@tonic-gate } 8240Sstevel@tonic-gate 8250Sstevel@tonic-gate static void 8260Sstevel@tonic-gate sctphdr_print(sctp_hdr_t *sctph) 8270Sstevel@tonic-gate { 8280Sstevel@tonic-gate in_port_t sport, dport; 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate mdb_printf("%<b>SCTP header%</b>\n"); 8310Sstevel@tonic-gate mdb_nhconvert(&sport, &sctph->sh_sport, sizeof (sport)); 8320Sstevel@tonic-gate mdb_nhconvert(&dport, &sctph->sh_dport, sizeof (dport)); 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate mdb_printf("%<u>%14s %14s %10s %10s%</u>\n", 8350Sstevel@tonic-gate "SPORT", "DPORT", "VTAG", "CHKSUM"); 8360Sstevel@tonic-gate mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %10u 0x%08x\n\n", sport, sport, 8370Sstevel@tonic-gate dport, dport, sctph->sh_verf, sctph->sh_chksum); 8380Sstevel@tonic-gate } 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate /* ARGSUSED */ 8410Sstevel@tonic-gate static int 8420Sstevel@tonic-gate sctphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 8430Sstevel@tonic-gate { 8440Sstevel@tonic-gate sctp_hdr_t sctph; 8450Sstevel@tonic-gate 8460Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 8470Sstevel@tonic-gate return (DCMD_USAGE); 8480Sstevel@tonic-gate 8490Sstevel@tonic-gate if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) { 8500Sstevel@tonic-gate mdb_warn("failed to read SCTP header at %p", addr); 8510Sstevel@tonic-gate return (DCMD_ERR); 8520Sstevel@tonic-gate } 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate sctphdr_print(&sctph); 8550Sstevel@tonic-gate return (DCMD_OK); 8560Sstevel@tonic-gate } 8570Sstevel@tonic-gate 8580Sstevel@tonic-gate static int 8590Sstevel@tonic-gate transport_hdr(int proto, uintptr_t addr) 8600Sstevel@tonic-gate { 8610Sstevel@tonic-gate mdb_printf("\n"); 8620Sstevel@tonic-gate switch (proto) { 8630Sstevel@tonic-gate case IPPROTO_TCP: { 8640Sstevel@tonic-gate struct tcphdr tcph; 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) { 8670Sstevel@tonic-gate mdb_warn("failed to read TCP header at %p", addr); 8680Sstevel@tonic-gate return (DCMD_ERR); 8690Sstevel@tonic-gate } 8700Sstevel@tonic-gate tcphdr_print(&tcph); 8710Sstevel@tonic-gate break; 8720Sstevel@tonic-gate } 8730Sstevel@tonic-gate case IPPROTO_UDP: { 8740Sstevel@tonic-gate struct udphdr udph; 8750Sstevel@tonic-gate 8760Sstevel@tonic-gate if (mdb_vread(&udph, sizeof (udph), addr) == -1) { 8770Sstevel@tonic-gate mdb_warn("failed to read UDP header at %p", addr); 8780Sstevel@tonic-gate return (DCMD_ERR); 8790Sstevel@tonic-gate } 8800Sstevel@tonic-gate udphdr_print(&udph); 8810Sstevel@tonic-gate break; 8820Sstevel@tonic-gate } 8830Sstevel@tonic-gate case IPPROTO_SCTP: { 8840Sstevel@tonic-gate sctp_hdr_t sctph; 8850Sstevel@tonic-gate 8860Sstevel@tonic-gate if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) { 8870Sstevel@tonic-gate mdb_warn("failed to read SCTP header at %p", addr); 8880Sstevel@tonic-gate return (DCMD_ERR); 8890Sstevel@tonic-gate } 8900Sstevel@tonic-gate sctphdr_print(&sctph); 8910Sstevel@tonic-gate break; 8920Sstevel@tonic-gate } 8930Sstevel@tonic-gate default: 8940Sstevel@tonic-gate break; 8950Sstevel@tonic-gate } 8960Sstevel@tonic-gate 8970Sstevel@tonic-gate return (DCMD_OK); 8980Sstevel@tonic-gate } 8990Sstevel@tonic-gate 9000Sstevel@tonic-gate static const mdb_bitmask_t ip_flags[] = { 9010Sstevel@tonic-gate { "DF", IPH_DF, IPH_DF }, 9020Sstevel@tonic-gate { "MF", IPH_MF, IPH_MF }, 9030Sstevel@tonic-gate { NULL, 0, 0 } 9040Sstevel@tonic-gate }; 9050Sstevel@tonic-gate 9060Sstevel@tonic-gate /* ARGSUSED */ 9070Sstevel@tonic-gate static int 9080Sstevel@tonic-gate iphdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 9090Sstevel@tonic-gate { 9100Sstevel@tonic-gate uint_t verbose = FALSE, force = FALSE; 9110Sstevel@tonic-gate ipha_t iph[1]; 9120Sstevel@tonic-gate uint16_t ver, totlen, hdrlen, ipid, off, csum; 9130Sstevel@tonic-gate uintptr_t nxt_proto; 9140Sstevel@tonic-gate char exp_csum[8]; 9150Sstevel@tonic-gate 9160Sstevel@tonic-gate if (mdb_getopts(argc, argv, 9170Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose, 9180Sstevel@tonic-gate 'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc) 9190Sstevel@tonic-gate return (DCMD_USAGE); 9200Sstevel@tonic-gate 9210Sstevel@tonic-gate if (mdb_vread(iph, sizeof (*iph), addr) == -1) { 9220Sstevel@tonic-gate mdb_warn("failed to read IPv4 header at %p", addr); 9230Sstevel@tonic-gate return (DCMD_ERR); 9240Sstevel@tonic-gate } 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate ver = (iph->ipha_version_and_hdr_length & 0xf0) >> 4; 9270Sstevel@tonic-gate if (ver != IPV4_VERSION) { 9280Sstevel@tonic-gate if (ver == IPV6_VERSION) { 9290Sstevel@tonic-gate return (ip6hdr(addr, flags, argc, argv)); 9300Sstevel@tonic-gate } else if (!force) { 9310Sstevel@tonic-gate mdb_warn("unknown IP version: %d\n", ver); 9320Sstevel@tonic-gate return (DCMD_ERR); 9330Sstevel@tonic-gate } 9340Sstevel@tonic-gate } 9350Sstevel@tonic-gate 9360Sstevel@tonic-gate mdb_printf("%<b>IPv4 header%</b>\n"); 9370Sstevel@tonic-gate mdb_printf("%-34s %-34s\n" 9380Sstevel@tonic-gate "%<u>%-4s %-4s %-5s %-5s %-6s %-5s %-5s %-6s %-8s %-6s%</u>\n", 9390Sstevel@tonic-gate "SRC", "DST", 9400Sstevel@tonic-gate "HLEN", "TOS", "LEN", "ID", "OFFSET", "TTL", "PROTO", "CHKSUM", 9410Sstevel@tonic-gate "EXP-CSUM", "FLGS"); 9420Sstevel@tonic-gate 9430Sstevel@tonic-gate hdrlen = (iph->ipha_version_and_hdr_length & 0x0f) << 2; 9440Sstevel@tonic-gate mdb_nhconvert(&totlen, &iph->ipha_length, sizeof (totlen)); 9450Sstevel@tonic-gate mdb_nhconvert(&ipid, &iph->ipha_ident, sizeof (ipid)); 9460Sstevel@tonic-gate mdb_nhconvert(&off, &iph->ipha_fragment_offset_and_flags, sizeof (off)); 9470Sstevel@tonic-gate if (hdrlen == IP_SIMPLE_HDR_LENGTH) { 9480Sstevel@tonic-gate if ((csum = ipcksum(iph, sizeof (*iph))) != 0) 9490Sstevel@tonic-gate csum = ~(~csum + ~iph->ipha_hdr_checksum); 9500Sstevel@tonic-gate else 9510Sstevel@tonic-gate csum = iph->ipha_hdr_checksum; 9520Sstevel@tonic-gate mdb_snprintf(exp_csum, 8, "%u", csum); 9530Sstevel@tonic-gate } else { 9540Sstevel@tonic-gate mdb_snprintf(exp_csum, 8, "<n/a>"); 9550Sstevel@tonic-gate } 9560Sstevel@tonic-gate 9570Sstevel@tonic-gate mdb_printf("%-34I %-34I%\n" 9580Sstevel@tonic-gate "%-4d %-4d %-5hu %-5hu %-6hu %-5hu %-5hu %-6u %-8s <%5hb>\n", 9590Sstevel@tonic-gate iph->ipha_src, iph->ipha_dst, 9600Sstevel@tonic-gate hdrlen, iph->ipha_type_of_service, totlen, ipid, 9610Sstevel@tonic-gate (off << 3) & 0xffff, iph->ipha_ttl, iph->ipha_protocol, 9620Sstevel@tonic-gate iph->ipha_hdr_checksum, exp_csum, off, ip_flags); 9630Sstevel@tonic-gate 9640Sstevel@tonic-gate if (verbose) { 9650Sstevel@tonic-gate nxt_proto = addr + hdrlen; 9660Sstevel@tonic-gate return (transport_hdr(iph->ipha_protocol, nxt_proto)); 9670Sstevel@tonic-gate } else { 9680Sstevel@tonic-gate return (DCMD_OK); 9690Sstevel@tonic-gate } 9700Sstevel@tonic-gate } 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate /* ARGSUSED */ 9730Sstevel@tonic-gate static int 9740Sstevel@tonic-gate ip6hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 9750Sstevel@tonic-gate { 9760Sstevel@tonic-gate uint_t verbose = FALSE, force = FALSE; 9770Sstevel@tonic-gate ip6_t iph[1]; 9780Sstevel@tonic-gate int ver, class, flow; 9790Sstevel@tonic-gate uint16_t plen; 9800Sstevel@tonic-gate uintptr_t nxt_proto; 9810Sstevel@tonic-gate 9820Sstevel@tonic-gate if (mdb_getopts(argc, argv, 9830Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose, 9840Sstevel@tonic-gate 'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc) 9850Sstevel@tonic-gate return (DCMD_USAGE); 9860Sstevel@tonic-gate 9870Sstevel@tonic-gate if (mdb_vread(iph, sizeof (*iph), addr) == -1) { 9880Sstevel@tonic-gate mdb_warn("failed to read IPv6 header at %p", addr); 9890Sstevel@tonic-gate return (DCMD_ERR); 9900Sstevel@tonic-gate } 9910Sstevel@tonic-gate 9920Sstevel@tonic-gate ver = (iph->ip6_vfc & 0xf0) >> 4; 9930Sstevel@tonic-gate if (ver != IPV6_VERSION) { 9940Sstevel@tonic-gate if (ver == IPV4_VERSION) { 9950Sstevel@tonic-gate return (iphdr(addr, flags, argc, argv)); 9960Sstevel@tonic-gate } else if (!force) { 9970Sstevel@tonic-gate mdb_warn("unknown IP version: %d\n", ver); 9980Sstevel@tonic-gate return (DCMD_ERR); 9990Sstevel@tonic-gate } 10000Sstevel@tonic-gate } 10010Sstevel@tonic-gate 10020Sstevel@tonic-gate mdb_printf("%<b>IPv6 header%</b>\n"); 10030Sstevel@tonic-gate mdb_printf("%<u>%-26s %-26s %4s %7s %5s %3s %3s%</u>\n", 10040Sstevel@tonic-gate "SRC", "DST", "TCLS", "FLOW-ID", "PLEN", "NXT", "HOP"); 10050Sstevel@tonic-gate 10060Sstevel@tonic-gate class = (iph->ip6_vcf & IPV6_FLOWINFO_TCLASS) >> 20; 10070Sstevel@tonic-gate mdb_nhconvert(&class, &class, sizeof (class)); 10080Sstevel@tonic-gate flow = iph->ip6_vcf & IPV6_FLOWINFO_FLOWLABEL; 10090Sstevel@tonic-gate mdb_nhconvert(&flow, &flow, sizeof (flow)); 10100Sstevel@tonic-gate mdb_nhconvert(&plen, &iph->ip6_plen, sizeof (plen)); 10110Sstevel@tonic-gate 10120Sstevel@tonic-gate mdb_printf("%-26N %-26N %4d %7d %5hu %3d %3d\n", 10130Sstevel@tonic-gate &iph->ip6_src, &iph->ip6_dst, 10140Sstevel@tonic-gate class, flow, plen, iph->ip6_nxt, iph->ip6_hlim); 10150Sstevel@tonic-gate 10160Sstevel@tonic-gate if (verbose) { 10170Sstevel@tonic-gate nxt_proto = addr + sizeof (ip6_t); 10180Sstevel@tonic-gate return (transport_hdr(iph->ip6_nxt, nxt_proto)); 10190Sstevel@tonic-gate } else { 10200Sstevel@tonic-gate return (DCMD_OK); 10210Sstevel@tonic-gate } 10220Sstevel@tonic-gate } 10230Sstevel@tonic-gate 10240Sstevel@tonic-gate int 10250Sstevel@tonic-gate ire(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 10260Sstevel@tonic-gate { 10270Sstevel@tonic-gate uint_t verbose = FALSE; 10280Sstevel@tonic-gate ire_t ire; 10295940Ssowmini ire_cbdata_t ire_cb; 10305940Ssowmini int ipversion = 0; 10315940Ssowmini const char *opt_P = NULL; 10320Sstevel@tonic-gate 10330Sstevel@tonic-gate if (mdb_getopts(argc, argv, 10345940Ssowmini 'v', MDB_OPT_SETBITS, TRUE, &verbose, 10355940Ssowmini 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 10360Sstevel@tonic-gate return (DCMD_USAGE); 10370Sstevel@tonic-gate 10385940Ssowmini if (opt_P != NULL) { 10395940Ssowmini if (strcmp("v4", opt_P) == 0) { 10405940Ssowmini ipversion = IPV4_VERSION; 10415940Ssowmini } else if (strcmp("v6", opt_P) == 0) { 10425940Ssowmini ipversion = IPV6_VERSION; 10435940Ssowmini } else { 10445940Ssowmini mdb_warn("invalid protocol '%s'\n", opt_P); 10455940Ssowmini return (DCMD_USAGE); 10465940Ssowmini } 10475940Ssowmini } 10485940Ssowmini 10490Sstevel@tonic-gate if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 10500Sstevel@tonic-gate 10510Sstevel@tonic-gate if (verbose) { 10520Sstevel@tonic-gate mdb_printf("%?s %40s %-20s%\n" 10530Sstevel@tonic-gate "%?s %40s %-20s%\n" 10543448Sdh155122 "%<u>%?s %40s %4s %-20s%</u>\n", 10550Sstevel@tonic-gate "ADDR", "SRC", "TYPE", 10560Sstevel@tonic-gate "", "DST", "MARKS", 10573448Sdh155122 "", "STACK", "ZONE", "FLAGS"); 10580Sstevel@tonic-gate } else { 10593448Sdh155122 mdb_printf("%<u>%?s %30s %30s %5s %4s%</u>\n", 10603448Sdh155122 "ADDR", "SRC", "DST", "STACK", "ZONE"); 10610Sstevel@tonic-gate } 10620Sstevel@tonic-gate } 10630Sstevel@tonic-gate 10645940Ssowmini ire_cb.verbose = (verbose == TRUE); 10655940Ssowmini ire_cb.ire_ipversion = ipversion; 10665940Ssowmini 10670Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC) { 10680Sstevel@tonic-gate (void) mdb_vread(&ire, sizeof (ire_t), addr); 10695940Ssowmini (void) ire_format(addr, &ire, &ire_cb); 10705940Ssowmini } else if (mdb_walk("ire", (mdb_walk_cb_t)ire_format, &ire_cb) == -1) { 10710Sstevel@tonic-gate mdb_warn("failed to walk ire table"); 10720Sstevel@tonic-gate return (DCMD_ERR); 10730Sstevel@tonic-gate } 10740Sstevel@tonic-gate 10750Sstevel@tonic-gate return (DCMD_OK); 10760Sstevel@tonic-gate } 10770Sstevel@tonic-gate 10780Sstevel@tonic-gate static size_t 10790Sstevel@tonic-gate mi_osize(const queue_t *q) 10800Sstevel@tonic-gate { 10810Sstevel@tonic-gate /* 10820Sstevel@tonic-gate * The code in common/inet/mi.c allocates an extra word to store the 10830Sstevel@tonic-gate * size of the allocation. An mi_o_s is thus a size_t plus an mi_o_s. 10840Sstevel@tonic-gate */ 10850Sstevel@tonic-gate struct mi_block { 10860Sstevel@tonic-gate size_t mi_nbytes; 10870Sstevel@tonic-gate struct mi_o_s mi_o; 10880Sstevel@tonic-gate } m; 10890Sstevel@tonic-gate 10900Sstevel@tonic-gate if (mdb_vread(&m, sizeof (m), (uintptr_t)q->q_ptr - 10910Sstevel@tonic-gate sizeof (m)) == sizeof (m)) 10920Sstevel@tonic-gate return (m.mi_nbytes - sizeof (m)); 10930Sstevel@tonic-gate 10940Sstevel@tonic-gate return (0); 10950Sstevel@tonic-gate } 10960Sstevel@tonic-gate 10970Sstevel@tonic-gate static void 10980Sstevel@tonic-gate ip_ill_qinfo(const queue_t *q, char *buf, size_t nbytes) 10990Sstevel@tonic-gate { 11000Sstevel@tonic-gate char name[32]; 11010Sstevel@tonic-gate ill_t ill; 11020Sstevel@tonic-gate 11030Sstevel@tonic-gate if (mdb_vread(&ill, sizeof (ill), 11040Sstevel@tonic-gate (uintptr_t)q->q_ptr) == sizeof (ill) && 11050Sstevel@tonic-gate mdb_readstr(name, sizeof (name), (uintptr_t)ill.ill_name) > 0) 11060Sstevel@tonic-gate (void) mdb_snprintf(buf, nbytes, "if: %s", name); 11070Sstevel@tonic-gate } 11080Sstevel@tonic-gate 11090Sstevel@tonic-gate void 11100Sstevel@tonic-gate ip_qinfo(const queue_t *q, char *buf, size_t nbytes) 11110Sstevel@tonic-gate { 11120Sstevel@tonic-gate size_t size = mi_osize(q); 11130Sstevel@tonic-gate 11140Sstevel@tonic-gate if (size == sizeof (ill_t)) 11150Sstevel@tonic-gate ip_ill_qinfo(q, buf, nbytes); 11160Sstevel@tonic-gate } 11170Sstevel@tonic-gate 11180Sstevel@tonic-gate uintptr_t 11190Sstevel@tonic-gate ip_rnext(const queue_t *q) 11200Sstevel@tonic-gate { 11210Sstevel@tonic-gate size_t size = mi_osize(q); 11220Sstevel@tonic-gate ill_t ill; 11230Sstevel@tonic-gate 11240Sstevel@tonic-gate if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill), 11250Sstevel@tonic-gate (uintptr_t)q->q_ptr) == sizeof (ill)) 11260Sstevel@tonic-gate return ((uintptr_t)ill.ill_rq); 11270Sstevel@tonic-gate 11280Sstevel@tonic-gate return (NULL); 11290Sstevel@tonic-gate } 11300Sstevel@tonic-gate 11310Sstevel@tonic-gate uintptr_t 11320Sstevel@tonic-gate ip_wnext(const queue_t *q) 11330Sstevel@tonic-gate { 11340Sstevel@tonic-gate size_t size = mi_osize(q); 11350Sstevel@tonic-gate ill_t ill; 11360Sstevel@tonic-gate 11370Sstevel@tonic-gate if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill), 11380Sstevel@tonic-gate (uintptr_t)q->q_ptr) == sizeof (ill)) 11390Sstevel@tonic-gate return ((uintptr_t)ill.ill_wq); 11400Sstevel@tonic-gate 11410Sstevel@tonic-gate return (NULL); 11420Sstevel@tonic-gate } 11430Sstevel@tonic-gate 11440Sstevel@tonic-gate /* 11450Sstevel@tonic-gate * Print the core fields in an squeue_t. With the "-v" argument, 11460Sstevel@tonic-gate * provide more verbose output. 11470Sstevel@tonic-gate */ 11480Sstevel@tonic-gate static int 11490Sstevel@tonic-gate squeue(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 11500Sstevel@tonic-gate { 11510Sstevel@tonic-gate unsigned int i; 11520Sstevel@tonic-gate unsigned int verbose = FALSE; 11530Sstevel@tonic-gate const int SQUEUE_STATEDELT = (int)(sizeof (uintptr_t) + 9); 11540Sstevel@tonic-gate boolean_t arm; 11550Sstevel@tonic-gate squeue_t squeue; 11560Sstevel@tonic-gate 11570Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 11580Sstevel@tonic-gate if (mdb_walk_dcmd("genunix`squeue_cache", "ip`squeue", 11590Sstevel@tonic-gate argc, argv) == -1) { 11600Sstevel@tonic-gate mdb_warn("failed to walk squeue cache"); 11610Sstevel@tonic-gate return (DCMD_ERR); 11620Sstevel@tonic-gate } 11630Sstevel@tonic-gate return (DCMD_OK); 11640Sstevel@tonic-gate } 11650Sstevel@tonic-gate 11660Sstevel@tonic-gate if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) 11670Sstevel@tonic-gate != argc) 11680Sstevel@tonic-gate return (DCMD_USAGE); 11690Sstevel@tonic-gate 11700Sstevel@tonic-gate if (!DCMD_HDRSPEC(flags) && verbose) 11710Sstevel@tonic-gate mdb_printf("\n\n"); 11720Sstevel@tonic-gate 11730Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) || verbose) { 11740Sstevel@tonic-gate mdb_printf("%?s %-5s %-3s %?s %?s %?s\n", 11750Sstevel@tonic-gate "ADDR", "STATE", "CPU", 11760Sstevel@tonic-gate "FIRST", "LAST", "WORKER"); 11770Sstevel@tonic-gate } 11780Sstevel@tonic-gate 11790Sstevel@tonic-gate if (mdb_vread(&squeue, sizeof (squeue_t), addr) == -1) { 11800Sstevel@tonic-gate mdb_warn("cannot read squeue_t at %p", addr); 11810Sstevel@tonic-gate return (DCMD_ERR); 11820Sstevel@tonic-gate } 11830Sstevel@tonic-gate 11840Sstevel@tonic-gate mdb_printf("%0?p %05x %3d %0?p %0?p %0?p\n", 11850Sstevel@tonic-gate addr, squeue.sq_state, squeue.sq_bind, 11860Sstevel@tonic-gate squeue.sq_first, squeue.sq_last, squeue.sq_worker); 11870Sstevel@tonic-gate 11880Sstevel@tonic-gate if (!verbose) 11890Sstevel@tonic-gate return (DCMD_OK); 11900Sstevel@tonic-gate 11910Sstevel@tonic-gate arm = B_TRUE; 11920Sstevel@tonic-gate for (i = 0; squeue_states[i].bit_name != NULL; i++) { 11930Sstevel@tonic-gate if (((squeue.sq_state) & (1 << i)) == 0) 11940Sstevel@tonic-gate continue; 11950Sstevel@tonic-gate 11960Sstevel@tonic-gate if (arm) { 11970Sstevel@tonic-gate mdb_printf("%*s|\n", SQUEUE_STATEDELT, ""); 11980Sstevel@tonic-gate mdb_printf("%*s+--> ", SQUEUE_STATEDELT, ""); 11990Sstevel@tonic-gate arm = B_FALSE; 12000Sstevel@tonic-gate } else 12010Sstevel@tonic-gate mdb_printf("%*s ", SQUEUE_STATEDELT, ""); 12020Sstevel@tonic-gate 12030Sstevel@tonic-gate mdb_printf("%-12s %s\n", squeue_states[i].bit_name, 12040Sstevel@tonic-gate squeue_states[i].bit_descr); 12050Sstevel@tonic-gate } 12060Sstevel@tonic-gate 12070Sstevel@tonic-gate return (DCMD_OK); 12080Sstevel@tonic-gate } 12090Sstevel@tonic-gate 12100Sstevel@tonic-gate static void 12110Sstevel@tonic-gate ip_squeue_help(void) 12120Sstevel@tonic-gate { 12130Sstevel@tonic-gate mdb_printf("Print the core information for a given NCA squeue_t.\n\n"); 12140Sstevel@tonic-gate mdb_printf("Options:\n"); 12150Sstevel@tonic-gate mdb_printf("\t-v\tbe verbose (more descriptive)\n"); 12160Sstevel@tonic-gate } 12170Sstevel@tonic-gate 12185023Scarlsonj /* 12195023Scarlsonj * This is called by ::th_trace (via a callback) when walking the th_hash 12205023Scarlsonj * list. It calls modent to find the entries. 12215023Scarlsonj */ 12225023Scarlsonj /* ARGSUSED */ 12235023Scarlsonj static int 12245023Scarlsonj modent_summary(uintptr_t addr, const void *data, void *private) 12255023Scarlsonj { 12265023Scarlsonj th_walk_data_t *thw = private; 12275023Scarlsonj const struct mod_hash_entry *mhe = data; 12285023Scarlsonj th_trace_t th; 12295023Scarlsonj 12305023Scarlsonj if (mdb_vread(&th, sizeof (th), (uintptr_t)mhe->mhe_val) == -1) { 12315023Scarlsonj mdb_warn("failed to read th_trace_t %p", mhe->mhe_val); 12325023Scarlsonj return (WALK_ERR); 12335023Scarlsonj } 12345023Scarlsonj 12355023Scarlsonj if (th.th_refcnt == 0 && thw->thw_non_zero_only) 12365023Scarlsonj return (WALK_NEXT); 12375023Scarlsonj 12385023Scarlsonj if (!thw->thw_match) { 12395023Scarlsonj mdb_printf("%?p %?p %?p %8d %?p\n", thw->thw_ipst, mhe->mhe_key, 12405023Scarlsonj mhe->mhe_val, th.th_refcnt, th.th_id); 12415023Scarlsonj } else if (thw->thw_matchkey == (uintptr_t)mhe->mhe_key) { 12425023Scarlsonj int i, j, k; 12435023Scarlsonj tr_buf_t *tr; 12445023Scarlsonj 12455023Scarlsonj mdb_printf("Object %p in IP stack %p:\n", mhe->mhe_key, 12465023Scarlsonj thw->thw_ipst); 12475023Scarlsonj i = th.th_trace_lastref; 12485023Scarlsonj mdb_printf("\tThread %p refcnt %d:\n", th.th_id, 12495023Scarlsonj th.th_refcnt); 12505023Scarlsonj for (j = TR_BUF_MAX; j > 0; j--) { 12515023Scarlsonj tr = th.th_trbuf + i; 12525023Scarlsonj if (tr->tr_depth == 0 || tr->tr_depth > TR_STACK_DEPTH) 12535023Scarlsonj break; 12545023Scarlsonj mdb_printf("\t T%+ld:\n", tr->tr_time - 12555023Scarlsonj thw->thw_lbolt); 12565023Scarlsonj for (k = 0; k < tr->tr_depth; k++) 12575023Scarlsonj mdb_printf("\t\t%a\n", tr->tr_stack[k]); 12585023Scarlsonj if (--i < 0) 12595023Scarlsonj i = TR_BUF_MAX - 1; 12605023Scarlsonj } 12615023Scarlsonj } 12625023Scarlsonj return (WALK_NEXT); 12635023Scarlsonj } 12645023Scarlsonj 12655023Scarlsonj /* 12665023Scarlsonj * This is called by ::th_trace (via a callback) when walking the th_hash 12675023Scarlsonj * list. It calls modent to find the entries. 12685023Scarlsonj */ 12695023Scarlsonj /* ARGSUSED */ 12705023Scarlsonj static int 12715023Scarlsonj th_hash_summary(uintptr_t addr, const void *data, void *private) 12725023Scarlsonj { 12735023Scarlsonj const th_hash_t *thh = data; 12745023Scarlsonj th_walk_data_t *thw = private; 12755023Scarlsonj 12765023Scarlsonj thw->thw_ipst = (uintptr_t)thh->thh_ipst; 12775023Scarlsonj return (mdb_pwalk("modent", modent_summary, private, 12785023Scarlsonj (uintptr_t)thh->thh_hash)); 12795023Scarlsonj } 12805023Scarlsonj 12815023Scarlsonj /* 12825023Scarlsonj * Print or summarize the th_trace_t structures. 12835023Scarlsonj */ 12845023Scarlsonj static int 12855023Scarlsonj th_trace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 12865023Scarlsonj { 12875023Scarlsonj th_walk_data_t thw; 12885023Scarlsonj 12895023Scarlsonj (void) memset(&thw, 0, sizeof (thw)); 12905023Scarlsonj 12915023Scarlsonj if (mdb_getopts(argc, argv, 12925023Scarlsonj 'n', MDB_OPT_SETBITS, TRUE, &thw.thw_non_zero_only, 12935023Scarlsonj NULL) != argc) 12945023Scarlsonj return (DCMD_USAGE); 12955023Scarlsonj 12965023Scarlsonj if (!(flags & DCMD_ADDRSPEC)) { 12975023Scarlsonj /* 12985023Scarlsonj * No address specified. Walk all of the th_hash_t in the 12995023Scarlsonj * system, and summarize the th_trace_t entries in each. 13005023Scarlsonj */ 13015023Scarlsonj mdb_printf("%?s %?s %?s %8s %?s\n", 13025023Scarlsonj "IPSTACK", "OBJECT", "TRACE", "REFCNT", "THREAD"); 13035023Scarlsonj thw.thw_match = B_FALSE; 13045023Scarlsonj } else { 13055023Scarlsonj thw.thw_match = B_TRUE; 13065023Scarlsonj thw.thw_matchkey = addr; 13075023Scarlsonj if (mdb_readvar(&thw.thw_lbolt, 13085023Scarlsonj mdb_prop_postmortem ? "panic_lbolt" : "lbolt") == -1) { 13095023Scarlsonj mdb_warn("failed to read lbolt"); 13105023Scarlsonj return (DCMD_ERR); 13115023Scarlsonj } 13125023Scarlsonj } 13135023Scarlsonj if (mdb_pwalk("th_hash", th_hash_summary, &thw, NULL) == -1) { 13145023Scarlsonj mdb_warn("can't walk th_hash entries"); 13155023Scarlsonj return (DCMD_ERR); 13165023Scarlsonj } 13175023Scarlsonj return (DCMD_OK); 13185023Scarlsonj } 13195023Scarlsonj 13205023Scarlsonj static void 13215023Scarlsonj th_trace_help(void) 13225023Scarlsonj { 13235023Scarlsonj mdb_printf("If given an address of an ill_t, ipif_t, ire_t, or nce_t, " 13245023Scarlsonj "print the\n" 13255023Scarlsonj "corresponding th_trace_t structure in detail. Otherwise, if no " 13265023Scarlsonj "address is\n" 13275023Scarlsonj "given, then summarize all th_trace_t structures.\n\n"); 13285023Scarlsonj mdb_printf("Options:\n" 13295023Scarlsonj "\t-n\tdisplay only entries with non-zero th_refcnt\n"); 13305023Scarlsonj } 13315023Scarlsonj 13320Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = { 1333*9089SVasumathi.Sundaram@Sun.COM { "conn_status", ":", 1334*9089SVasumathi.Sundaram@Sun.COM "display connection structures from ipcl hash tables", 1335*9089SVasumathi.Sundaram@Sun.COM conn_status, conn_status_help }, 1336*9089SVasumathi.Sundaram@Sun.COM { "srcid_status", ":", 1337*9089SVasumathi.Sundaram@Sun.COM "display connection structures from ipcl hash tables", 1338*9089SVasumathi.Sundaram@Sun.COM srcid_status }, 1339*9089SVasumathi.Sundaram@Sun.COM { "ill", "?[-v] [-P v4 | v6]", "display ill_t structures", 1340*9089SVasumathi.Sundaram@Sun.COM ill, ill_help }, 13410Sstevel@tonic-gate { "illif", "?[-P v4 | v6]", 13420Sstevel@tonic-gate "display or filter IP Lower Level InterFace structures", illif, 13430Sstevel@tonic-gate illif_help }, 13440Sstevel@tonic-gate { "iphdr", ":[-vf]", "display an IPv4 header", iphdr }, 13450Sstevel@tonic-gate { "ip6hdr", ":[-vf]", "display an IPv6 header", ip6hdr }, 1346*9089SVasumathi.Sundaram@Sun.COM { "ipif", "?[-v] [-P v4 | v6]", "display ipif structures", 1347*9089SVasumathi.Sundaram@Sun.COM ipif, ipif_help }, 13485940Ssowmini { "ire", "?[-v] [-P v4|v6]", 13495940Ssowmini "display Internet Route Entry structures", ire }, 13505940Ssowmini { "nce", "?[-P v4 | v6]", "display Neighbor Cache Entry structures", 13515940Ssowmini nce }, 13520Sstevel@tonic-gate { "squeue", ":[-v]", "print core squeue_t info", squeue, 13530Sstevel@tonic-gate ip_squeue_help }, 13540Sstevel@tonic-gate { "tcphdr", ":", "display a TCP header", tcphdr }, 13550Sstevel@tonic-gate { "udphdr", ":", "display an UDP header", udphdr }, 13560Sstevel@tonic-gate { "sctphdr", ":", "display an SCTP header", sctphdr }, 13575023Scarlsonj { "th_trace", "?[-n]", "display th_trace_t structures", th_trace, 13585023Scarlsonj th_trace_help }, 13590Sstevel@tonic-gate { NULL } 13600Sstevel@tonic-gate }; 13610Sstevel@tonic-gate 13620Sstevel@tonic-gate static const mdb_walker_t walkers[] = { 1363*9089SVasumathi.Sundaram@Sun.COM { "conn_status", "walk list of conn_t structures", 1364*9089SVasumathi.Sundaram@Sun.COM ip_stacks_common_walk_init, conn_status_walk_step, NULL }, 13653448Sdh155122 { "illif", "walk list of ill interface types for all stacks", 13665940Ssowmini ip_stacks_common_walk_init, illif_walk_step, NULL }, 13673448Sdh155122 { "illif_stack", "walk list of ill interface types", 13683448Sdh155122 illif_stack_walk_init, illif_stack_walk_step, 13693448Sdh155122 illif_stack_walk_fini }, 1370*9089SVasumathi.Sundaram@Sun.COM { "ill", "walk list of nce structures for all stacks", 1371*9089SVasumathi.Sundaram@Sun.COM ill_walk_init, ill_walk_step, NULL }, 1372*9089SVasumathi.Sundaram@Sun.COM { "ipif", "walk list of ipif structures for all stacks", 1373*9089SVasumathi.Sundaram@Sun.COM ipif_walk_init, ipif_walk_step, NULL }, 1374*9089SVasumathi.Sundaram@Sun.COM { "ipif_list", "walk the linked list of ipif structures " 1375*9089SVasumathi.Sundaram@Sun.COM "for a given ill", 1376*9089SVasumathi.Sundaram@Sun.COM ip_list_walk_init, ip_list_walk_step, 1377*9089SVasumathi.Sundaram@Sun.COM ip_list_walk_fini, &ipif_walk_arg }, 1378*9089SVasumathi.Sundaram@Sun.COM { "srcid", "walk list of srcid_map structures for all stacks", 1379*9089SVasumathi.Sundaram@Sun.COM ip_stacks_common_walk_init, srcid_walk_step, NULL }, 1380*9089SVasumathi.Sundaram@Sun.COM { "srcid_list", "walk list of srcid_map structures for a stack", 1381*9089SVasumathi.Sundaram@Sun.COM ip_list_walk_init, ip_list_walk_step, ip_list_walk_fini, 1382*9089SVasumathi.Sundaram@Sun.COM &srcid_walk_arg }, 13830Sstevel@tonic-gate { "ire", "walk active ire_t structures", 13840Sstevel@tonic-gate ire_walk_init, ire_walk_step, NULL }, 13853448Sdh155122 { "ire_ctable", "walk ire_t structures in the ctable", 13865940Ssowmini ip_stacks_common_walk_init, ire_ctable_walk_step, NULL }, 13873448Sdh155122 { "ire_next", "walk ire_t structures in the ctable", 13883448Sdh155122 ire_next_walk_init, ire_next_walk_step, NULL }, 13893448Sdh155122 { "ip_stacks", "walk all the ip_stack_t", 13903448Sdh155122 ip_stacks_walk_init, ip_stacks_walk_step, NULL }, 13915023Scarlsonj { "th_hash", "walk all the th_hash_t entries", 13925023Scarlsonj th_hash_walk_init, th_hash_walk_step, NULL }, 13935940Ssowmini { "nce", "walk list of nce structures for all stacks", 13945940Ssowmini ip_stacks_common_walk_init, nce_walk_step, NULL }, 13955940Ssowmini { "nce_stack", "walk list of nce structures", 13965940Ssowmini nce_stack_walk_init, nce_stack_walk_step, 13975940Ssowmini nce_stack_walk_fini}, 1398*9089SVasumathi.Sundaram@Sun.COM { "udp_hash", "walk list of conn_t structures in ips_ipcl_udp_fanout", 1399*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_init, ipcl_hash_walk_step, 1400*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_fini, &udp_hash_arg}, 1401*9089SVasumathi.Sundaram@Sun.COM { "conn_hash", "walk list of conn_t structures in ips_ipcl_conn_fanout", 1402*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_init, ipcl_hash_walk_step, 1403*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_fini, &conn_hash_arg}, 1404*9089SVasumathi.Sundaram@Sun.COM { "bind_hash", "walk list of conn_t structures in ips_ipcl_bind_fanout", 1405*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_init, ipcl_hash_walk_step, 1406*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_fini, &bind_hash_arg}, 1407*9089SVasumathi.Sundaram@Sun.COM { "proto_hash", "walk list of conn_t structures in " 1408*9089SVasumathi.Sundaram@Sun.COM "ips_ipcl_proto_fanout", 1409*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_init, ipcl_hash_walk_step, 1410*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_fini, &proto_hash_arg}, 1411*9089SVasumathi.Sundaram@Sun.COM { "proto_v6_hash", "walk list of conn_t structures in " 1412*9089SVasumathi.Sundaram@Sun.COM "ips_ipcl_proto_fanout_v6", 1413*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_init, ipcl_hash_walk_step, 1414*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_fini, &proto_v6_hash_arg}, 14150Sstevel@tonic-gate { NULL } 14160Sstevel@tonic-gate }; 14170Sstevel@tonic-gate 14180Sstevel@tonic-gate static const mdb_qops_t ip_qops = { ip_qinfo, ip_rnext, ip_wnext }; 14190Sstevel@tonic-gate static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 14200Sstevel@tonic-gate 14210Sstevel@tonic-gate const mdb_modinfo_t * 14220Sstevel@tonic-gate _mdb_init(void) 14230Sstevel@tonic-gate { 14240Sstevel@tonic-gate GElf_Sym sym; 14250Sstevel@tonic-gate 14262546Scarlsonj if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0) 14270Sstevel@tonic-gate mdb_qops_install(&ip_qops, (uintptr_t)sym.st_value); 14280Sstevel@tonic-gate 14290Sstevel@tonic-gate return (&modinfo); 14300Sstevel@tonic-gate } 14310Sstevel@tonic-gate 14320Sstevel@tonic-gate void 14330Sstevel@tonic-gate _mdb_fini(void) 14340Sstevel@tonic-gate { 14350Sstevel@tonic-gate GElf_Sym sym; 14360Sstevel@tonic-gate 14372546Scarlsonj if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0) 14380Sstevel@tonic-gate mdb_qops_remove(&ip_qops, (uintptr_t)sym.st_value); 14390Sstevel@tonic-gate } 14405940Ssowmini 14415940Ssowmini static char * 14425940Ssowmini nce_state(int nce_state) 14435940Ssowmini { 14445940Ssowmini switch (nce_state) { 14455940Ssowmini case ND_UNCHANGED: 14465940Ssowmini return ("unchanged"); 14475940Ssowmini case ND_INCOMPLETE: 14485940Ssowmini return ("incomplete"); 14495940Ssowmini case ND_REACHABLE: 14505940Ssowmini return ("reachable"); 14515940Ssowmini case ND_STALE: 14525940Ssowmini return ("stale"); 14535940Ssowmini case ND_DELAY: 14545940Ssowmini return ("delay"); 14555940Ssowmini case ND_PROBE: 14565940Ssowmini return ("probe"); 14575940Ssowmini case ND_UNREACHABLE: 14585940Ssowmini return ("unreach"); 14595940Ssowmini case ND_INITIAL: 14605940Ssowmini return ("initial"); 14615940Ssowmini default: 14625940Ssowmini return ("??"); 14635940Ssowmini } 14645940Ssowmini } 14655940Ssowmini 14665940Ssowmini static char * 14675940Ssowmini nce_l2_addr(const nce_t *nce, const ill_t *ill) 14685940Ssowmini { 14695940Ssowmini uchar_t *h; 14705940Ssowmini static char addr_buf[L2MAXADDRSTRLEN]; 14715940Ssowmini mblk_t mp; 14725940Ssowmini size_t mblen; 14735940Ssowmini 14745940Ssowmini if (ill->ill_flags & ILLF_XRESOLV) { 14755940Ssowmini return ("XRESOLV"); 14765940Ssowmini } 14775940Ssowmini 14785940Ssowmini if (nce->nce_res_mp == NULL) { 14795940Ssowmini return ("None"); 14805940Ssowmini } 14815940Ssowmini 14825940Ssowmini if (ill->ill_net_type == IRE_IF_RESOLVER) { 14835940Ssowmini 14845940Ssowmini if (mdb_vread(&mp, sizeof (mblk_t), 14855940Ssowmini (uintptr_t)nce->nce_res_mp) == -1) { 14865940Ssowmini mdb_warn("failed to read nce_res_mp at %p", 14875940Ssowmini nce->nce_res_mp); 14885940Ssowmini } 14895940Ssowmini 14905940Ssowmini if (ill->ill_nd_lla_len == 0) 14915940Ssowmini return ("None"); 14925940Ssowmini mblen = mp.b_wptr - mp.b_rptr; 14935940Ssowmini if (mblen > (sizeof (dl_unitdata_req_t) + MAX_SAP_LEN) || 14945940Ssowmini ill->ill_nd_lla_len > MAX_SAP_LEN || 14955940Ssowmini NCE_LL_ADDR_OFFSET(ill) + ill->ill_nd_lla_len > mblen) { 14965940Ssowmini return ("Truncated"); 14975940Ssowmini } 14985940Ssowmini h = mdb_zalloc(mblen, UM_SLEEP); 14995940Ssowmini if (mdb_vread(h, mblen, (uintptr_t)(mp.b_rptr)) == -1) { 15005940Ssowmini mdb_warn("failed to read hwaddr at %p", 15015940Ssowmini mp.b_rptr + NCE_LL_ADDR_OFFSET(ill)); 15025940Ssowmini return ("Unknown"); 15035940Ssowmini } 15045940Ssowmini mdb_mac_addr(h + NCE_LL_ADDR_OFFSET(ill), ill->ill_nd_lla_len, 15055940Ssowmini addr_buf, sizeof (addr_buf)); 15065940Ssowmini } else { 15075940Ssowmini return ("None"); 15085940Ssowmini } 15095940Ssowmini mdb_free(h, mblen); 15105940Ssowmini return (addr_buf); 15115940Ssowmini } 15125940Ssowmini 15135940Ssowmini static void 15145940Ssowmini nce_header(uint_t flags) 15155940Ssowmini { 15165940Ssowmini if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 15175940Ssowmini 15185940Ssowmini mdb_printf("%<u>%?s %-20s %-10s %-8s %-5s %s%</u>\n", 15195940Ssowmini "ADDR", "HW_ADDR", "STATE", "FLAGS", "ILL", "IP ADDR"); 15205940Ssowmini } 15215940Ssowmini } 15225940Ssowmini 15235940Ssowmini int 15245940Ssowmini nce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 15255940Ssowmini { 15265940Ssowmini nce_t nce; 15275940Ssowmini nce_cbdata_t id; 15285940Ssowmini int ipversion = 0; 15295940Ssowmini const char *opt_P = NULL; 15305940Ssowmini 15315940Ssowmini if (mdb_getopts(argc, argv, 15325940Ssowmini 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 15335940Ssowmini return (DCMD_USAGE); 15345940Ssowmini 15355940Ssowmini if (opt_P != NULL) { 15365940Ssowmini if (strcmp("v4", opt_P) == 0) { 15375940Ssowmini ipversion = IPV4_VERSION; 15385940Ssowmini } else if (strcmp("v6", opt_P) == 0) { 15395940Ssowmini ipversion = IPV6_VERSION; 15405940Ssowmini } else { 15415940Ssowmini mdb_warn("invalid protocol '%s'\n", opt_P); 15425940Ssowmini return (DCMD_USAGE); 15435940Ssowmini } 15445940Ssowmini } 15455940Ssowmini 15465940Ssowmini if (flags & DCMD_ADDRSPEC) { 15475940Ssowmini 15485940Ssowmini if (mdb_vread(&nce, sizeof (nce_t), addr) == -1) { 15495940Ssowmini mdb_warn("failed to read nce at %p\n", addr); 15505940Ssowmini return (DCMD_ERR); 15515940Ssowmini } 15525940Ssowmini if (ipversion != 0 && nce.nce_ipversion != ipversion) { 15535940Ssowmini mdb_printf("IP Version mismatch\n"); 15545940Ssowmini return (DCMD_ERR); 15555940Ssowmini } 15565940Ssowmini nce_header(flags); 15575940Ssowmini return (nce_format(addr, &nce, ipversion)); 15585940Ssowmini 15595940Ssowmini } else { 15605940Ssowmini id.nce_addr = addr; 15615940Ssowmini id.nce_ipversion = ipversion; 15625940Ssowmini nce_header(flags); 15635940Ssowmini if (mdb_walk("nce", (mdb_walk_cb_t)nce_cb, &id) == -1) { 15645940Ssowmini mdb_warn("failed to walk nce table\n"); 15655940Ssowmini return (DCMD_ERR); 15665940Ssowmini } 15675940Ssowmini } 15685940Ssowmini return (DCMD_OK); 15695940Ssowmini } 15705940Ssowmini 15715940Ssowmini static int 15725940Ssowmini nce_format(uintptr_t addr, const nce_t *nce, int ipversion) 15735940Ssowmini { 15745940Ssowmini static const mdb_bitmask_t nce_flags[] = { 15755940Ssowmini { "P", NCE_F_PERMANENT, NCE_F_PERMANENT }, 15765940Ssowmini { "R", NCE_F_ISROUTER, NCE_F_ISROUTER }, 15775940Ssowmini { "N", NCE_F_NONUD, NCE_F_NONUD }, 15785940Ssowmini { "A", NCE_F_ANYCAST, NCE_F_ANYCAST }, 15795940Ssowmini { "C", NCE_F_CONDEMNED, NCE_F_CONDEMNED }, 15805940Ssowmini { "U", NCE_F_UNSOL_ADV, NCE_F_UNSOL_ADV }, 15815940Ssowmini { "B", NCE_F_BCAST, NCE_F_BCAST }, 15825940Ssowmini { NULL, 0, 0 } 15835940Ssowmini }; 15845940Ssowmini #define NCE_MAX_FLAGS (sizeof (nce_flags) / sizeof (mdb_bitmask_t)) 15855940Ssowmini struct in_addr nceaddr; 15865940Ssowmini ill_t ill; 15875940Ssowmini char ill_name[LIFNAMSIZ]; 15885940Ssowmini char flagsbuf[NCE_MAX_FLAGS]; 15895940Ssowmini 15905940Ssowmini if (mdb_vread(&ill, sizeof (ill), (uintptr_t)nce->nce_ill) == -1) { 15915940Ssowmini mdb_warn("failed to read nce_ill at %p", 15925940Ssowmini nce->nce_ill); 15935940Ssowmini return (DCMD_ERR); 15945940Ssowmini } 15955940Ssowmini 15965940Ssowmini (void) mdb_readstr(ill_name, MIN(LIFNAMSIZ, ill.ill_name_length), 15975940Ssowmini (uintptr_t)ill.ill_name); 15985940Ssowmini 15995940Ssowmini mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%hb", 16005940Ssowmini nce->nce_flags, nce_flags); 16015940Ssowmini 16025940Ssowmini if (ipversion != 0 && nce->nce_ipversion != ipversion) 16035940Ssowmini return (DCMD_OK); 16045940Ssowmini 16055940Ssowmini if (nce->nce_ipversion == IPV4_VERSION) { 16065940Ssowmini IN6_V4MAPPED_TO_INADDR(&nce->nce_addr, &nceaddr); 16075940Ssowmini mdb_printf("%?p %-20s %-10s " 16085940Ssowmini "%-8s " 16095940Ssowmini "%-5s %I\n", 16105940Ssowmini addr, nce_l2_addr(nce, &ill), 16115940Ssowmini nce_state(nce->nce_state), 16125940Ssowmini flagsbuf, 16135940Ssowmini ill_name, nceaddr.s_addr); 16145940Ssowmini } else { 16155940Ssowmini mdb_printf("%?p %-20s %-10s %-8s %-5s %N\n", 16165940Ssowmini addr, nce_l2_addr(nce, &ill), 16175940Ssowmini nce_state(nce->nce_state), 16185940Ssowmini flagsbuf, 16195940Ssowmini ill_name, &nce->nce_addr); 16205940Ssowmini } 16215940Ssowmini 16225940Ssowmini return (DCMD_OK); 16235940Ssowmini } 16245940Ssowmini 16255940Ssowmini static uintptr_t 16265940Ssowmini nce_get_next_hash_tbl(uintptr_t start, int *index, struct ndp_g_s ndp) 16275940Ssowmini { 16285940Ssowmini uintptr_t addr = start; 16295940Ssowmini int i = *index; 16305940Ssowmini 16315940Ssowmini while (addr == NULL) { 16325940Ssowmini 16335940Ssowmini if (++i >= NCE_TABLE_SIZE) 16345940Ssowmini break; 16355940Ssowmini addr = (uintptr_t)ndp.nce_hash_tbl[i]; 16365940Ssowmini } 16375940Ssowmini *index = i; 16385940Ssowmini return (addr); 16395940Ssowmini } 16405940Ssowmini 16415940Ssowmini static int 16425940Ssowmini nce_walk_step(mdb_walk_state_t *wsp) 16435940Ssowmini { 16445940Ssowmini uintptr_t kaddr4, kaddr6; 16455940Ssowmini 16465940Ssowmini kaddr4 = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ndp4); 16475940Ssowmini kaddr6 = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ndp6); 16485940Ssowmini 16495940Ssowmini if (mdb_vread(&kaddr4, sizeof (kaddr4), kaddr4) == -1) { 16505940Ssowmini mdb_warn("can't read ips_ip_cache_table at %p", kaddr4); 16515940Ssowmini return (WALK_ERR); 16525940Ssowmini } 16535940Ssowmini if (mdb_vread(&kaddr6, sizeof (kaddr6), kaddr6) == -1) { 16545940Ssowmini mdb_warn("can't read ips_ip_cache_table at %p", kaddr6); 16555940Ssowmini return (WALK_ERR); 16565940Ssowmini } 16575940Ssowmini if (mdb_pwalk("nce_stack", wsp->walk_callback, wsp->walk_cbdata, 16585940Ssowmini kaddr4) == -1) { 16595940Ssowmini mdb_warn("couldn't walk 'nce_stack' for ips_ndp4 %p", 16605940Ssowmini kaddr4); 16615940Ssowmini return (WALK_ERR); 16625940Ssowmini } 16635940Ssowmini if (mdb_pwalk("nce_stack", wsp->walk_callback, 16645940Ssowmini wsp->walk_cbdata, kaddr6) == -1) { 16655940Ssowmini mdb_warn("couldn't walk 'nce_stack' for ips_ndp6 %p", 16665940Ssowmini kaddr6); 16675940Ssowmini return (WALK_ERR); 16685940Ssowmini } 16695940Ssowmini return (WALK_NEXT); 16705940Ssowmini } 16715940Ssowmini 1672*9089SVasumathi.Sundaram@Sun.COM static uintptr_t 1673*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_get_next_connf_tbl(ipcl_hash_walk_data_t *iw) 1674*9089SVasumathi.Sundaram@Sun.COM { 1675*9089SVasumathi.Sundaram@Sun.COM struct connf_s connf; 1676*9089SVasumathi.Sundaram@Sun.COM uintptr_t addr = NULL, next; 1677*9089SVasumathi.Sundaram@Sun.COM int index = iw->connf_tbl_index; 1678*9089SVasumathi.Sundaram@Sun.COM 1679*9089SVasumathi.Sundaram@Sun.COM do { 1680*9089SVasumathi.Sundaram@Sun.COM next = iw->hash_tbl + index * sizeof (struct connf_s); 1681*9089SVasumathi.Sundaram@Sun.COM if (++index >= iw->hash_tbl_size) { 1682*9089SVasumathi.Sundaram@Sun.COM addr = NULL; 1683*9089SVasumathi.Sundaram@Sun.COM break; 1684*9089SVasumathi.Sundaram@Sun.COM } 1685*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&connf, sizeof (struct connf_s), next) == -1) { 1686*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read conn_t at %p", next); 1687*9089SVasumathi.Sundaram@Sun.COM return (NULL); 1688*9089SVasumathi.Sundaram@Sun.COM } 1689*9089SVasumathi.Sundaram@Sun.COM addr = (uintptr_t)connf.connf_head; 1690*9089SVasumathi.Sundaram@Sun.COM } while (addr == NULL); 1691*9089SVasumathi.Sundaram@Sun.COM iw->connf_tbl_index = index; 1692*9089SVasumathi.Sundaram@Sun.COM return (addr); 1693*9089SVasumathi.Sundaram@Sun.COM } 1694*9089SVasumathi.Sundaram@Sun.COM 1695*9089SVasumathi.Sundaram@Sun.COM static int 1696*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_init(mdb_walk_state_t *wsp) 1697*9089SVasumathi.Sundaram@Sun.COM { 1698*9089SVasumathi.Sundaram@Sun.COM const hash_walk_arg_t *arg = wsp->walk_arg; 1699*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_data_t *iw; 1700*9089SVasumathi.Sundaram@Sun.COM uintptr_t tbladdr; 1701*9089SVasumathi.Sundaram@Sun.COM uintptr_t sizeaddr; 1702*9089SVasumathi.Sundaram@Sun.COM 1703*9089SVasumathi.Sundaram@Sun.COM iw = mdb_alloc(sizeof (ipcl_hash_walk_data_t), UM_SLEEP); 1704*9089SVasumathi.Sundaram@Sun.COM iw->conn = mdb_alloc(sizeof (conn_t), UM_SLEEP); 1705*9089SVasumathi.Sundaram@Sun.COM tbladdr = wsp->walk_addr + arg->tbl_off; 1706*9089SVasumathi.Sundaram@Sun.COM sizeaddr = wsp->walk_addr + arg->size_off; 1707*9089SVasumathi.Sundaram@Sun.COM 1708*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&iw->hash_tbl, sizeof (uintptr_t), tbladdr) == -1) { 1709*9089SVasumathi.Sundaram@Sun.COM mdb_warn("can't read fanout table addr at %p", tbladdr); 1710*9089SVasumathi.Sundaram@Sun.COM mdb_free(iw->conn, sizeof (conn_t)); 1711*9089SVasumathi.Sundaram@Sun.COM mdb_free(iw, sizeof (ipcl_hash_walk_data_t)); 1712*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 1713*9089SVasumathi.Sundaram@Sun.COM } 1714*9089SVasumathi.Sundaram@Sun.COM if (arg->tbl_off == OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout) || 1715*9089SVasumathi.Sundaram@Sun.COM arg->tbl_off == OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v6)) { 1716*9089SVasumathi.Sundaram@Sun.COM iw->hash_tbl_size = IPPROTO_MAX; 1717*9089SVasumathi.Sundaram@Sun.COM } else { 1718*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&iw->hash_tbl_size, sizeof (int), 1719*9089SVasumathi.Sundaram@Sun.COM sizeaddr) == -1) { 1720*9089SVasumathi.Sundaram@Sun.COM mdb_warn("can't read fanout table size addr at %p", 1721*9089SVasumathi.Sundaram@Sun.COM sizeaddr); 1722*9089SVasumathi.Sundaram@Sun.COM mdb_free(iw->conn, sizeof (conn_t)); 1723*9089SVasumathi.Sundaram@Sun.COM mdb_free(iw, sizeof (ipcl_hash_walk_data_t)); 1724*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 1725*9089SVasumathi.Sundaram@Sun.COM } 1726*9089SVasumathi.Sundaram@Sun.COM } 1727*9089SVasumathi.Sundaram@Sun.COM iw->connf_tbl_index = 0; 1728*9089SVasumathi.Sundaram@Sun.COM wsp->walk_addr = ipcl_hash_get_next_connf_tbl(iw); 1729*9089SVasumathi.Sundaram@Sun.COM wsp->walk_data = iw; 1730*9089SVasumathi.Sundaram@Sun.COM 1731*9089SVasumathi.Sundaram@Sun.COM if (wsp->walk_addr != NULL) 1732*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 1733*9089SVasumathi.Sundaram@Sun.COM else 1734*9089SVasumathi.Sundaram@Sun.COM return (WALK_DONE); 1735*9089SVasumathi.Sundaram@Sun.COM } 1736*9089SVasumathi.Sundaram@Sun.COM 1737*9089SVasumathi.Sundaram@Sun.COM static int 1738*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_step(mdb_walk_state_t *wsp) 1739*9089SVasumathi.Sundaram@Sun.COM { 1740*9089SVasumathi.Sundaram@Sun.COM uintptr_t addr = wsp->walk_addr; 1741*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_data_t *iw = wsp->walk_data; 1742*9089SVasumathi.Sundaram@Sun.COM conn_t *conn = iw->conn; 1743*9089SVasumathi.Sundaram@Sun.COM int ret = WALK_DONE; 1744*9089SVasumathi.Sundaram@Sun.COM 1745*9089SVasumathi.Sundaram@Sun.COM while (addr != NULL) { 1746*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(conn, sizeof (conn_t), addr) == -1) { 1747*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read conn_t at %p", addr); 1748*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 1749*9089SVasumathi.Sundaram@Sun.COM } 1750*9089SVasumathi.Sundaram@Sun.COM ret = wsp->walk_callback(addr, iw, wsp->walk_cbdata); 1751*9089SVasumathi.Sundaram@Sun.COM if (ret != WALK_NEXT) 1752*9089SVasumathi.Sundaram@Sun.COM break; 1753*9089SVasumathi.Sundaram@Sun.COM addr = (uintptr_t)conn->conn_next; 1754*9089SVasumathi.Sundaram@Sun.COM } 1755*9089SVasumathi.Sundaram@Sun.COM if (ret == WALK_NEXT) { 1756*9089SVasumathi.Sundaram@Sun.COM wsp->walk_addr = ipcl_hash_get_next_connf_tbl(iw); 1757*9089SVasumathi.Sundaram@Sun.COM 1758*9089SVasumathi.Sundaram@Sun.COM if (wsp->walk_addr != NULL) 1759*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 1760*9089SVasumathi.Sundaram@Sun.COM else 1761*9089SVasumathi.Sundaram@Sun.COM return (WALK_DONE); 1762*9089SVasumathi.Sundaram@Sun.COM } 1763*9089SVasumathi.Sundaram@Sun.COM 1764*9089SVasumathi.Sundaram@Sun.COM return (ret); 1765*9089SVasumathi.Sundaram@Sun.COM } 1766*9089SVasumathi.Sundaram@Sun.COM 1767*9089SVasumathi.Sundaram@Sun.COM static void 1768*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_fini(mdb_walk_state_t *wsp) 1769*9089SVasumathi.Sundaram@Sun.COM { 1770*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_data_t *iw = wsp->walk_data; 1771*9089SVasumathi.Sundaram@Sun.COM 1772*9089SVasumathi.Sundaram@Sun.COM mdb_free(iw->conn, sizeof (conn_t)); 1773*9089SVasumathi.Sundaram@Sun.COM mdb_free(iw, sizeof (ipcl_hash_walk_data_t)); 1774*9089SVasumathi.Sundaram@Sun.COM } 1775*9089SVasumathi.Sundaram@Sun.COM 17765940Ssowmini /* 17775940Ssowmini * Called with walk_addr being the address of ips_ndp{4,6} 17785940Ssowmini */ 17795940Ssowmini static int 17805940Ssowmini nce_stack_walk_init(mdb_walk_state_t *wsp) 17815940Ssowmini { 17825940Ssowmini nce_walk_data_t *nw; 17835940Ssowmini 17845940Ssowmini if (wsp->walk_addr == NULL) { 17855940Ssowmini mdb_warn("nce_stack requires ndp_g_s address\n"); 17865940Ssowmini return (WALK_ERR); 17875940Ssowmini } 17885940Ssowmini 17895940Ssowmini nw = mdb_alloc(sizeof (nce_walk_data_t), UM_SLEEP); 17905940Ssowmini 17915940Ssowmini if (mdb_vread(&nw->nce_ip_ndp, sizeof (struct ndp_g_s), 17925940Ssowmini wsp->walk_addr) == -1) { 17935940Ssowmini mdb_warn("failed to read 'ip_ndp' at %p", 17945940Ssowmini wsp->walk_addr); 17955940Ssowmini mdb_free(nw, sizeof (nce_walk_data_t)); 17965940Ssowmini return (WALK_ERR); 17975940Ssowmini } 17985940Ssowmini 17995940Ssowmini nw->nce_hash_tbl_index = 0; 18005940Ssowmini wsp->walk_addr = nce_get_next_hash_tbl(NULL, 18015940Ssowmini &nw->nce_hash_tbl_index, nw->nce_ip_ndp); 18025940Ssowmini wsp->walk_data = nw; 18035940Ssowmini 18045940Ssowmini return (WALK_NEXT); 18055940Ssowmini } 18065940Ssowmini 18075940Ssowmini static int 18085940Ssowmini nce_stack_walk_step(mdb_walk_state_t *wsp) 18095940Ssowmini { 18105940Ssowmini uintptr_t addr = wsp->walk_addr; 18115940Ssowmini nce_walk_data_t *nw = wsp->walk_data; 18125940Ssowmini 18135940Ssowmini if (addr == NULL) 18145940Ssowmini return (WALK_DONE); 18155940Ssowmini 18165940Ssowmini if (mdb_vread(&nw->nce, sizeof (nce_t), addr) == -1) { 18175940Ssowmini mdb_warn("failed to read nce_t at %p", addr); 18185940Ssowmini return (WALK_ERR); 18195940Ssowmini } 18205940Ssowmini 18215940Ssowmini wsp->walk_addr = (uintptr_t)nw->nce.nce_next; 18225940Ssowmini 18235940Ssowmini wsp->walk_addr = nce_get_next_hash_tbl(wsp->walk_addr, 18245940Ssowmini &nw->nce_hash_tbl_index, nw->nce_ip_ndp); 18255940Ssowmini 18265940Ssowmini return (wsp->walk_callback(addr, nw, wsp->walk_cbdata)); 18275940Ssowmini } 18285940Ssowmini 18295940Ssowmini static void 18305940Ssowmini nce_stack_walk_fini(mdb_walk_state_t *wsp) 18315940Ssowmini { 18325940Ssowmini mdb_free(wsp->walk_data, sizeof (nce_walk_data_t)); 18335940Ssowmini } 18345940Ssowmini 18355940Ssowmini /* ARGSUSED */ 18365940Ssowmini static int 18375940Ssowmini nce_cb(uintptr_t addr, const nce_walk_data_t *iw, nce_cbdata_t *id) 18385940Ssowmini { 18395940Ssowmini nce_t nce; 18405940Ssowmini 18415940Ssowmini if (mdb_vread(&nce, sizeof (nce_t), addr) == -1) { 18425940Ssowmini mdb_warn("failed to read nce at %p", addr); 18435940Ssowmini return (WALK_NEXT); 18445940Ssowmini } 18455940Ssowmini (void) nce_format(addr, &nce, id->nce_ipversion); 18465940Ssowmini return (WALK_NEXT); 18475940Ssowmini } 1848*9089SVasumathi.Sundaram@Sun.COM 1849*9089SVasumathi.Sundaram@Sun.COM static int 1850*9089SVasumathi.Sundaram@Sun.COM ill_walk_init(mdb_walk_state_t *wsp) 1851*9089SVasumathi.Sundaram@Sun.COM { 1852*9089SVasumathi.Sundaram@Sun.COM if (mdb_layered_walk("illif", wsp) == -1) { 1853*9089SVasumathi.Sundaram@Sun.COM mdb_warn("can't walk 'illif'"); 1854*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 1855*9089SVasumathi.Sundaram@Sun.COM } 1856*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 1857*9089SVasumathi.Sundaram@Sun.COM } 1858*9089SVasumathi.Sundaram@Sun.COM 1859*9089SVasumathi.Sundaram@Sun.COM static int 1860*9089SVasumathi.Sundaram@Sun.COM ill_walk_step(mdb_walk_state_t *wsp) 1861*9089SVasumathi.Sundaram@Sun.COM { 1862*9089SVasumathi.Sundaram@Sun.COM ill_if_t ill_if; 1863*9089SVasumathi.Sundaram@Sun.COM 1864*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&ill_if, sizeof (ill_if_t), wsp->walk_addr) == -1) { 1865*9089SVasumathi.Sundaram@Sun.COM mdb_warn("can't read ill_if_t at %p", wsp->walk_addr); 1866*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 1867*9089SVasumathi.Sundaram@Sun.COM } 1868*9089SVasumathi.Sundaram@Sun.COM wsp->walk_addr = (uintptr_t)(wsp->walk_addr + 1869*9089SVasumathi.Sundaram@Sun.COM offsetof(ill_if_t, illif_avl_by_ppa)); 1870*9089SVasumathi.Sundaram@Sun.COM if (mdb_pwalk("avl", wsp->walk_callback, wsp->walk_cbdata, 1871*9089SVasumathi.Sundaram@Sun.COM wsp->walk_addr) == -1) { 1872*9089SVasumathi.Sundaram@Sun.COM mdb_warn("can't walk 'avl'"); 1873*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 1874*9089SVasumathi.Sundaram@Sun.COM } 1875*9089SVasumathi.Sundaram@Sun.COM 1876*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 1877*9089SVasumathi.Sundaram@Sun.COM } 1878*9089SVasumathi.Sundaram@Sun.COM 1879*9089SVasumathi.Sundaram@Sun.COM /* ARGSUSED */ 1880*9089SVasumathi.Sundaram@Sun.COM static int 1881*9089SVasumathi.Sundaram@Sun.COM ill_cb(uintptr_t addr, const ill_walk_data_t *iw, ill_cbdata_t *id) 1882*9089SVasumathi.Sundaram@Sun.COM { 1883*9089SVasumathi.Sundaram@Sun.COM ill_t ill; 1884*9089SVasumathi.Sundaram@Sun.COM 1885*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&ill, sizeof (ill_t), (uintptr_t)addr) == -1) { 1886*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read ill at %p", addr); 1887*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 1888*9089SVasumathi.Sundaram@Sun.COM } 1889*9089SVasumathi.Sundaram@Sun.COM return (ill_format((uintptr_t)addr, &ill, id)); 1890*9089SVasumathi.Sundaram@Sun.COM } 1891*9089SVasumathi.Sundaram@Sun.COM 1892*9089SVasumathi.Sundaram@Sun.COM static void 1893*9089SVasumathi.Sundaram@Sun.COM ill_header(boolean_t verbose) 1894*9089SVasumathi.Sundaram@Sun.COM { 1895*9089SVasumathi.Sundaram@Sun.COM if (verbose) { 1896*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?s %-8s %3s %-10s %-?s %-?s %-10s%</u>\n", 1897*9089SVasumathi.Sundaram@Sun.COM "ADDR", "NAME", "VER", "TYPE", "WQ", "IPST", "FLAGS"); 1898*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?s %4s%4s %-?s\n", 1899*9089SVasumathi.Sundaram@Sun.COM "PHYINT", "CNT", "", "GROUP"); 1900*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%<u>%80s%</u>\n", ""); 1901*9089SVasumathi.Sundaram@Sun.COM } else { 1902*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%<u>%-?s %-8s %-3s %-10s %4s %-?s %-10s%</u>\n", 1903*9089SVasumathi.Sundaram@Sun.COM "ADDR", "NAME", "VER", "TYPE", "CNT", "WQ", "FLAGS"); 1904*9089SVasumathi.Sundaram@Sun.COM } 1905*9089SVasumathi.Sundaram@Sun.COM } 1906*9089SVasumathi.Sundaram@Sun.COM 1907*9089SVasumathi.Sundaram@Sun.COM static int 1908*9089SVasumathi.Sundaram@Sun.COM ill_format(uintptr_t addr, const void *illptr, void *ill_cb_arg) 1909*9089SVasumathi.Sundaram@Sun.COM { 1910*9089SVasumathi.Sundaram@Sun.COM ill_t *ill = (ill_t *)illptr; 1911*9089SVasumathi.Sundaram@Sun.COM ill_cbdata_t *illcb = ill_cb_arg; 1912*9089SVasumathi.Sundaram@Sun.COM boolean_t verbose = illcb->verbose; 1913*9089SVasumathi.Sundaram@Sun.COM phyint_t phyi; 1914*9089SVasumathi.Sundaram@Sun.COM static const mdb_bitmask_t fmasks[] = { 1915*9089SVasumathi.Sundaram@Sun.COM { "R", PHYI_RUNNING, PHYI_RUNNING }, 1916*9089SVasumathi.Sundaram@Sun.COM { "P", PHYI_PROMISC, PHYI_PROMISC }, 1917*9089SVasumathi.Sundaram@Sun.COM { "V", PHYI_VIRTUAL, PHYI_VIRTUAL }, 1918*9089SVasumathi.Sundaram@Sun.COM { "I", PHYI_IPMP, PHYI_IPMP }, 1919*9089SVasumathi.Sundaram@Sun.COM { "f", PHYI_FAILED, PHYI_FAILED }, 1920*9089SVasumathi.Sundaram@Sun.COM { "S", PHYI_STANDBY, PHYI_STANDBY }, 1921*9089SVasumathi.Sundaram@Sun.COM { "i", PHYI_INACTIVE, PHYI_INACTIVE }, 1922*9089SVasumathi.Sundaram@Sun.COM { "O", PHYI_OFFLINE, PHYI_OFFLINE }, 1923*9089SVasumathi.Sundaram@Sun.COM { "T", ILLF_NOTRAILERS, ILLF_NOTRAILERS }, 1924*9089SVasumathi.Sundaram@Sun.COM { "A", ILLF_NOARP, ILLF_NOARP }, 1925*9089SVasumathi.Sundaram@Sun.COM { "M", ILLF_MULTICAST, ILLF_MULTICAST }, 1926*9089SVasumathi.Sundaram@Sun.COM { "F", ILLF_ROUTER, ILLF_ROUTER }, 1927*9089SVasumathi.Sundaram@Sun.COM { "D", ILLF_NONUD, ILLF_NONUD }, 1928*9089SVasumathi.Sundaram@Sun.COM { "X", ILLF_NORTEXCH, ILLF_NORTEXCH }, 1929*9089SVasumathi.Sundaram@Sun.COM { NULL, 0, 0 } 1930*9089SVasumathi.Sundaram@Sun.COM }; 1931*9089SVasumathi.Sundaram@Sun.COM static const mdb_bitmask_t v_fmasks[] = { 1932*9089SVasumathi.Sundaram@Sun.COM { "RUNNING", PHYI_RUNNING, PHYI_RUNNING }, 1933*9089SVasumathi.Sundaram@Sun.COM { "PROMISC", PHYI_PROMISC, PHYI_PROMISC }, 1934*9089SVasumathi.Sundaram@Sun.COM { "VIRTUAL", PHYI_VIRTUAL, PHYI_VIRTUAL }, 1935*9089SVasumathi.Sundaram@Sun.COM { "IPMP", PHYI_IPMP, PHYI_IPMP }, 1936*9089SVasumathi.Sundaram@Sun.COM { "FAILED", PHYI_FAILED, PHYI_FAILED }, 1937*9089SVasumathi.Sundaram@Sun.COM { "STANDBY", PHYI_STANDBY, PHYI_STANDBY }, 1938*9089SVasumathi.Sundaram@Sun.COM { "INACTIVE", PHYI_INACTIVE, PHYI_INACTIVE }, 1939*9089SVasumathi.Sundaram@Sun.COM { "OFFLINE", PHYI_OFFLINE, PHYI_OFFLINE }, 1940*9089SVasumathi.Sundaram@Sun.COM { "NOTRAILER", ILLF_NOTRAILERS, ILLF_NOTRAILERS }, 1941*9089SVasumathi.Sundaram@Sun.COM { "NOARP", ILLF_NOARP, ILLF_NOARP }, 1942*9089SVasumathi.Sundaram@Sun.COM { "MULTICAST", ILLF_MULTICAST, ILLF_MULTICAST }, 1943*9089SVasumathi.Sundaram@Sun.COM { "ROUTER", ILLF_ROUTER, ILLF_ROUTER }, 1944*9089SVasumathi.Sundaram@Sun.COM { "NONUD", ILLF_NONUD, ILLF_NONUD }, 1945*9089SVasumathi.Sundaram@Sun.COM { "NORTEXCH", ILLF_NORTEXCH, ILLF_NORTEXCH }, 1946*9089SVasumathi.Sundaram@Sun.COM { NULL, 0, 0 } 1947*9089SVasumathi.Sundaram@Sun.COM }; 1948*9089SVasumathi.Sundaram@Sun.COM char ill_name[LIFNAMSIZ]; 1949*9089SVasumathi.Sundaram@Sun.COM int cnt; 1950*9089SVasumathi.Sundaram@Sun.COM char *typebuf; 1951*9089SVasumathi.Sundaram@Sun.COM char sbuf[DEFCOLS]; 1952*9089SVasumathi.Sundaram@Sun.COM int ipver = illcb->ill_ipversion; 1953*9089SVasumathi.Sundaram@Sun.COM 1954*9089SVasumathi.Sundaram@Sun.COM if (ipver != 0) { 1955*9089SVasumathi.Sundaram@Sun.COM if ((ipver == IPV4_VERSION && ill->ill_isv6) || 1956*9089SVasumathi.Sundaram@Sun.COM (ipver == IPV6_VERSION && !ill->ill_isv6)) { 1957*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 1958*9089SVasumathi.Sundaram@Sun.COM } 1959*9089SVasumathi.Sundaram@Sun.COM } 1960*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&phyi, sizeof (phyint_t), 1961*9089SVasumathi.Sundaram@Sun.COM (uintptr_t)ill->ill_phyint) == -1) { 1962*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read ill_phyint at %p", 1963*9089SVasumathi.Sundaram@Sun.COM (uintptr_t)ill->ill_phyint); 1964*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 1965*9089SVasumathi.Sundaram@Sun.COM } 1966*9089SVasumathi.Sundaram@Sun.COM (void) mdb_readstr(ill_name, MIN(LIFNAMSIZ, ill->ill_name_length), 1967*9089SVasumathi.Sundaram@Sun.COM (uintptr_t)ill->ill_name); 1968*9089SVasumathi.Sundaram@Sun.COM 1969*9089SVasumathi.Sundaram@Sun.COM switch (ill->ill_type) { 1970*9089SVasumathi.Sundaram@Sun.COM case 0: 1971*9089SVasumathi.Sundaram@Sun.COM typebuf = "LOOPBACK"; 1972*9089SVasumathi.Sundaram@Sun.COM break; 1973*9089SVasumathi.Sundaram@Sun.COM case IFT_ETHER: 1974*9089SVasumathi.Sundaram@Sun.COM typebuf = "ETHER"; 1975*9089SVasumathi.Sundaram@Sun.COM break; 1976*9089SVasumathi.Sundaram@Sun.COM case IFT_OTHER: 1977*9089SVasumathi.Sundaram@Sun.COM typebuf = "OTHER"; 1978*9089SVasumathi.Sundaram@Sun.COM break; 1979*9089SVasumathi.Sundaram@Sun.COM default: 1980*9089SVasumathi.Sundaram@Sun.COM typebuf = NULL; 1981*9089SVasumathi.Sundaram@Sun.COM break; 1982*9089SVasumathi.Sundaram@Sun.COM } 1983*9089SVasumathi.Sundaram@Sun.COM cnt = ill->ill_refcnt + ill->ill_ire_cnt + ill->ill_nce_cnt + 1984*9089SVasumathi.Sundaram@Sun.COM ill->ill_ilm_walker_cnt + ill->ill_ilm_cnt; 1985*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?p %-8s %-3s ", 1986*9089SVasumathi.Sundaram@Sun.COM addr, ill_name, ill->ill_isv6 ? "v6" : "v4"); 1987*9089SVasumathi.Sundaram@Sun.COM if (typebuf != NULL) 1988*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-10s ", typebuf); 1989*9089SVasumathi.Sundaram@Sun.COM else 1990*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-10x ", ill->ill_type); 1991*9089SVasumathi.Sundaram@Sun.COM if (verbose) { 1992*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?p %-?p %-llb\n", 1993*9089SVasumathi.Sundaram@Sun.COM ill->ill_wq, ill->ill_ipst, 1994*9089SVasumathi.Sundaram@Sun.COM ill->ill_flags | phyi.phyint_flags, v_fmasks); 1995*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?p %4d%4s %-?p\n", 1996*9089SVasumathi.Sundaram@Sun.COM ill->ill_phyint, cnt, "", ill->ill_grp); 1997*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(sbuf, sizeof (sbuf), "%*s %3s", 1998*9089SVasumathi.Sundaram@Sun.COM sizeof (uintptr_t) * 2, "", ""); 1999*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%s|\n%s+--> %3d %-18s " 2000*9089SVasumathi.Sundaram@Sun.COM "references from active threads\n", 2001*9089SVasumathi.Sundaram@Sun.COM sbuf, sbuf, ill->ill_refcnt, "ill_refcnt"); 2002*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%*s %7d %-18s ires referencing this ill\n", 2003*9089SVasumathi.Sundaram@Sun.COM strlen(sbuf), "", ill->ill_ire_cnt, "ill_ire_cnt"); 2004*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%*s %7d %-18s nces referencing this ill\n", 2005*9089SVasumathi.Sundaram@Sun.COM strlen(sbuf), "", ill->ill_nce_cnt, "ill_nce_cnt"); 2006*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%*s %7d %-18s ilms referencing this ill\n", 2007*9089SVasumathi.Sundaram@Sun.COM strlen(sbuf), "", ill->ill_ilm_cnt, "ill_ilm_cnt"); 2008*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%*s %7d %-18s active ilm walkers\n\n", 2009*9089SVasumathi.Sundaram@Sun.COM strlen(sbuf), "", ill->ill_ilm_walker_cnt, 2010*9089SVasumathi.Sundaram@Sun.COM "ill_ilm_walker_cnt"); 2011*9089SVasumathi.Sundaram@Sun.COM } else { 2012*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%4d %-?p %-llb\n", 2013*9089SVasumathi.Sundaram@Sun.COM cnt, ill->ill_wq, 2014*9089SVasumathi.Sundaram@Sun.COM ill->ill_flags | phyi.phyint_flags, fmasks); 2015*9089SVasumathi.Sundaram@Sun.COM } 2016*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2017*9089SVasumathi.Sundaram@Sun.COM } 2018*9089SVasumathi.Sundaram@Sun.COM 2019*9089SVasumathi.Sundaram@Sun.COM static int 2020*9089SVasumathi.Sundaram@Sun.COM ill(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2021*9089SVasumathi.Sundaram@Sun.COM { 2022*9089SVasumathi.Sundaram@Sun.COM ill_t ill_data; 2023*9089SVasumathi.Sundaram@Sun.COM ill_cbdata_t id; 2024*9089SVasumathi.Sundaram@Sun.COM int ipversion = 0; 2025*9089SVasumathi.Sundaram@Sun.COM const char *opt_P = NULL; 2026*9089SVasumathi.Sundaram@Sun.COM uint_t verbose = FALSE; 2027*9089SVasumathi.Sundaram@Sun.COM 2028*9089SVasumathi.Sundaram@Sun.COM if (mdb_getopts(argc, argv, 2029*9089SVasumathi.Sundaram@Sun.COM 'v', MDB_OPT_SETBITS, TRUE, &verbose, 2030*9089SVasumathi.Sundaram@Sun.COM 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 2031*9089SVasumathi.Sundaram@Sun.COM return (DCMD_USAGE); 2032*9089SVasumathi.Sundaram@Sun.COM 2033*9089SVasumathi.Sundaram@Sun.COM if (opt_P != NULL) { 2034*9089SVasumathi.Sundaram@Sun.COM if (strcmp("v4", opt_P) == 0) { 2035*9089SVasumathi.Sundaram@Sun.COM ipversion = IPV4_VERSION; 2036*9089SVasumathi.Sundaram@Sun.COM } else if (strcmp("v6", opt_P) == 0) { 2037*9089SVasumathi.Sundaram@Sun.COM ipversion = IPV6_VERSION; 2038*9089SVasumathi.Sundaram@Sun.COM } else { 2039*9089SVasumathi.Sundaram@Sun.COM mdb_warn("invalid protocol '%s'\n", opt_P); 2040*9089SVasumathi.Sundaram@Sun.COM return (DCMD_USAGE); 2041*9089SVasumathi.Sundaram@Sun.COM } 2042*9089SVasumathi.Sundaram@Sun.COM } 2043*9089SVasumathi.Sundaram@Sun.COM 2044*9089SVasumathi.Sundaram@Sun.COM id.verbose = verbose; 2045*9089SVasumathi.Sundaram@Sun.COM id.ill_addr = addr; 2046*9089SVasumathi.Sundaram@Sun.COM id.ill_ipversion = ipversion; 2047*9089SVasumathi.Sundaram@Sun.COM 2048*9089SVasumathi.Sundaram@Sun.COM ill_header(verbose); 2049*9089SVasumathi.Sundaram@Sun.COM if (flags & DCMD_ADDRSPEC) { 2050*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&ill_data, sizeof (ill_t), addr) == -1) { 2051*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read ill at %p\n", addr); 2052*9089SVasumathi.Sundaram@Sun.COM return (DCMD_ERR); 2053*9089SVasumathi.Sundaram@Sun.COM } 2054*9089SVasumathi.Sundaram@Sun.COM (void) ill_format(addr, &ill_data, &id); 2055*9089SVasumathi.Sundaram@Sun.COM } else { 2056*9089SVasumathi.Sundaram@Sun.COM if (mdb_walk("ill", (mdb_walk_cb_t)ill_cb, &id) == -1) { 2057*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to walk ills\n"); 2058*9089SVasumathi.Sundaram@Sun.COM return (DCMD_ERR); 2059*9089SVasumathi.Sundaram@Sun.COM } 2060*9089SVasumathi.Sundaram@Sun.COM } 2061*9089SVasumathi.Sundaram@Sun.COM return (DCMD_OK); 2062*9089SVasumathi.Sundaram@Sun.COM } 2063*9089SVasumathi.Sundaram@Sun.COM 2064*9089SVasumathi.Sundaram@Sun.COM static void 2065*9089SVasumathi.Sundaram@Sun.COM ill_help(void) 2066*9089SVasumathi.Sundaram@Sun.COM { 2067*9089SVasumathi.Sundaram@Sun.COM mdb_printf("Prints the following fields: ill ptr, name, " 2068*9089SVasumathi.Sundaram@Sun.COM "IP version, count, ill type and ill flags.\n" 2069*9089SVasumathi.Sundaram@Sun.COM "The count field is a sum of individual refcnts and is expanded " 2070*9089SVasumathi.Sundaram@Sun.COM "with the -v option.\n\n"); 2071*9089SVasumathi.Sundaram@Sun.COM mdb_printf("Options:\n"); 2072*9089SVasumathi.Sundaram@Sun.COM mdb_printf("\t-P v4 | v6" 2073*9089SVasumathi.Sundaram@Sun.COM "\tfilter ill structures for the specified protocol\n"); 2074*9089SVasumathi.Sundaram@Sun.COM } 2075*9089SVasumathi.Sundaram@Sun.COM 2076*9089SVasumathi.Sundaram@Sun.COM static int 2077*9089SVasumathi.Sundaram@Sun.COM ip_list_walk_init(mdb_walk_state_t *wsp) 2078*9089SVasumathi.Sundaram@Sun.COM { 2079*9089SVasumathi.Sundaram@Sun.COM const ip_list_walk_arg_t *arg = wsp->walk_arg; 2080*9089SVasumathi.Sundaram@Sun.COM ip_list_walk_data_t *iw; 2081*9089SVasumathi.Sundaram@Sun.COM uintptr_t addr = (uintptr_t)(wsp->walk_addr + arg->off); 2082*9089SVasumathi.Sundaram@Sun.COM 2083*9089SVasumathi.Sundaram@Sun.COM if (wsp->walk_addr == NULL) { 2084*9089SVasumathi.Sundaram@Sun.COM mdb_warn("only local walks supported\n"); 2085*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 2086*9089SVasumathi.Sundaram@Sun.COM } 2087*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t), 2088*9089SVasumathi.Sundaram@Sun.COM addr) == -1) { 2089*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read list head at %p", addr); 2090*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 2091*9089SVasumathi.Sundaram@Sun.COM } 2092*9089SVasumathi.Sundaram@Sun.COM iw = mdb_alloc(sizeof (ip_list_walk_data_t), UM_SLEEP); 2093*9089SVasumathi.Sundaram@Sun.COM iw->nextoff = arg->nextp_off; 2094*9089SVasumathi.Sundaram@Sun.COM wsp->walk_data = iw; 2095*9089SVasumathi.Sundaram@Sun.COM 2096*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2097*9089SVasumathi.Sundaram@Sun.COM } 2098*9089SVasumathi.Sundaram@Sun.COM 2099*9089SVasumathi.Sundaram@Sun.COM static int 2100*9089SVasumathi.Sundaram@Sun.COM ip_list_walk_step(mdb_walk_state_t *wsp) 2101*9089SVasumathi.Sundaram@Sun.COM { 2102*9089SVasumathi.Sundaram@Sun.COM ip_list_walk_data_t *iw = wsp->walk_data; 2103*9089SVasumathi.Sundaram@Sun.COM uintptr_t addr = wsp->walk_addr; 2104*9089SVasumathi.Sundaram@Sun.COM 2105*9089SVasumathi.Sundaram@Sun.COM if (addr == NULL) 2106*9089SVasumathi.Sundaram@Sun.COM return (WALK_DONE); 2107*9089SVasumathi.Sundaram@Sun.COM wsp->walk_addr = addr + iw->nextoff; 2108*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t), 2109*9089SVasumathi.Sundaram@Sun.COM wsp->walk_addr) == -1) { 2110*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read list node at %p", addr); 2111*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 2112*9089SVasumathi.Sundaram@Sun.COM } 2113*9089SVasumathi.Sundaram@Sun.COM return (wsp->walk_callback(addr, iw, wsp->walk_cbdata)); 2114*9089SVasumathi.Sundaram@Sun.COM } 2115*9089SVasumathi.Sundaram@Sun.COM 2116*9089SVasumathi.Sundaram@Sun.COM static void 2117*9089SVasumathi.Sundaram@Sun.COM ip_list_walk_fini(mdb_walk_state_t *wsp) 2118*9089SVasumathi.Sundaram@Sun.COM { 2119*9089SVasumathi.Sundaram@Sun.COM mdb_free(wsp->walk_data, sizeof (ip_list_walk_data_t)); 2120*9089SVasumathi.Sundaram@Sun.COM } 2121*9089SVasumathi.Sundaram@Sun.COM 2122*9089SVasumathi.Sundaram@Sun.COM static int 2123*9089SVasumathi.Sundaram@Sun.COM ipif_walk_init(mdb_walk_state_t *wsp) 2124*9089SVasumathi.Sundaram@Sun.COM { 2125*9089SVasumathi.Sundaram@Sun.COM if (mdb_layered_walk("ill", wsp) == -1) { 2126*9089SVasumathi.Sundaram@Sun.COM mdb_warn("can't walk 'ills'"); 2127*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 2128*9089SVasumathi.Sundaram@Sun.COM } 2129*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2130*9089SVasumathi.Sundaram@Sun.COM } 2131*9089SVasumathi.Sundaram@Sun.COM 2132*9089SVasumathi.Sundaram@Sun.COM static int 2133*9089SVasumathi.Sundaram@Sun.COM ipif_walk_step(mdb_walk_state_t *wsp) 2134*9089SVasumathi.Sundaram@Sun.COM { 2135*9089SVasumathi.Sundaram@Sun.COM if (mdb_pwalk("ipif_list", wsp->walk_callback, wsp->walk_cbdata, 2136*9089SVasumathi.Sundaram@Sun.COM wsp->walk_addr) == -1) { 2137*9089SVasumathi.Sundaram@Sun.COM mdb_warn("can't walk 'ipif_list'"); 2138*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 2139*9089SVasumathi.Sundaram@Sun.COM } 2140*9089SVasumathi.Sundaram@Sun.COM 2141*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2142*9089SVasumathi.Sundaram@Sun.COM } 2143*9089SVasumathi.Sundaram@Sun.COM 2144*9089SVasumathi.Sundaram@Sun.COM /* ARGSUSED */ 2145*9089SVasumathi.Sundaram@Sun.COM static int 2146*9089SVasumathi.Sundaram@Sun.COM ipif_cb(uintptr_t addr, const ipif_walk_data_t *iw, ipif_cbdata_t *id) 2147*9089SVasumathi.Sundaram@Sun.COM { 2148*9089SVasumathi.Sundaram@Sun.COM ipif_t ipif; 2149*9089SVasumathi.Sundaram@Sun.COM 2150*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&ipif, sizeof (ipif_t), (uintptr_t)addr) == -1) { 2151*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read ipif at %p", addr); 2152*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2153*9089SVasumathi.Sundaram@Sun.COM } 2154*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&id->ill, sizeof (ill_t), 2155*9089SVasumathi.Sundaram@Sun.COM (uintptr_t)ipif.ipif_ill) == -1) { 2156*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read ill at %p", ipif.ipif_ill); 2157*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2158*9089SVasumathi.Sundaram@Sun.COM } 2159*9089SVasumathi.Sundaram@Sun.COM (void) ipif_format((uintptr_t)addr, &ipif, id); 2160*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2161*9089SVasumathi.Sundaram@Sun.COM } 2162*9089SVasumathi.Sundaram@Sun.COM 2163*9089SVasumathi.Sundaram@Sun.COM static void 2164*9089SVasumathi.Sundaram@Sun.COM ipif_header(boolean_t verbose) 2165*9089SVasumathi.Sundaram@Sun.COM { 2166*9089SVasumathi.Sundaram@Sun.COM if (verbose) { 2167*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?s %-10s %-3s %-?s %-8s %-30s\n", 2168*9089SVasumathi.Sundaram@Sun.COM "ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS"); 2169*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%s\n%s\n", 2170*9089SVasumathi.Sundaram@Sun.COM "LCLADDR", "BROADCAST"); 2171*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%<u>%80s%</u>\n", ""); 2172*9089SVasumathi.Sundaram@Sun.COM } else { 2173*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?s %-10s %6s %-?s %-8s %-30s\n", 2174*9089SVasumathi.Sundaram@Sun.COM "ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS"); 2175*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%s\n%<u>%80s%</u>\n", "LCLADDR", ""); 2176*9089SVasumathi.Sundaram@Sun.COM } 2177*9089SVasumathi.Sundaram@Sun.COM } 2178*9089SVasumathi.Sundaram@Sun.COM 2179*9089SVasumathi.Sundaram@Sun.COM #ifdef _BIG_ENDIAN 2180*9089SVasumathi.Sundaram@Sun.COM #define ip_ntohl_32(x) ((x) & 0xffffffff) 2181*9089SVasumathi.Sundaram@Sun.COM #else 2182*9089SVasumathi.Sundaram@Sun.COM #define ip_ntohl_32(x) (((uint32_t)(x) << 24) | \ 2183*9089SVasumathi.Sundaram@Sun.COM (((uint32_t)(x) << 8) & 0xff0000) | \ 2184*9089SVasumathi.Sundaram@Sun.COM (((uint32_t)(x) >> 8) & 0xff00) | \ 2185*9089SVasumathi.Sundaram@Sun.COM ((uint32_t)(x) >> 24)) 2186*9089SVasumathi.Sundaram@Sun.COM #endif 2187*9089SVasumathi.Sundaram@Sun.COM 2188*9089SVasumathi.Sundaram@Sun.COM int 2189*9089SVasumathi.Sundaram@Sun.COM mask_to_prefixlen(int af, const in6_addr_t *addr) 2190*9089SVasumathi.Sundaram@Sun.COM { 2191*9089SVasumathi.Sundaram@Sun.COM int len = 0; 2192*9089SVasumathi.Sundaram@Sun.COM int i; 2193*9089SVasumathi.Sundaram@Sun.COM uint_t mask = 0; 2194*9089SVasumathi.Sundaram@Sun.COM 2195*9089SVasumathi.Sundaram@Sun.COM if (af == AF_INET6) { 2196*9089SVasumathi.Sundaram@Sun.COM for (i = 0; i < 4; i++) { 2197*9089SVasumathi.Sundaram@Sun.COM if (addr->s6_addr32[i] == 0xffffffff) { 2198*9089SVasumathi.Sundaram@Sun.COM len += 32; 2199*9089SVasumathi.Sundaram@Sun.COM } else { 2200*9089SVasumathi.Sundaram@Sun.COM mask = addr->s6_addr32[i]; 2201*9089SVasumathi.Sundaram@Sun.COM break; 2202*9089SVasumathi.Sundaram@Sun.COM } 2203*9089SVasumathi.Sundaram@Sun.COM } 2204*9089SVasumathi.Sundaram@Sun.COM } else { 2205*9089SVasumathi.Sundaram@Sun.COM mask = V4_PART_OF_V6((*addr)); 2206*9089SVasumathi.Sundaram@Sun.COM } 2207*9089SVasumathi.Sundaram@Sun.COM if (mask > 0) 2208*9089SVasumathi.Sundaram@Sun.COM len += (33 - mdb_ffs(ip_ntohl_32(mask))); 2209*9089SVasumathi.Sundaram@Sun.COM return (len); 2210*9089SVasumathi.Sundaram@Sun.COM } 2211*9089SVasumathi.Sundaram@Sun.COM 2212*9089SVasumathi.Sundaram@Sun.COM static int 2213*9089SVasumathi.Sundaram@Sun.COM ipif_format(uintptr_t addr, const void *ipifptr, void *ipif_cb_arg) 2214*9089SVasumathi.Sundaram@Sun.COM { 2215*9089SVasumathi.Sundaram@Sun.COM const ipif_t *ipif = ipifptr; 2216*9089SVasumathi.Sundaram@Sun.COM ipif_cbdata_t *ipifcb = ipif_cb_arg; 2217*9089SVasumathi.Sundaram@Sun.COM boolean_t verbose = ipifcb->verbose; 2218*9089SVasumathi.Sundaram@Sun.COM char ill_name[LIFNAMSIZ]; 2219*9089SVasumathi.Sundaram@Sun.COM char buf[LIFNAMSIZ]; 2220*9089SVasumathi.Sundaram@Sun.COM int cnt; 2221*9089SVasumathi.Sundaram@Sun.COM static const mdb_bitmask_t sfmasks[] = { 2222*9089SVasumathi.Sundaram@Sun.COM { "CO", IPIF_CONDEMNED, IPIF_CONDEMNED}, 2223*9089SVasumathi.Sundaram@Sun.COM { "CH", IPIF_CHANGING, IPIF_CHANGING}, 2224*9089SVasumathi.Sundaram@Sun.COM { "SL", IPIF_SET_LINKLOCAL, IPIF_SET_LINKLOCAL}, 2225*9089SVasumathi.Sundaram@Sun.COM { "ZS", IPIF_ZERO_SOURCE, IPIF_ZERO_SOURCE}, 2226*9089SVasumathi.Sundaram@Sun.COM { NULL, 0, 0 } 2227*9089SVasumathi.Sundaram@Sun.COM }; 2228*9089SVasumathi.Sundaram@Sun.COM static const mdb_bitmask_t fmasks[] = { 2229*9089SVasumathi.Sundaram@Sun.COM { "UP", IPIF_UP, IPIF_UP }, 2230*9089SVasumathi.Sundaram@Sun.COM { "UNN", IPIF_UNNUMBERED, IPIF_UNNUMBERED}, 2231*9089SVasumathi.Sundaram@Sun.COM { "DHCP", IPIF_DHCPRUNNING, IPIF_DHCPRUNNING}, 2232*9089SVasumathi.Sundaram@Sun.COM { "PRIV", IPIF_PRIVATE, IPIF_PRIVATE}, 2233*9089SVasumathi.Sundaram@Sun.COM { "NOXMT", IPIF_NOXMIT, IPIF_NOXMIT}, 2234*9089SVasumathi.Sundaram@Sun.COM { "NOLCL", IPIF_NOLOCAL, IPIF_NOLOCAL}, 2235*9089SVasumathi.Sundaram@Sun.COM { "DEPR", IPIF_DEPRECATED, IPIF_DEPRECATED}, 2236*9089SVasumathi.Sundaram@Sun.COM { "PREF", IPIF_PREFERRED, IPIF_PREFERRED}, 2237*9089SVasumathi.Sundaram@Sun.COM { "TEMP", IPIF_TEMPORARY, IPIF_TEMPORARY}, 2238*9089SVasumathi.Sundaram@Sun.COM { "ACONF", IPIF_ADDRCONF, IPIF_ADDRCONF}, 2239*9089SVasumathi.Sundaram@Sun.COM { "ANY", IPIF_ANYCAST, IPIF_ANYCAST}, 2240*9089SVasumathi.Sundaram@Sun.COM { "NFAIL", IPIF_NOFAILOVER, IPIF_NOFAILOVER}, 2241*9089SVasumathi.Sundaram@Sun.COM { NULL, 0, 0 } 2242*9089SVasumathi.Sundaram@Sun.COM }; 2243*9089SVasumathi.Sundaram@Sun.COM char flagsbuf[2 * A_CNT(fmasks)]; 2244*9089SVasumathi.Sundaram@Sun.COM char bitfields[A_CNT(fmasks)]; 2245*9089SVasumathi.Sundaram@Sun.COM char sflagsbuf[A_CNT(sfmasks)]; 2246*9089SVasumathi.Sundaram@Sun.COM char sbuf[DEFCOLS], addrstr[INET6_ADDRSTRLEN]; 2247*9089SVasumathi.Sundaram@Sun.COM int ipver = ipifcb->ipif_ipversion; 2248*9089SVasumathi.Sundaram@Sun.COM int af; 2249*9089SVasumathi.Sundaram@Sun.COM 2250*9089SVasumathi.Sundaram@Sun.COM if (ipver != 0) { 2251*9089SVasumathi.Sundaram@Sun.COM if ((ipver == IPV4_VERSION && ipifcb->ill.ill_isv6) || 2252*9089SVasumathi.Sundaram@Sun.COM (ipver == IPV6_VERSION && !ipifcb->ill.ill_isv6)) { 2253*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2254*9089SVasumathi.Sundaram@Sun.COM } 2255*9089SVasumathi.Sundaram@Sun.COM } 2256*9089SVasumathi.Sundaram@Sun.COM if ((mdb_readstr(ill_name, MIN(LIFNAMSIZ, 2257*9089SVasumathi.Sundaram@Sun.COM ipifcb->ill.ill_name_length), 2258*9089SVasumathi.Sundaram@Sun.COM (uintptr_t)ipifcb->ill.ill_name)) == -1) { 2259*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read ill_name of ill %p\n", ipifcb->ill); 2260*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2261*9089SVasumathi.Sundaram@Sun.COM } 2262*9089SVasumathi.Sundaram@Sun.COM if (ipif->ipif_id != 0) { 2263*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(buf, LIFNAMSIZ, "%s:%d", 2264*9089SVasumathi.Sundaram@Sun.COM ill_name, ipif->ipif_id); 2265*9089SVasumathi.Sundaram@Sun.COM } else { 2266*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(buf, LIFNAMSIZ, "%s", ill_name); 2267*9089SVasumathi.Sundaram@Sun.COM } 2268*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(bitfields, sizeof (bitfields), "%s", 2269*9089SVasumathi.Sundaram@Sun.COM ipif->ipif_addr_ready ? ",ADR" : "", 2270*9089SVasumathi.Sundaram@Sun.COM ipif->ipif_multicast_up ? ",MU" : "", 2271*9089SVasumathi.Sundaram@Sun.COM ipif->ipif_was_up ? ",WU" : "", 2272*9089SVasumathi.Sundaram@Sun.COM ipif->ipif_was_dup ? ",WD" : "", 2273*9089SVasumathi.Sundaram@Sun.COM ipif->ipif_joined_allhosts ? ",JA" : ""); 2274*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%llb%s", 2275*9089SVasumathi.Sundaram@Sun.COM ipif->ipif_flags, fmasks, bitfields); 2276*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(sflagsbuf, sizeof (sflagsbuf), "%b", 2277*9089SVasumathi.Sundaram@Sun.COM ipif->ipif_state_flags, sfmasks); 2278*9089SVasumathi.Sundaram@Sun.COM 2279*9089SVasumathi.Sundaram@Sun.COM cnt = ipif->ipif_refcnt + ipif->ipif_ire_cnt + ipif->ipif_ilm_cnt; 2280*9089SVasumathi.Sundaram@Sun.COM 2281*9089SVasumathi.Sundaram@Sun.COM if (ipifcb->ill.ill_isv6) { 2282*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(addrstr, sizeof (addrstr), "%N", 2283*9089SVasumathi.Sundaram@Sun.COM &ipif->ipif_v6lcl_addr); 2284*9089SVasumathi.Sundaram@Sun.COM af = AF_INET6; 2285*9089SVasumathi.Sundaram@Sun.COM } else { 2286*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(addrstr, sizeof (addrstr), "%I", 2287*9089SVasumathi.Sundaram@Sun.COM V4_PART_OF_V6((ipif->ipif_v6lcl_addr))); 2288*9089SVasumathi.Sundaram@Sun.COM af = AF_INET; 2289*9089SVasumathi.Sundaram@Sun.COM } 2290*9089SVasumathi.Sundaram@Sun.COM 2291*9089SVasumathi.Sundaram@Sun.COM if (verbose) { 2292*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?p %-10s %3d %-?p %-8s %-30s\n", 2293*9089SVasumathi.Sundaram@Sun.COM addr, buf, cnt, ipif->ipif_ill, 2294*9089SVasumathi.Sundaram@Sun.COM sflagsbuf, flagsbuf); 2295*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(sbuf, sizeof (sbuf), "%*s %12s", 2296*9089SVasumathi.Sundaram@Sun.COM sizeof (uintptr_t) * 2, "", ""); 2297*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%s |\n%s +---> %4d %-15s " 2298*9089SVasumathi.Sundaram@Sun.COM "Active consistent reader cnt\n", 2299*9089SVasumathi.Sundaram@Sun.COM sbuf, sbuf, ipif->ipif_refcnt, "ipif_refcnt"); 2300*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%*s %10d %-15s " 2301*9089SVasumathi.Sundaram@Sun.COM "Number of ire's referencing this ipif\n", 2302*9089SVasumathi.Sundaram@Sun.COM strlen(sbuf), "", ipif->ipif_ire_cnt, "ipif_ire_cnt"); 2303*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%*s %10d %-15s " 2304*9089SVasumathi.Sundaram@Sun.COM "Number of ilm's referencing this ipif\n\n", 2305*9089SVasumathi.Sundaram@Sun.COM strlen(sbuf), "", ipif->ipif_ilm_cnt, "ipif_ilm_cnt"); 2306*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-s/%d\n", 2307*9089SVasumathi.Sundaram@Sun.COM addrstr, mask_to_prefixlen(af, &ipif->ipif_v6net_mask)); 2308*9089SVasumathi.Sundaram@Sun.COM if (ipifcb->ill.ill_isv6) { 2309*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-N\n", &ipif->ipif_v6brd_addr); 2310*9089SVasumathi.Sundaram@Sun.COM } else { 2311*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-I\n", 2312*9089SVasumathi.Sundaram@Sun.COM V4_PART_OF_V6((ipif->ipif_v6brd_addr))); 2313*9089SVasumathi.Sundaram@Sun.COM } 2314*9089SVasumathi.Sundaram@Sun.COM } else { 2315*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?p %-10s %6d %-?p %-8s %-30s\n", 2316*9089SVasumathi.Sundaram@Sun.COM addr, buf, cnt, ipif->ipif_ill, 2317*9089SVasumathi.Sundaram@Sun.COM sflagsbuf, flagsbuf); 2318*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-s/%d\n", 2319*9089SVasumathi.Sundaram@Sun.COM addrstr, mask_to_prefixlen(af, &ipif->ipif_v6net_mask)); 2320*9089SVasumathi.Sundaram@Sun.COM } 2321*9089SVasumathi.Sundaram@Sun.COM 2322*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2323*9089SVasumathi.Sundaram@Sun.COM } 2324*9089SVasumathi.Sundaram@Sun.COM 2325*9089SVasumathi.Sundaram@Sun.COM static int 2326*9089SVasumathi.Sundaram@Sun.COM ipif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2327*9089SVasumathi.Sundaram@Sun.COM { 2328*9089SVasumathi.Sundaram@Sun.COM ipif_t ipif; 2329*9089SVasumathi.Sundaram@Sun.COM ipif_cbdata_t id; 2330*9089SVasumathi.Sundaram@Sun.COM int ipversion = 0; 2331*9089SVasumathi.Sundaram@Sun.COM const char *opt_P = NULL; 2332*9089SVasumathi.Sundaram@Sun.COM uint_t verbose = FALSE; 2333*9089SVasumathi.Sundaram@Sun.COM 2334*9089SVasumathi.Sundaram@Sun.COM if (mdb_getopts(argc, argv, 2335*9089SVasumathi.Sundaram@Sun.COM 'v', MDB_OPT_SETBITS, TRUE, &verbose, 2336*9089SVasumathi.Sundaram@Sun.COM 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 2337*9089SVasumathi.Sundaram@Sun.COM return (DCMD_USAGE); 2338*9089SVasumathi.Sundaram@Sun.COM 2339*9089SVasumathi.Sundaram@Sun.COM if (opt_P != NULL) { 2340*9089SVasumathi.Sundaram@Sun.COM if (strcmp("v4", opt_P) == 0) { 2341*9089SVasumathi.Sundaram@Sun.COM ipversion = IPV4_VERSION; 2342*9089SVasumathi.Sundaram@Sun.COM } else if (strcmp("v6", opt_P) == 0) { 2343*9089SVasumathi.Sundaram@Sun.COM ipversion = IPV6_VERSION; 2344*9089SVasumathi.Sundaram@Sun.COM } else { 2345*9089SVasumathi.Sundaram@Sun.COM mdb_warn("invalid protocol '%s'\n", opt_P); 2346*9089SVasumathi.Sundaram@Sun.COM return (DCMD_USAGE); 2347*9089SVasumathi.Sundaram@Sun.COM } 2348*9089SVasumathi.Sundaram@Sun.COM } 2349*9089SVasumathi.Sundaram@Sun.COM 2350*9089SVasumathi.Sundaram@Sun.COM id.verbose = verbose; 2351*9089SVasumathi.Sundaram@Sun.COM id.ipif_ipversion = ipversion; 2352*9089SVasumathi.Sundaram@Sun.COM 2353*9089SVasumathi.Sundaram@Sun.COM if (flags & DCMD_ADDRSPEC) { 2354*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&ipif, sizeof (ipif_t), addr) == -1) { 2355*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read ipif at %p\n", addr); 2356*9089SVasumathi.Sundaram@Sun.COM return (DCMD_ERR); 2357*9089SVasumathi.Sundaram@Sun.COM } 2358*9089SVasumathi.Sundaram@Sun.COM ipif_header(verbose); 2359*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&id.ill, sizeof (ill_t), 2360*9089SVasumathi.Sundaram@Sun.COM (uintptr_t)ipif.ipif_ill) == -1) { 2361*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read ill at %p", ipif.ipif_ill); 2362*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2363*9089SVasumathi.Sundaram@Sun.COM } 2364*9089SVasumathi.Sundaram@Sun.COM return (ipif_format(addr, &ipif, &id)); 2365*9089SVasumathi.Sundaram@Sun.COM } else { 2366*9089SVasumathi.Sundaram@Sun.COM ipif_header(verbose); 2367*9089SVasumathi.Sundaram@Sun.COM if (mdb_walk("ipif", (mdb_walk_cb_t)ipif_cb, &id) == -1) { 2368*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to walk ipifs\n"); 2369*9089SVasumathi.Sundaram@Sun.COM return (DCMD_ERR); 2370*9089SVasumathi.Sundaram@Sun.COM } 2371*9089SVasumathi.Sundaram@Sun.COM } 2372*9089SVasumathi.Sundaram@Sun.COM return (DCMD_OK); 2373*9089SVasumathi.Sundaram@Sun.COM } 2374*9089SVasumathi.Sundaram@Sun.COM 2375*9089SVasumathi.Sundaram@Sun.COM static void 2376*9089SVasumathi.Sundaram@Sun.COM ipif_help(void) 2377*9089SVasumathi.Sundaram@Sun.COM { 2378*9089SVasumathi.Sundaram@Sun.COM mdb_printf("Prints the following fields: ipif ptr, name, " 2379*9089SVasumathi.Sundaram@Sun.COM "count, ill ptr, state flags and ipif flags.\n" 2380*9089SVasumathi.Sundaram@Sun.COM "The count field is a sum of individual refcnts and is expanded " 2381*9089SVasumathi.Sundaram@Sun.COM "with the -v option.\n" 2382*9089SVasumathi.Sundaram@Sun.COM "The flags field shows the following:" 2383*9089SVasumathi.Sundaram@Sun.COM "\n\tUNN -> UNNUMBERED, DHCP -> DHCPRUNNING, PRIV -> PRIVATE, " 2384*9089SVasumathi.Sundaram@Sun.COM "\n\tNOXMT -> NOXMIT, NOLCL -> NOLOCAL, DEPR -> DEPRECATED, " 2385*9089SVasumathi.Sundaram@Sun.COM "\n\tPREF -> PREFERRED, TEMP -> TEMPORARY, ACONF -> ADDRCONF, " 2386*9089SVasumathi.Sundaram@Sun.COM "\n\tANY -> ANYCAST, NFAIL -> NOFAILOVER, " 2387*9089SVasumathi.Sundaram@Sun.COM "\n\tADR -> ipif_addr_ready, MU -> ipif_multicast_up, " 2388*9089SVasumathi.Sundaram@Sun.COM "\n\tWU -> ipif_was_up, WD -> ipif_was_dup, " 2389*9089SVasumathi.Sundaram@Sun.COM "JA -> ipif_joined_allhosts.\n\n"); 2390*9089SVasumathi.Sundaram@Sun.COM mdb_printf("Options:\n"); 2391*9089SVasumathi.Sundaram@Sun.COM mdb_printf("\t-P v4 | v6" 2392*9089SVasumathi.Sundaram@Sun.COM "\tfilter ipif structures on ills for the specified protocol\n"); 2393*9089SVasumathi.Sundaram@Sun.COM } 2394*9089SVasumathi.Sundaram@Sun.COM 2395*9089SVasumathi.Sundaram@Sun.COM static int 2396*9089SVasumathi.Sundaram@Sun.COM conn_status_walk_fanout(uintptr_t addr, mdb_walk_state_t *wsp, 2397*9089SVasumathi.Sundaram@Sun.COM const char *walkname) 2398*9089SVasumathi.Sundaram@Sun.COM { 2399*9089SVasumathi.Sundaram@Sun.COM if (mdb_pwalk(walkname, wsp->walk_callback, wsp->walk_cbdata, 2400*9089SVasumathi.Sundaram@Sun.COM addr) == -1) { 2401*9089SVasumathi.Sundaram@Sun.COM mdb_warn("couldn't walk '%s' at %p", walkname, addr); 2402*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 2403*9089SVasumathi.Sundaram@Sun.COM } 2404*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2405*9089SVasumathi.Sundaram@Sun.COM } 2406*9089SVasumathi.Sundaram@Sun.COM 2407*9089SVasumathi.Sundaram@Sun.COM static int 2408*9089SVasumathi.Sundaram@Sun.COM conn_status_walk_step(mdb_walk_state_t *wsp) 2409*9089SVasumathi.Sundaram@Sun.COM { 2410*9089SVasumathi.Sundaram@Sun.COM uintptr_t addr = wsp->walk_addr; 2411*9089SVasumathi.Sundaram@Sun.COM 2412*9089SVasumathi.Sundaram@Sun.COM (void) conn_status_walk_fanout(addr, wsp, "udp_hash"); 2413*9089SVasumathi.Sundaram@Sun.COM (void) conn_status_walk_fanout(addr, wsp, "conn_hash"); 2414*9089SVasumathi.Sundaram@Sun.COM (void) conn_status_walk_fanout(addr, wsp, "bind_hash"); 2415*9089SVasumathi.Sundaram@Sun.COM (void) conn_status_walk_fanout(addr, wsp, "proto_hash"); 2416*9089SVasumathi.Sundaram@Sun.COM (void) conn_status_walk_fanout(addr, wsp, "proto_v6_hash"); 2417*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2418*9089SVasumathi.Sundaram@Sun.COM } 2419*9089SVasumathi.Sundaram@Sun.COM 2420*9089SVasumathi.Sundaram@Sun.COM /* ARGSUSED */ 2421*9089SVasumathi.Sundaram@Sun.COM static int 2422*9089SVasumathi.Sundaram@Sun.COM conn_status_cb(uintptr_t addr, const void *walk_data, 2423*9089SVasumathi.Sundaram@Sun.COM void *private) 2424*9089SVasumathi.Sundaram@Sun.COM { 2425*9089SVasumathi.Sundaram@Sun.COM netstack_t nss; 2426*9089SVasumathi.Sundaram@Sun.COM char src_addrstr[INET6_ADDRSTRLEN]; 2427*9089SVasumathi.Sundaram@Sun.COM char rem_addrstr[INET6_ADDRSTRLEN]; 2428*9089SVasumathi.Sundaram@Sun.COM const ipcl_hash_walk_data_t *iw = walk_data; 2429*9089SVasumathi.Sundaram@Sun.COM conn_t *conn = iw->conn; 2430*9089SVasumathi.Sundaram@Sun.COM 2431*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(conn, sizeof (conn_t), addr) == -1) { 2432*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read conn_t at %p", addr); 2433*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 2434*9089SVasumathi.Sundaram@Sun.COM } 2435*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&nss, sizeof (nss), 2436*9089SVasumathi.Sundaram@Sun.COM (uintptr_t)conn->conn_netstack) == -1) { 2437*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read netstack_t %p", 2438*9089SVasumathi.Sundaram@Sun.COM conn->conn_netstack); 2439*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 2440*9089SVasumathi.Sundaram@Sun.COM } 2441*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?p %-?p %?d %?d\n", addr, conn->conn_wq, 2442*9089SVasumathi.Sundaram@Sun.COM nss.netstack_stackid, conn->conn_zoneid); 2443*9089SVasumathi.Sundaram@Sun.COM 2444*9089SVasumathi.Sundaram@Sun.COM if (conn->conn_af_isv6) { 2445*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(src_addrstr, sizeof (rem_addrstr), "%N", 2446*9089SVasumathi.Sundaram@Sun.COM &conn->conn_srcv6); 2447*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(rem_addrstr, sizeof (rem_addrstr), "%N", 2448*9089SVasumathi.Sundaram@Sun.COM &conn->conn_remv6); 2449*9089SVasumathi.Sundaram@Sun.COM } else { 2450*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(src_addrstr, sizeof (src_addrstr), "%I", 2451*9089SVasumathi.Sundaram@Sun.COM V4_PART_OF_V6((conn->conn_srcv6))); 2452*9089SVasumathi.Sundaram@Sun.COM mdb_snprintf(rem_addrstr, sizeof (rem_addrstr), "%I", 2453*9089SVasumathi.Sundaram@Sun.COM V4_PART_OF_V6((conn->conn_remv6))); 2454*9089SVasumathi.Sundaram@Sun.COM } 2455*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%s:%-5d\n%s:%-5d\n", 2456*9089SVasumathi.Sundaram@Sun.COM src_addrstr, conn->conn_lport, rem_addrstr, conn->conn_fport); 2457*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2458*9089SVasumathi.Sundaram@Sun.COM } 2459*9089SVasumathi.Sundaram@Sun.COM 2460*9089SVasumathi.Sundaram@Sun.COM static void 2461*9089SVasumathi.Sundaram@Sun.COM conn_header(void) 2462*9089SVasumathi.Sundaram@Sun.COM { 2463*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?s %-?s %?s %?s\n%s\n%s\n", 2464*9089SVasumathi.Sundaram@Sun.COM "ADDR", "WQ", "STACK", "ZONE", "SRC:PORT", "DEST:PORT"); 2465*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%<u>%80s%</u>\n", ""); 2466*9089SVasumathi.Sundaram@Sun.COM } 2467*9089SVasumathi.Sundaram@Sun.COM 2468*9089SVasumathi.Sundaram@Sun.COM /*ARGSUSED*/ 2469*9089SVasumathi.Sundaram@Sun.COM static int 2470*9089SVasumathi.Sundaram@Sun.COM conn_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2471*9089SVasumathi.Sundaram@Sun.COM { 2472*9089SVasumathi.Sundaram@Sun.COM conn_header(); 2473*9089SVasumathi.Sundaram@Sun.COM if (flags & DCMD_ADDRSPEC) { 2474*9089SVasumathi.Sundaram@Sun.COM (void) conn_status_cb(addr, NULL, NULL); 2475*9089SVasumathi.Sundaram@Sun.COM } else { 2476*9089SVasumathi.Sundaram@Sun.COM if (mdb_walk("conn_status", (mdb_walk_cb_t)conn_status_cb, 2477*9089SVasumathi.Sundaram@Sun.COM NULL) == -1) { 2478*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to walk conn_fanout"); 2479*9089SVasumathi.Sundaram@Sun.COM return (DCMD_ERR); 2480*9089SVasumathi.Sundaram@Sun.COM } 2481*9089SVasumathi.Sundaram@Sun.COM } 2482*9089SVasumathi.Sundaram@Sun.COM return (DCMD_OK); 2483*9089SVasumathi.Sundaram@Sun.COM } 2484*9089SVasumathi.Sundaram@Sun.COM 2485*9089SVasumathi.Sundaram@Sun.COM static void 2486*9089SVasumathi.Sundaram@Sun.COM conn_status_help(void) 2487*9089SVasumathi.Sundaram@Sun.COM { 2488*9089SVasumathi.Sundaram@Sun.COM mdb_printf("Prints conn_t structures from the following hash tables: " 2489*9089SVasumathi.Sundaram@Sun.COM "\n\tips_ipcl_udp_fanout\n\tips_ipcl_bind_fanout" 2490*9089SVasumathi.Sundaram@Sun.COM "\n\tips_ipcl_conn_fanout\n\tips_ipcl_proto_fanout" 2491*9089SVasumathi.Sundaram@Sun.COM "\n\tips_ipcl_proto_fanout_v6\n"); 2492*9089SVasumathi.Sundaram@Sun.COM } 2493*9089SVasumathi.Sundaram@Sun.COM 2494*9089SVasumathi.Sundaram@Sun.COM static int 2495*9089SVasumathi.Sundaram@Sun.COM srcid_walk_step(mdb_walk_state_t *wsp) 2496*9089SVasumathi.Sundaram@Sun.COM { 2497*9089SVasumathi.Sundaram@Sun.COM if (mdb_pwalk("srcid_list", wsp->walk_callback, wsp->walk_cbdata, 2498*9089SVasumathi.Sundaram@Sun.COM wsp->walk_addr) == -1) { 2499*9089SVasumathi.Sundaram@Sun.COM mdb_warn("can't walk 'srcid_list'"); 2500*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 2501*9089SVasumathi.Sundaram@Sun.COM } 2502*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2503*9089SVasumathi.Sundaram@Sun.COM } 2504*9089SVasumathi.Sundaram@Sun.COM 2505*9089SVasumathi.Sundaram@Sun.COM /* ARGSUSED */ 2506*9089SVasumathi.Sundaram@Sun.COM static int 2507*9089SVasumathi.Sundaram@Sun.COM srcid_status_cb(uintptr_t addr, const void *walk_data, 2508*9089SVasumathi.Sundaram@Sun.COM void *private) 2509*9089SVasumathi.Sundaram@Sun.COM { 2510*9089SVasumathi.Sundaram@Sun.COM srcid_map_t smp; 2511*9089SVasumathi.Sundaram@Sun.COM 2512*9089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&smp, sizeof (srcid_map_t), addr) == -1) { 2513*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read srcid_map at %p", addr); 2514*9089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 2515*9089SVasumathi.Sundaram@Sun.COM } 2516*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?p %3d %4d %6d %N\n", 2517*9089SVasumathi.Sundaram@Sun.COM addr, smp.sm_srcid, smp.sm_zoneid, smp.sm_refcnt, 2518*9089SVasumathi.Sundaram@Sun.COM &smp.sm_addr); 2519*9089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 2520*9089SVasumathi.Sundaram@Sun.COM } 2521*9089SVasumathi.Sundaram@Sun.COM 2522*9089SVasumathi.Sundaram@Sun.COM static void 2523*9089SVasumathi.Sundaram@Sun.COM srcid_header(void) 2524*9089SVasumathi.Sundaram@Sun.COM { 2525*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%-?s %3s %4s %6s %s\n", 2526*9089SVasumathi.Sundaram@Sun.COM "ADDR", "ID", "ZONE", "REFCNT", "IPADDR"); 2527*9089SVasumathi.Sundaram@Sun.COM mdb_printf("%<u>%80s%</u>\n", ""); 2528*9089SVasumathi.Sundaram@Sun.COM } 2529*9089SVasumathi.Sundaram@Sun.COM 2530*9089SVasumathi.Sundaram@Sun.COM /*ARGSUSED*/ 2531*9089SVasumathi.Sundaram@Sun.COM static int 2532*9089SVasumathi.Sundaram@Sun.COM srcid_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2533*9089SVasumathi.Sundaram@Sun.COM { 2534*9089SVasumathi.Sundaram@Sun.COM srcid_header(); 2535*9089SVasumathi.Sundaram@Sun.COM if (flags & DCMD_ADDRSPEC) { 2536*9089SVasumathi.Sundaram@Sun.COM (void) srcid_status_cb(addr, NULL, NULL); 2537*9089SVasumathi.Sundaram@Sun.COM } else { 2538*9089SVasumathi.Sundaram@Sun.COM if (mdb_walk("srcid", (mdb_walk_cb_t)srcid_status_cb, 2539*9089SVasumathi.Sundaram@Sun.COM NULL) == -1) { 2540*9089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to walk srcid_map"); 2541*9089SVasumathi.Sundaram@Sun.COM return (DCMD_ERR); 2542*9089SVasumathi.Sundaram@Sun.COM } 2543*9089SVasumathi.Sundaram@Sun.COM } 2544*9089SVasumathi.Sundaram@Sun.COM return (DCMD_OK); 2545*9089SVasumathi.Sundaram@Sun.COM } 2546