1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 30*0Sstevel@tonic-gate #include <mdb/mdb_ks.h> 31*0Sstevel@tonic-gate #include <mdb/mdb_ctf.h> 32*0Sstevel@tonic-gate #include <sys/types.h> 33*0Sstevel@tonic-gate #include <sys/tihdr.h> 34*0Sstevel@tonic-gate #include <inet/led.h> 35*0Sstevel@tonic-gate #include <inet/common.h> 36*0Sstevel@tonic-gate #include <netinet/in.h> 37*0Sstevel@tonic-gate #include <netinet/ip6.h> 38*0Sstevel@tonic-gate #include <netinet/icmp6.h> 39*0Sstevel@tonic-gate #include <inet/ip.h> 40*0Sstevel@tonic-gate #include <inet/ip6.h> 41*0Sstevel@tonic-gate #include <inet/ipclassifier.h> 42*0Sstevel@tonic-gate #include <inet/tcp.h> 43*0Sstevel@tonic-gate #include <sys/stream.h> 44*0Sstevel@tonic-gate #include <sys/vfs.h> 45*0Sstevel@tonic-gate #include <sys/stropts.h> 46*0Sstevel@tonic-gate #include <sys/tpicommon.h> 47*0Sstevel@tonic-gate #include <sys/socket.h> 48*0Sstevel@tonic-gate #include <sys/socketvar.h> 49*0Sstevel@tonic-gate #include <sys/cred_impl.h> 50*0Sstevel@tonic-gate #include <inet/udp_impl.h> 51*0Sstevel@tonic-gate #include <inet/arp_impl.h> 52*0Sstevel@tonic-gate #include <inet/rawip_impl.h> 53*0Sstevel@tonic-gate #include <inet/mi.h> 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate #define MIH2MIO(mihp) (&(mihp)->mh_o) 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate #define ADDR_V6_WIDTH 23 58*0Sstevel@tonic-gate #define ADDR_V4_WIDTH 15 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate #define NETSTAT_ALL 0x1 61*0Sstevel@tonic-gate #define NETSTAT_VERBOSE 0x2 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate /* 64*0Sstevel@tonic-gate * Print an IPv4 address and port number in a compact and easy to read format 65*0Sstevel@tonic-gate * The arguments are in network byte order 66*0Sstevel@tonic-gate */ 67*0Sstevel@tonic-gate static void 68*0Sstevel@tonic-gate net_ipv4addrport_pr(const in6_addr_t *nipv6addr, in_port_t nport) 69*0Sstevel@tonic-gate { 70*0Sstevel@tonic-gate uint32_t naddr = V4_PART_OF_V6((*nipv6addr)); 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate mdb_nhconvert(&nport, &nport, sizeof (nport)); 73*0Sstevel@tonic-gate mdb_printf("%*I.%-5hu", ADDR_V4_WIDTH, naddr, nport); 74*0Sstevel@tonic-gate } 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate /* 77*0Sstevel@tonic-gate * Print an IPv6 address and port number in a compact and easy to read format 78*0Sstevel@tonic-gate * The arguments are in network byte order 79*0Sstevel@tonic-gate */ 80*0Sstevel@tonic-gate static void 81*0Sstevel@tonic-gate net_ipv6addrport_pr(const in6_addr_t *naddr, in_port_t nport) 82*0Sstevel@tonic-gate { 83*0Sstevel@tonic-gate mdb_nhconvert(&nport, &nport, sizeof (nport)); 84*0Sstevel@tonic-gate mdb_printf("%*N.%-5hu", ADDR_V6_WIDTH, naddr, nport); 85*0Sstevel@tonic-gate } 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate static int 88*0Sstevel@tonic-gate net_tcp_active(const tcp_t *tcp) 89*0Sstevel@tonic-gate { 90*0Sstevel@tonic-gate return (tcp->tcp_state >= TCPS_ESTABLISHED); 91*0Sstevel@tonic-gate } 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate static int 94*0Sstevel@tonic-gate net_tcp_ipv4(const tcp_t *tcp) 95*0Sstevel@tonic-gate { 96*0Sstevel@tonic-gate return ((tcp->tcp_ipversion == IPV4_VERSION) || 97*0Sstevel@tonic-gate (IN6_IS_ADDR_UNSPECIFIED(&tcp->tcp_ip_src_v6) && 98*0Sstevel@tonic-gate (tcp->tcp_state <= TCPS_LISTEN))); 99*0Sstevel@tonic-gate } 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate static int 102*0Sstevel@tonic-gate net_tcp_ipv6(const tcp_t *tcp) 103*0Sstevel@tonic-gate { 104*0Sstevel@tonic-gate return (tcp->tcp_ipversion == IPV6_VERSION); 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate static int 108*0Sstevel@tonic-gate net_udp_active(const udp_t *udp) 109*0Sstevel@tonic-gate { 110*0Sstevel@tonic-gate return ((udp->udp_state != TS_UNBND) && (udp->udp_state != TS_IDLE)); 111*0Sstevel@tonic-gate } 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate static int 114*0Sstevel@tonic-gate net_udp_ipv4(const udp_t *udp) 115*0Sstevel@tonic-gate { 116*0Sstevel@tonic-gate return ((udp->udp_ipversion == IPV4_VERSION) || 117*0Sstevel@tonic-gate (IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src) && 118*0Sstevel@tonic-gate (udp->udp_state <= TS_IDLE))); 119*0Sstevel@tonic-gate } 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate static int 122*0Sstevel@tonic-gate net_udp_ipv6(const udp_t *udp) 123*0Sstevel@tonic-gate { 124*0Sstevel@tonic-gate return (udp->udp_ipversion == IPV6_VERSION); 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate int 128*0Sstevel@tonic-gate sonode_walk_init(mdb_walk_state_t *wsp) 129*0Sstevel@tonic-gate { 130*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 131*0Sstevel@tonic-gate GElf_Sym sym; 132*0Sstevel@tonic-gate struct socklist *slp; 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate if (mdb_lookup_by_obj("sockfs", "socklist", &sym) == -1) { 135*0Sstevel@tonic-gate mdb_warn("failed to lookup sockfs`socklist"); 136*0Sstevel@tonic-gate return (WALK_ERR); 137*0Sstevel@tonic-gate } 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate slp = (struct socklist *)(uintptr_t)sym.st_value; 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr), 142*0Sstevel@tonic-gate (uintptr_t)&slp->sl_list) == -1) { 143*0Sstevel@tonic-gate mdb_warn("failed to read address of initial sonode " 144*0Sstevel@tonic-gate "at %p", &slp->sl_list); 145*0Sstevel@tonic-gate return (WALK_ERR); 146*0Sstevel@tonic-gate } 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate wsp->walk_data = mdb_alloc(sizeof (struct sonode), UM_SLEEP); 150*0Sstevel@tonic-gate return (WALK_NEXT); 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate int 154*0Sstevel@tonic-gate sonode_walk_step(mdb_walk_state_t *wsp) 155*0Sstevel@tonic-gate { 156*0Sstevel@tonic-gate int status; 157*0Sstevel@tonic-gate struct sonode *sonodep; 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) 160*0Sstevel@tonic-gate return (WALK_DONE); 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate if (mdb_vread(wsp->walk_data, sizeof (struct sonode), 163*0Sstevel@tonic-gate wsp->walk_addr) == -1) { 164*0Sstevel@tonic-gate mdb_warn("failed to read sonode at %p", wsp->walk_addr); 165*0Sstevel@tonic-gate return (WALK_ERR); 166*0Sstevel@tonic-gate } 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 169*0Sstevel@tonic-gate wsp->walk_cbdata); 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate sonodep = wsp->walk_data; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)sonodep->so_next; 174*0Sstevel@tonic-gate return (status); 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate void 178*0Sstevel@tonic-gate sonode_walk_fini(mdb_walk_state_t *wsp) 179*0Sstevel@tonic-gate { 180*0Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (struct sonode)); 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate struct mi_walk_data { 184*0Sstevel@tonic-gate uintptr_t mi_wd_miofirst; 185*0Sstevel@tonic-gate MI_O mi_wd_miodata; 186*0Sstevel@tonic-gate }; 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate int 189*0Sstevel@tonic-gate mi_walk_init(mdb_walk_state_t *wsp) 190*0Sstevel@tonic-gate { 191*0Sstevel@tonic-gate struct mi_walk_data *wdp; 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 194*0Sstevel@tonic-gate mdb_warn("mi doesn't support global walks\n"); 195*0Sstevel@tonic-gate return (WALK_ERR); 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate wdp = mdb_alloc(sizeof (struct mi_walk_data), UM_SLEEP); 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate /* So that we do not immediately return WALK_DONE below */ 201*0Sstevel@tonic-gate wdp->mi_wd_miofirst = NULL; 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate wsp->walk_data = wdp; 204*0Sstevel@tonic-gate return (WALK_NEXT); 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate int 208*0Sstevel@tonic-gate mi_walk_step(mdb_walk_state_t *wsp) 209*0Sstevel@tonic-gate { 210*0Sstevel@tonic-gate struct mi_walk_data *wdp = wsp->walk_data; 211*0Sstevel@tonic-gate MI_OP miop = &wdp->mi_wd_miodata; 212*0Sstevel@tonic-gate int status; 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate /* Always false in the first iteration */ 215*0Sstevel@tonic-gate if ((wsp->walk_addr == (uintptr_t)NULL) || 216*0Sstevel@tonic-gate (wsp->walk_addr == wdp->mi_wd_miofirst)) { 217*0Sstevel@tonic-gate return (WALK_DONE); 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate if (mdb_vread(miop, sizeof (MI_O), wsp->walk_addr) == -1) { 221*0Sstevel@tonic-gate mdb_warn("failed to read MI object at %p", wsp->walk_addr); 222*0Sstevel@tonic-gate return (WALK_ERR); 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, miop, wsp->walk_cbdata); 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate /* Only true in the first iteration */ 228*0Sstevel@tonic-gate if (wdp->mi_wd_miofirst == NULL) 229*0Sstevel@tonic-gate wdp->mi_wd_miofirst = wsp->walk_addr; 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)miop->mi_o_next; 232*0Sstevel@tonic-gate return (status); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate void 236*0Sstevel@tonic-gate mi_walk_fini(mdb_walk_state_t *wsp) 237*0Sstevel@tonic-gate { 238*0Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (struct mi_walk_data)); 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate typedef struct mi_payload_walk_data_s { 242*0Sstevel@tonic-gate uintptr_t mi_pwd_first; 243*0Sstevel@tonic-gate void *mi_pwd_data; 244*0Sstevel@tonic-gate } mi_payload_walk_data_t; 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate static void 247*0Sstevel@tonic-gate delete_mi_payload_walk_data(mi_payload_walk_data_t *pwdp, size_t payload_size) 248*0Sstevel@tonic-gate { 249*0Sstevel@tonic-gate mdb_free(pwdp->mi_pwd_data, payload_size); 250*0Sstevel@tonic-gate mdb_free(pwdp, sizeof (mi_payload_walk_data_t)); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate typedef struct mi_payload_walk_arg_s { 254*0Sstevel@tonic-gate const char *mi_pwa_obj; /* load object of mi_o_head_t * */ 255*0Sstevel@tonic-gate const char *mi_pwa_sym; /* symbol name of mi_o_head_t * */ 256*0Sstevel@tonic-gate const size_t mi_pwa_size; /* size of mi payload */ 257*0Sstevel@tonic-gate const uint_t mi_pwa_flags; /* device and/or module */ 258*0Sstevel@tonic-gate } mi_payload_walk_arg_t; 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate #define MI_PAYLOAD_DEVICE 0x1 261*0Sstevel@tonic-gate #define MI_PAYLOAD_MODULE 0x2 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate int 264*0Sstevel@tonic-gate mi_payload_walk_init(mdb_walk_state_t *wsp) 265*0Sstevel@tonic-gate { 266*0Sstevel@tonic-gate const mi_payload_walk_arg_t *arg = wsp->walk_arg; 267*0Sstevel@tonic-gate mi_payload_walk_data_t *pwdp; 268*0Sstevel@tonic-gate GElf_Sym sym; 269*0Sstevel@tonic-gate mi_head_t *mihp; 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate /* Determine the address to start or end the walk with */ 272*0Sstevel@tonic-gate if (mdb_lookup_by_obj(arg->mi_pwa_obj, arg->mi_pwa_sym, &sym) == -1) { 273*0Sstevel@tonic-gate mdb_warn("failed to lookup %s`%s", 274*0Sstevel@tonic-gate arg->mi_pwa_obj, arg->mi_pwa_sym); 275*0Sstevel@tonic-gate return (WALK_ERR); 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate if (mdb_vread(&mihp, sizeof (mihp), (uintptr_t)sym.st_value) == -1) { 279*0Sstevel@tonic-gate mdb_warn("failed to read address of global MI Head " 280*0Sstevel@tonic-gate "mi_o_head_t at %p", (uintptr_t)sym.st_value); 281*0Sstevel@tonic-gate return (WALK_ERR); 282*0Sstevel@tonic-gate } 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate pwdp = mdb_alloc(sizeof (mi_payload_walk_data_t), UM_SLEEP); 285*0Sstevel@tonic-gate pwdp->mi_pwd_data = mdb_alloc(arg->mi_pwa_size, UM_SLEEP); 286*0Sstevel@tonic-gate wsp->walk_data = pwdp; 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 289*0Sstevel@tonic-gate /* Do not immediately return WALK_DONE below */ 290*0Sstevel@tonic-gate pwdp->mi_pwd_first = NULL; 291*0Sstevel@tonic-gate /* We determined where to begin */ 292*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)MIH2MIO(mihp); 293*0Sstevel@tonic-gate } else { 294*0Sstevel@tonic-gate /* Do not cycle through all of the MI_O objects */ 295*0Sstevel@tonic-gate pwdp->mi_pwd_first = (uintptr_t)MIH2MIO(mihp); 296*0Sstevel@tonic-gate /* We were given where to begin */ 297*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)((MI_OP)wsp->walk_addr - 1); 298*0Sstevel@tonic-gate } 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate if (mdb_layered_walk("genunix`mi", wsp) == -1) { 301*0Sstevel@tonic-gate mdb_warn("failed to walk genunix`mi"); 302*0Sstevel@tonic-gate delete_mi_payload_walk_data(pwdp, arg->mi_pwa_size); 303*0Sstevel@tonic-gate return (WALK_ERR); 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate return (WALK_NEXT); 307*0Sstevel@tonic-gate } 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate int 310*0Sstevel@tonic-gate mi_payload_walk_step(mdb_walk_state_t *wsp) 311*0Sstevel@tonic-gate { 312*0Sstevel@tonic-gate const mi_payload_walk_arg_t *arg = wsp->walk_arg; 313*0Sstevel@tonic-gate mi_payload_walk_data_t *pwdp = wsp->walk_data; 314*0Sstevel@tonic-gate void *payload = pwdp->mi_pwd_data; 315*0Sstevel@tonic-gate uintptr_t payload_kaddr = (uintptr_t)((MI_OP)wsp->walk_addr + 1); 316*0Sstevel@tonic-gate const MI_O *mio = wsp->walk_layer; 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate /* If this is a local walk, prevent cycling */ 319*0Sstevel@tonic-gate if (wsp->walk_addr == pwdp->mi_pwd_first) 320*0Sstevel@tonic-gate return (WALK_DONE); 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate /* 323*0Sstevel@tonic-gate * This was a global walk, prevent reading this payload as the 324*0Sstevel@tonic-gate * initial MI_O is the head of the list and is not the header 325*0Sstevel@tonic-gate * to a valid payload 326*0Sstevel@tonic-gate */ 327*0Sstevel@tonic-gate if (pwdp->mi_pwd_first == NULL) { 328*0Sstevel@tonic-gate pwdp->mi_pwd_first = wsp->walk_addr; 329*0Sstevel@tonic-gate return (WALK_NEXT); 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate if (mio->mi_o_isdev == B_FALSE) { 333*0Sstevel@tonic-gate /* mio is a module */ 334*0Sstevel@tonic-gate if (!(arg->mi_pwa_flags & MI_PAYLOAD_MODULE)) 335*0Sstevel@tonic-gate return (WALK_NEXT); 336*0Sstevel@tonic-gate } else { 337*0Sstevel@tonic-gate /* mio is a device */ 338*0Sstevel@tonic-gate if (!(arg->mi_pwa_flags & MI_PAYLOAD_DEVICE)) 339*0Sstevel@tonic-gate return (WALK_NEXT); 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate if (mdb_vread(payload, arg->mi_pwa_size, payload_kaddr) == -1) { 343*0Sstevel@tonic-gate mdb_warn("failed to read payload at %p", payload_kaddr); 344*0Sstevel@tonic-gate return (WALK_ERR); 345*0Sstevel@tonic-gate } 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate return (wsp->walk_callback(payload_kaddr, payload, wsp->walk_cbdata)); 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate void 351*0Sstevel@tonic-gate mi_payload_walk_fini(mdb_walk_state_t *wsp) 352*0Sstevel@tonic-gate { 353*0Sstevel@tonic-gate const mi_payload_walk_arg_t *arg = wsp->walk_arg; 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate delete_mi_payload_walk_data(wsp->walk_data, arg->mi_pwa_size); 356*0Sstevel@tonic-gate } 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate const mi_payload_walk_arg_t mi_udp_arg = { 359*0Sstevel@tonic-gate "udp", "udp_g_head", sizeof (udp_t), 360*0Sstevel@tonic-gate MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE 361*0Sstevel@tonic-gate }; 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate const mi_payload_walk_arg_t mi_ar_arg = { 364*0Sstevel@tonic-gate "arp", "ar_g_head", sizeof (ar_t), 365*0Sstevel@tonic-gate MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE 366*0Sstevel@tonic-gate }; 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate const mi_payload_walk_arg_t mi_icmp_arg = { 369*0Sstevel@tonic-gate "icmp", "icmp_g_head", sizeof (icmp_t), 370*0Sstevel@tonic-gate MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE 371*0Sstevel@tonic-gate }; 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate const mi_payload_walk_arg_t mi_ill_arg = 374*0Sstevel@tonic-gate { "ip", "ip_g_head", sizeof (ill_t), MI_PAYLOAD_MODULE }; 375*0Sstevel@tonic-gate 376*0Sstevel@tonic-gate int 377*0Sstevel@tonic-gate sonode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 378*0Sstevel@tonic-gate { 379*0Sstevel@tonic-gate const char *optf = NULL; 380*0Sstevel@tonic-gate const char *optt = NULL; 381*0Sstevel@tonic-gate const char *optp = NULL; 382*0Sstevel@tonic-gate int family, type, proto; 383*0Sstevel@tonic-gate int filter = 0; 384*0Sstevel@tonic-gate struct sonode so; 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 387*0Sstevel@tonic-gate if (mdb_walk_dcmd("genunix`sonode", "genunix`sonode", argc, 388*0Sstevel@tonic-gate argv) == -1) { 389*0Sstevel@tonic-gate mdb_warn("failed to walk sonode"); 390*0Sstevel@tonic-gate return (DCMD_ERR); 391*0Sstevel@tonic-gate } 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate return (DCMD_OK); 394*0Sstevel@tonic-gate } 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 397*0Sstevel@tonic-gate 'f', MDB_OPT_STR, &optf, 398*0Sstevel@tonic-gate 't', MDB_OPT_STR, &optt, 399*0Sstevel@tonic-gate 'p', MDB_OPT_STR, &optp, 400*0Sstevel@tonic-gate NULL) != argc) 401*0Sstevel@tonic-gate return (DCMD_USAGE); 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate if (optf != NULL) { 404*0Sstevel@tonic-gate if (strcmp("inet", optf) == 0) 405*0Sstevel@tonic-gate family = AF_INET; 406*0Sstevel@tonic-gate else if (strcmp("inet6", optf) == 0) 407*0Sstevel@tonic-gate family = AF_INET6; 408*0Sstevel@tonic-gate else if (strcmp("unix", optf) == 0) 409*0Sstevel@tonic-gate family = AF_UNIX; 410*0Sstevel@tonic-gate else 411*0Sstevel@tonic-gate family = mdb_strtoull(optf); 412*0Sstevel@tonic-gate filter = 1; 413*0Sstevel@tonic-gate } 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gate if (optt != NULL) { 416*0Sstevel@tonic-gate if (strcmp("stream", optt) == 0) 417*0Sstevel@tonic-gate type = SOCK_STREAM; 418*0Sstevel@tonic-gate else if (strcmp("dgram", optt) == 0) 419*0Sstevel@tonic-gate type = SOCK_DGRAM; 420*0Sstevel@tonic-gate else if (strcmp("raw", optt) == 0) 421*0Sstevel@tonic-gate type = SOCK_RAW; 422*0Sstevel@tonic-gate else 423*0Sstevel@tonic-gate type = mdb_strtoull(optt); 424*0Sstevel@tonic-gate filter = 1; 425*0Sstevel@tonic-gate } 426*0Sstevel@tonic-gate 427*0Sstevel@tonic-gate if (optp != NULL) { 428*0Sstevel@tonic-gate proto = mdb_strtoull(optp); 429*0Sstevel@tonic-gate filter = 1; 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && !filter) { 433*0Sstevel@tonic-gate mdb_printf("%<u>%-?s Family Type Proto State Mode Flag " 434*0Sstevel@tonic-gate "AccessVP%</u>\n", "Sonode:"); 435*0Sstevel@tonic-gate } 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate if (mdb_vread(&so, sizeof (so), addr) == -1) { 438*0Sstevel@tonic-gate mdb_warn("failed to read sonode at %p", addr); 439*0Sstevel@tonic-gate return (DCMD_ERR); 440*0Sstevel@tonic-gate } 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gate if ((optf != NULL) && (so.so_family != family)) 443*0Sstevel@tonic-gate return (DCMD_OK); 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate if ((optt != NULL) && (so.so_type != type)) 446*0Sstevel@tonic-gate return (DCMD_OK); 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate if ((optp != NULL) && (so.so_protocol != proto)) 449*0Sstevel@tonic-gate return (DCMD_OK); 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate if (filter) { 452*0Sstevel@tonic-gate mdb_printf("%0?p\n", addr); 453*0Sstevel@tonic-gate return (DCMD_OK); 454*0Sstevel@tonic-gate } 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate mdb_printf("%0?p ", addr); 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate switch (so.so_family) { 459*0Sstevel@tonic-gate case AF_UNIX: 460*0Sstevel@tonic-gate mdb_printf("unix "); 461*0Sstevel@tonic-gate break; 462*0Sstevel@tonic-gate case AF_INET: 463*0Sstevel@tonic-gate mdb_printf("inet "); 464*0Sstevel@tonic-gate break; 465*0Sstevel@tonic-gate case AF_INET6: 466*0Sstevel@tonic-gate mdb_printf("inet6 "); 467*0Sstevel@tonic-gate break; 468*0Sstevel@tonic-gate default: 469*0Sstevel@tonic-gate mdb_printf("%6hi", so.so_family); 470*0Sstevel@tonic-gate } 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate switch (so.so_type) { 473*0Sstevel@tonic-gate case SOCK_STREAM: 474*0Sstevel@tonic-gate mdb_printf(" strm"); 475*0Sstevel@tonic-gate break; 476*0Sstevel@tonic-gate case SOCK_DGRAM: 477*0Sstevel@tonic-gate mdb_printf(" dgrm"); 478*0Sstevel@tonic-gate break; 479*0Sstevel@tonic-gate case SOCK_RAW: 480*0Sstevel@tonic-gate mdb_printf(" raw "); 481*0Sstevel@tonic-gate break; 482*0Sstevel@tonic-gate default: 483*0Sstevel@tonic-gate mdb_printf(" %4hi", so.so_type); 484*0Sstevel@tonic-gate } 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate mdb_printf(" %5hi %05x %04x %04hx %0?p\n", 487*0Sstevel@tonic-gate so.so_protocol, so.so_state, so.so_mode, 488*0Sstevel@tonic-gate so.so_flag, so.so_accessvp); 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate return (DCMD_OK); 491*0Sstevel@tonic-gate } 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate #define MI_PAYLOAD 0x1 494*0Sstevel@tonic-gate #define MI_DEVICE 0x2 495*0Sstevel@tonic-gate #define MI_MODULE 0x4 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate int 498*0Sstevel@tonic-gate mi(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 499*0Sstevel@tonic-gate { 500*0Sstevel@tonic-gate uint_t opts = 0; 501*0Sstevel@tonic-gate MI_O mio; 502*0Sstevel@tonic-gate 503*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 504*0Sstevel@tonic-gate return (DCMD_USAGE); 505*0Sstevel@tonic-gate 506*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 507*0Sstevel@tonic-gate 'p', MDB_OPT_SETBITS, MI_PAYLOAD, &opts, 508*0Sstevel@tonic-gate 'd', MDB_OPT_SETBITS, MI_DEVICE, &opts, 509*0Sstevel@tonic-gate 'm', MDB_OPT_SETBITS, MI_MODULE, &opts, 510*0Sstevel@tonic-gate NULL) != argc) 511*0Sstevel@tonic-gate return (DCMD_USAGE); 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate if ((opts & (MI_DEVICE | MI_MODULE)) == (MI_DEVICE | MI_MODULE)) { 514*0Sstevel@tonic-gate mdb_warn("at most one filter, d for devices or m " 515*0Sstevel@tonic-gate "for modules, may be specified\n"); 516*0Sstevel@tonic-gate return (DCMD_USAGE); 517*0Sstevel@tonic-gate } 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate if ((opts == 0) && (DCMD_HDRSPEC(flags))) { 520*0Sstevel@tonic-gate mdb_printf("%<u>%-?s %-?s %-?s IsDev Dev%</u>\n", 521*0Sstevel@tonic-gate "MI_O", "Next", "Prev"); 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate if (mdb_vread(&mio, sizeof (mio), addr) == -1) { 525*0Sstevel@tonic-gate mdb_warn("failed to read mi object MI_O at %p", addr); 526*0Sstevel@tonic-gate return (DCMD_ERR); 527*0Sstevel@tonic-gate } 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate if (opts != 0) { 530*0Sstevel@tonic-gate if (mio.mi_o_isdev == B_FALSE) { 531*0Sstevel@tonic-gate /* mio is a module */ 532*0Sstevel@tonic-gate if (!(opts & MI_MODULE) && (opts & MI_DEVICE)) 533*0Sstevel@tonic-gate return (DCMD_OK); 534*0Sstevel@tonic-gate } else { 535*0Sstevel@tonic-gate /* mio is a device */ 536*0Sstevel@tonic-gate if (!(opts & MI_DEVICE) && (opts & MI_MODULE)) 537*0Sstevel@tonic-gate return (DCMD_OK); 538*0Sstevel@tonic-gate } 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate if (opts & MI_PAYLOAD) 541*0Sstevel@tonic-gate mdb_printf("%p\n", addr + sizeof (MI_O)); 542*0Sstevel@tonic-gate else 543*0Sstevel@tonic-gate mdb_printf("%p\n", addr); 544*0Sstevel@tonic-gate return (DCMD_OK); 545*0Sstevel@tonic-gate } 546*0Sstevel@tonic-gate 547*0Sstevel@tonic-gate mdb_printf("%0?p %0?p %0?p ", addr, mio.mi_o_next, mio.mi_o_prev); 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate if (mio.mi_o_isdev == B_FALSE) 550*0Sstevel@tonic-gate mdb_printf("FALSE"); 551*0Sstevel@tonic-gate else 552*0Sstevel@tonic-gate mdb_printf("TRUE "); 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate mdb_printf(" %0?p\n", mio.mi_o_dev); 555*0Sstevel@tonic-gate 556*0Sstevel@tonic-gate return (DCMD_OK); 557*0Sstevel@tonic-gate } 558*0Sstevel@tonic-gate 559*0Sstevel@tonic-gate static void 560*0Sstevel@tonic-gate netstat_tcp_verbose_pr(const tcp_t *tcp) 561*0Sstevel@tonic-gate { 562*0Sstevel@tonic-gate mdb_printf(" %5i %08x %08x %5i %08x %08x %5li %5i\n", 563*0Sstevel@tonic-gate tcp->tcp_swnd, tcp->tcp_snxt, tcp->tcp_suna, tcp->tcp_rwnd, 564*0Sstevel@tonic-gate tcp->tcp_rack, tcp->tcp_rnxt, tcp->tcp_rto, tcp->tcp_mss); 565*0Sstevel@tonic-gate } 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate /*ARGSUSED*/ 568*0Sstevel@tonic-gate static int 569*0Sstevel@tonic-gate netstat_tcp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data, int af) 570*0Sstevel@tonic-gate { 571*0Sstevel@tonic-gate const uintptr_t opts = (uintptr_t)cb_data; 572*0Sstevel@tonic-gate static size_t itc_size = 0; 573*0Sstevel@tonic-gate uintptr_t tcp_kaddr; 574*0Sstevel@tonic-gate conn_t *connp; 575*0Sstevel@tonic-gate tcp_t *tcp; 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate if (itc_size == 0) { 578*0Sstevel@tonic-gate mdb_ctf_id_t id; 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate if (mdb_ctf_lookup_by_name("itc_t", &id) != 0) { 581*0Sstevel@tonic-gate mdb_warn("failed to lookup type 'itc_t'"); 582*0Sstevel@tonic-gate return (WALK_ERR); 583*0Sstevel@tonic-gate } 584*0Sstevel@tonic-gate itc_size = mdb_ctf_type_size(id); 585*0Sstevel@tonic-gate } 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate connp = (conn_t *)mdb_alloc(itc_size, UM_SLEEP | UM_GC); 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate if (mdb_vread(connp, itc_size, kaddr) == -1) { 590*0Sstevel@tonic-gate mdb_warn("failed to read connection info at %p", kaddr); 591*0Sstevel@tonic-gate return (WALK_ERR); 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate tcp_kaddr = (uintptr_t)connp->conn_tcp; 595*0Sstevel@tonic-gate tcp = (tcp_t *)((uintptr_t)connp + (tcp_kaddr - kaddr)); 596*0Sstevel@tonic-gate 597*0Sstevel@tonic-gate if ((uintptr_t)tcp < (uintptr_t)connp || 598*0Sstevel@tonic-gate (uintptr_t)&tcp->tcp_connp > (uintptr_t)connp + itc_size || 599*0Sstevel@tonic-gate (uintptr_t)tcp->tcp_connp != kaddr) { 600*0Sstevel@tonic-gate mdb_warn("conn_tcp %p is invalid", tcp_kaddr); 601*0Sstevel@tonic-gate return (WALK_NEXT); 602*0Sstevel@tonic-gate } 603*0Sstevel@tonic-gate connp->conn_tcp = tcp; 604*0Sstevel@tonic-gate tcp->tcp_connp = connp; 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate if (!(opts & NETSTAT_ALL || net_tcp_active(tcp)) || 607*0Sstevel@tonic-gate (af == AF_INET && !net_tcp_ipv4(tcp)) || 608*0Sstevel@tonic-gate (af == AF_INET6 && !net_tcp_ipv6(tcp))) { 609*0Sstevel@tonic-gate return (WALK_NEXT); 610*0Sstevel@tonic-gate } 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate mdb_printf("%0?p %2i ", tcp_kaddr, tcp->tcp_state); 613*0Sstevel@tonic-gate if (af == AF_INET) { 614*0Sstevel@tonic-gate net_ipv4addrport_pr(&tcp->tcp_ip_src_v6, tcp->tcp_lport); 615*0Sstevel@tonic-gate mdb_printf(" "); 616*0Sstevel@tonic-gate net_ipv4addrport_pr(&tcp->tcp_remote_v6, tcp->tcp_fport); 617*0Sstevel@tonic-gate } else if (af == AF_INET6) { 618*0Sstevel@tonic-gate net_ipv6addrport_pr(&tcp->tcp_ip_src_v6, tcp->tcp_lport); 619*0Sstevel@tonic-gate mdb_printf(" "); 620*0Sstevel@tonic-gate net_ipv6addrport_pr(&tcp->tcp_remote_v6, tcp->tcp_fport); 621*0Sstevel@tonic-gate } 622*0Sstevel@tonic-gate mdb_printf(" %4i\n", connp->conn_zoneid); 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate if (opts & NETSTAT_VERBOSE) 625*0Sstevel@tonic-gate netstat_tcp_verbose_pr(tcp); 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate return (WALK_NEXT); 628*0Sstevel@tonic-gate } 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate static int 631*0Sstevel@tonic-gate netstat_tcpv4_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 632*0Sstevel@tonic-gate { 633*0Sstevel@tonic-gate return (netstat_tcp_cb(kaddr, walk_data, cb_data, AF_INET)); 634*0Sstevel@tonic-gate } 635*0Sstevel@tonic-gate 636*0Sstevel@tonic-gate static int 637*0Sstevel@tonic-gate netstat_tcpv6_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 638*0Sstevel@tonic-gate { 639*0Sstevel@tonic-gate return (netstat_tcp_cb(kaddr, walk_data, cb_data, AF_INET6)); 640*0Sstevel@tonic-gate } 641*0Sstevel@tonic-gate 642*0Sstevel@tonic-gate static int 643*0Sstevel@tonic-gate netstat_udpv4_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 644*0Sstevel@tonic-gate { 645*0Sstevel@tonic-gate const udp_t *udp = walk_data; 646*0Sstevel@tonic-gate const uintptr_t opts = (uintptr_t)cb_data; 647*0Sstevel@tonic-gate 648*0Sstevel@tonic-gate if (!((opts & NETSTAT_ALL || net_udp_active(udp)) && net_udp_ipv4(udp))) 649*0Sstevel@tonic-gate return (WALK_NEXT); 650*0Sstevel@tonic-gate 651*0Sstevel@tonic-gate mdb_printf("%0?p %2i ", kaddr, udp->udp_state); 652*0Sstevel@tonic-gate net_ipv4addrport_pr(&udp->udp_v6src, udp->udp_port); 653*0Sstevel@tonic-gate mdb_printf(" "); 654*0Sstevel@tonic-gate net_ipv4addrport_pr(&udp->udp_v6dst, udp->udp_dstport); 655*0Sstevel@tonic-gate mdb_printf(" %4i\n", udp->udp_zoneid); 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate return (WALK_NEXT); 658*0Sstevel@tonic-gate } 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate static int 661*0Sstevel@tonic-gate netstat_udpv6_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 662*0Sstevel@tonic-gate { 663*0Sstevel@tonic-gate const udp_t *udp = walk_data; 664*0Sstevel@tonic-gate const uintptr_t opts = (uintptr_t)cb_data; 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate if (!((opts & NETSTAT_ALL || net_udp_active(udp)) && net_udp_ipv6(udp))) 667*0Sstevel@tonic-gate return (WALK_NEXT); 668*0Sstevel@tonic-gate 669*0Sstevel@tonic-gate mdb_printf("%0?p %2i ", kaddr, udp->udp_state); 670*0Sstevel@tonic-gate net_ipv6addrport_pr(&udp->udp_v6src, udp->udp_port); 671*0Sstevel@tonic-gate mdb_printf(" "); 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate /* Remote */ 674*0Sstevel@tonic-gate if (udp->udp_state == TS_DATA_XFER) 675*0Sstevel@tonic-gate net_ipv6addrport_pr(&udp->udp_v6dst, udp->udp_dstport); 676*0Sstevel@tonic-gate else 677*0Sstevel@tonic-gate mdb_printf("%*s.0 ", ADDR_V6_WIDTH, "0:0:0:0:0:0:0:0"); 678*0Sstevel@tonic-gate mdb_printf(" %4i\n", udp->udp_zoneid); 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gate return (WALK_NEXT); 681*0Sstevel@tonic-gate } 682*0Sstevel@tonic-gate 683*0Sstevel@tonic-gate /* 684*0Sstevel@tonic-gate * print the address of a unix domain socket 685*0Sstevel@tonic-gate * 686*0Sstevel@tonic-gate * so is the address of a AF_UNIX struct sonode in mdb's address space 687*0Sstevel@tonic-gate * soa is the address of the struct soaddr to print 688*0Sstevel@tonic-gate * 689*0Sstevel@tonic-gate * returns 0 on success, -1 otherwise 690*0Sstevel@tonic-gate */ 691*0Sstevel@tonic-gate static int 692*0Sstevel@tonic-gate netstat_unix_name_pr(const struct sonode *so, const struct soaddr *soa) 693*0Sstevel@tonic-gate { 694*0Sstevel@tonic-gate const char none[] = " (none)"; 695*0Sstevel@tonic-gate 696*0Sstevel@tonic-gate if ((so->so_state & SS_ISBOUND) && (soa->soa_len != 0)) { 697*0Sstevel@tonic-gate if (so->so_state & SS_FADDR_NOXLATE) { 698*0Sstevel@tonic-gate mdb_printf("%-14s ", " (socketpair)"); 699*0Sstevel@tonic-gate } else { 700*0Sstevel@tonic-gate if (soa->soa_len > sizeof (sa_family_t)) { 701*0Sstevel@tonic-gate char addr[MAXPATHLEN + 1]; 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate if (mdb_readstr(addr, sizeof (addr), 704*0Sstevel@tonic-gate (uintptr_t)&soa->soa_sa->sa_data) == -1) { 705*0Sstevel@tonic-gate mdb_warn("failed to read unix address " 706*0Sstevel@tonic-gate "at %p", &soa->soa_sa->sa_data); 707*0Sstevel@tonic-gate return (-1); 708*0Sstevel@tonic-gate } 709*0Sstevel@tonic-gate 710*0Sstevel@tonic-gate mdb_printf("%-14s ", addr); 711*0Sstevel@tonic-gate } else { 712*0Sstevel@tonic-gate mdb_printf("%-14s ", none); 713*0Sstevel@tonic-gate } 714*0Sstevel@tonic-gate } 715*0Sstevel@tonic-gate } else { 716*0Sstevel@tonic-gate mdb_printf("%-14s ", none); 717*0Sstevel@tonic-gate } 718*0Sstevel@tonic-gate 719*0Sstevel@tonic-gate return (0); 720*0Sstevel@tonic-gate } 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate /* based on sockfs_snapshot */ 723*0Sstevel@tonic-gate /*ARGSUSED*/ 724*0Sstevel@tonic-gate static int 725*0Sstevel@tonic-gate netstat_unix_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 726*0Sstevel@tonic-gate { 727*0Sstevel@tonic-gate const struct sonode *so = walk_data; 728*0Sstevel@tonic-gate 729*0Sstevel@tonic-gate if (so->so_accessvp == NULL) 730*0Sstevel@tonic-gate return (WALK_NEXT); 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate if (so->so_family != AF_UNIX) { 733*0Sstevel@tonic-gate mdb_warn("sonode of family %hi at %p\n", so->so_family, kaddr); 734*0Sstevel@tonic-gate return (WALK_ERR); 735*0Sstevel@tonic-gate } 736*0Sstevel@tonic-gate 737*0Sstevel@tonic-gate mdb_printf("%-?p ", kaddr); 738*0Sstevel@tonic-gate 739*0Sstevel@tonic-gate switch (so->so_serv_type) { 740*0Sstevel@tonic-gate case T_CLTS: 741*0Sstevel@tonic-gate mdb_printf("%-10s ", "dgram"); 742*0Sstevel@tonic-gate break; 743*0Sstevel@tonic-gate case T_COTS: 744*0Sstevel@tonic-gate mdb_printf("%-10s ", "stream"); 745*0Sstevel@tonic-gate break; 746*0Sstevel@tonic-gate case T_COTS_ORD: 747*0Sstevel@tonic-gate mdb_printf("%-10s ", "stream-ord"); 748*0Sstevel@tonic-gate break; 749*0Sstevel@tonic-gate default: 750*0Sstevel@tonic-gate mdb_printf("%-10i ", so->so_serv_type); 751*0Sstevel@tonic-gate } 752*0Sstevel@tonic-gate 753*0Sstevel@tonic-gate if ((so->so_state & SS_ISBOUND) && 754*0Sstevel@tonic-gate (so->so_ux_laddr.soua_magic == SOU_MAGIC_EXPLICIT)) { 755*0Sstevel@tonic-gate mdb_printf("%0?p ", so->so_ux_laddr.soua_vp); 756*0Sstevel@tonic-gate } else { 757*0Sstevel@tonic-gate mdb_printf("%0?p ", NULL); 758*0Sstevel@tonic-gate } 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate if ((so->so_state & SS_ISCONNECTED) && 761*0Sstevel@tonic-gate (so->so_ux_faddr.soua_magic == SOU_MAGIC_EXPLICIT)) { 762*0Sstevel@tonic-gate mdb_printf("%0?p ", so->so_ux_faddr.soua_vp); 763*0Sstevel@tonic-gate } else { 764*0Sstevel@tonic-gate mdb_printf("%0?p ", NULL); 765*0Sstevel@tonic-gate } 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate if (netstat_unix_name_pr(so, &so->so_laddr) == -1) 768*0Sstevel@tonic-gate return (WALK_ERR); 769*0Sstevel@tonic-gate 770*0Sstevel@tonic-gate if (netstat_unix_name_pr(so, &so->so_faddr) == -1) 771*0Sstevel@tonic-gate return (WALK_ERR); 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate mdb_printf("%4i\n", so->so_zoneid); 774*0Sstevel@tonic-gate 775*0Sstevel@tonic-gate return (WALK_NEXT); 776*0Sstevel@tonic-gate } 777*0Sstevel@tonic-gate 778*0Sstevel@tonic-gate static void 779*0Sstevel@tonic-gate netstat_tcp_verbose_header_pr(void) 780*0Sstevel@tonic-gate { 781*0Sstevel@tonic-gate mdb_printf(" %<u>%-5s %-8s %-8s %-5s %-8s %-8s %5s %5s%</u>\n", 782*0Sstevel@tonic-gate "Swind", "Snext", "Suna", "Rwind", "Rack", "Rnext", "Rto", "Mss"); 783*0Sstevel@tonic-gate } 784*0Sstevel@tonic-gate 785*0Sstevel@tonic-gate /*ARGSUSED*/ 786*0Sstevel@tonic-gate int 787*0Sstevel@tonic-gate netstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 788*0Sstevel@tonic-gate { 789*0Sstevel@tonic-gate uint_t opts = 0; 790*0Sstevel@tonic-gate const char *optf = NULL; 791*0Sstevel@tonic-gate const char *optP = NULL; 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 794*0Sstevel@tonic-gate 'a', MDB_OPT_SETBITS, NETSTAT_ALL, &opts, 795*0Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, NETSTAT_VERBOSE, &opts, 796*0Sstevel@tonic-gate 'f', MDB_OPT_STR, &optf, 797*0Sstevel@tonic-gate 'P', MDB_OPT_STR, &optP, 798*0Sstevel@tonic-gate NULL) != argc) 799*0Sstevel@tonic-gate return (DCMD_USAGE); 800*0Sstevel@tonic-gate 801*0Sstevel@tonic-gate if (optP != NULL) { 802*0Sstevel@tonic-gate if ((strcmp("tcp", optP) != 0) && (strcmp("udp", optP) != 0)) 803*0Sstevel@tonic-gate return (DCMD_USAGE); 804*0Sstevel@tonic-gate 805*0Sstevel@tonic-gate } 806*0Sstevel@tonic-gate 807*0Sstevel@tonic-gate if (optf != NULL) { 808*0Sstevel@tonic-gate if ((strcmp("inet", optf) != 0) && 809*0Sstevel@tonic-gate (strcmp("inet6", optf) != 0) && 810*0Sstevel@tonic-gate (strcmp("unix", optf) != 0)) 811*0Sstevel@tonic-gate return (DCMD_USAGE); 812*0Sstevel@tonic-gate } 813*0Sstevel@tonic-gate 814*0Sstevel@tonic-gate if ((optP == NULL) || (strcmp("tcp", optP) == 0)) { 815*0Sstevel@tonic-gate if ((optf == NULL) || (strcmp("inet", optf) == 0)) { 816*0Sstevel@tonic-gate /* Print TCPv4 connection */ 817*0Sstevel@tonic-gate mdb_printf( 818*0Sstevel@tonic-gate "%<u>%-?s St %*s %*s %s%</u>\n", 819*0Sstevel@tonic-gate "TCPv4", ADDR_V4_WIDTH, "Local Address", 820*0Sstevel@tonic-gate ADDR_V4_WIDTH, "Remote Address", "Zone"); 821*0Sstevel@tonic-gate 822*0Sstevel@tonic-gate if (opts & NETSTAT_VERBOSE) 823*0Sstevel@tonic-gate netstat_tcp_verbose_header_pr(); 824*0Sstevel@tonic-gate 825*0Sstevel@tonic-gate if (mdb_walk("ipcl_tcpconn_cache", netstat_tcpv4_cb, 826*0Sstevel@tonic-gate (void *)(uintptr_t)opts) == -1) { 827*0Sstevel@tonic-gate mdb_warn("failed to walk ipcl_tcpconn_cache"); 828*0Sstevel@tonic-gate return (DCMD_ERR); 829*0Sstevel@tonic-gate } 830*0Sstevel@tonic-gate } 831*0Sstevel@tonic-gate 832*0Sstevel@tonic-gate if ((optf == NULL) || (strcmp("inet6", optf) == 0)) { 833*0Sstevel@tonic-gate /* Print TCPv6 connection */ 834*0Sstevel@tonic-gate mdb_printf( 835*0Sstevel@tonic-gate "%<u>%-?s St %*s %*s %s\n%</u>", 836*0Sstevel@tonic-gate "TCPv6", ADDR_V6_WIDTH, "Local Address", 837*0Sstevel@tonic-gate ADDR_V6_WIDTH, "Remote Address", "Zone"); 838*0Sstevel@tonic-gate 839*0Sstevel@tonic-gate if (opts & NETSTAT_VERBOSE) 840*0Sstevel@tonic-gate netstat_tcp_verbose_header_pr(); 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate if (mdb_walk("ipcl_tcpconn_cache", netstat_tcpv6_cb, 843*0Sstevel@tonic-gate (void *)(uintptr_t)opts) == -1) { 844*0Sstevel@tonic-gate mdb_warn("failed to walk ipcl_tcpconn_cache"); 845*0Sstevel@tonic-gate return (DCMD_ERR); 846*0Sstevel@tonic-gate } 847*0Sstevel@tonic-gate } 848*0Sstevel@tonic-gate } 849*0Sstevel@tonic-gate 850*0Sstevel@tonic-gate if ((optP == NULL) || (strcmp("udp", optP) == 0)) { 851*0Sstevel@tonic-gate if ((optf == NULL) || (strcmp("inet", optf) == 0)) { 852*0Sstevel@tonic-gate /* Print UDPv4 connection */ 853*0Sstevel@tonic-gate mdb_printf( 854*0Sstevel@tonic-gate "%<u>%-?s St %*s %*s %s\n%</u>", 855*0Sstevel@tonic-gate "UDPv4", ADDR_V4_WIDTH, "Local Address", 856*0Sstevel@tonic-gate ADDR_V4_WIDTH, "Remote Address", "Zone"); 857*0Sstevel@tonic-gate 858*0Sstevel@tonic-gate if (mdb_walk("genunix`udp", netstat_udpv4_cb, 859*0Sstevel@tonic-gate (void *)(uintptr_t)opts) == -1) { 860*0Sstevel@tonic-gate mdb_warn("failed to walk genunix`udp"); 861*0Sstevel@tonic-gate return (DCMD_ERR); 862*0Sstevel@tonic-gate } 863*0Sstevel@tonic-gate 864*0Sstevel@tonic-gate } 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate if ((optf == NULL) || (strcmp("inet6", optf) == 0)) { 867*0Sstevel@tonic-gate /* Print UDPv6 connection */ 868*0Sstevel@tonic-gate mdb_printf( 869*0Sstevel@tonic-gate "%<u>%-?s St %*s %*s %s\n%</u>", 870*0Sstevel@tonic-gate "UDPv6", ADDR_V6_WIDTH, "Local Address", 871*0Sstevel@tonic-gate ADDR_V6_WIDTH, "Remote Address", "Zone"); 872*0Sstevel@tonic-gate 873*0Sstevel@tonic-gate if (mdb_walk("genunix`udp", netstat_udpv6_cb, 874*0Sstevel@tonic-gate (void *)(uintptr_t)opts) == -1) { 875*0Sstevel@tonic-gate mdb_warn("failed to walk genunix`udp"); 876*0Sstevel@tonic-gate return (DCMD_ERR); 877*0Sstevel@tonic-gate } 878*0Sstevel@tonic-gate 879*0Sstevel@tonic-gate } 880*0Sstevel@tonic-gate } 881*0Sstevel@tonic-gate 882*0Sstevel@tonic-gate if (((optf == NULL) || (strcmp("unix", optf) == 0)) && (optP == NULL)) { 883*0Sstevel@tonic-gate /* Print Unix Domain Sockets */ 884*0Sstevel@tonic-gate mdb_printf("%<u>%-?s %-10s %-?s %-?s %-14s %-14s %s%</u>\n", 885*0Sstevel@tonic-gate "AF_UNIX", "Type", "Vnode", "Conn", "Local Addr", 886*0Sstevel@tonic-gate "Remote Addr", "Zone"); 887*0Sstevel@tonic-gate 888*0Sstevel@tonic-gate if (mdb_walk("genunix`sonode", netstat_unix_cb, NULL) == -1) { 889*0Sstevel@tonic-gate mdb_warn("failed to walk genunix`sonode"); 890*0Sstevel@tonic-gate return (DCMD_ERR); 891*0Sstevel@tonic-gate } 892*0Sstevel@tonic-gate } 893*0Sstevel@tonic-gate 894*0Sstevel@tonic-gate return (DCMD_OK); 895*0Sstevel@tonic-gate } 896