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 51676Sjpk * Common Development and Distribution License (the "License"). 61676Sjpk * 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 /* 229089SVasumathi.Sundaram@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 <mdb/mdb_modapi.h> 270Sstevel@tonic-gate #include <mdb/mdb_ks.h> 280Sstevel@tonic-gate #include <mdb/mdb_ctf.h> 290Sstevel@tonic-gate #include <sys/types.h> 300Sstevel@tonic-gate #include <sys/tihdr.h> 310Sstevel@tonic-gate #include <inet/led.h> 320Sstevel@tonic-gate #include <inet/common.h> 330Sstevel@tonic-gate #include <netinet/in.h> 340Sstevel@tonic-gate #include <netinet/ip6.h> 350Sstevel@tonic-gate #include <netinet/icmp6.h> 360Sstevel@tonic-gate #include <inet/ip.h> 370Sstevel@tonic-gate #include <inet/ip6.h> 380Sstevel@tonic-gate #include <inet/ipclassifier.h> 390Sstevel@tonic-gate #include <inet/tcp.h> 400Sstevel@tonic-gate #include <sys/stream.h> 410Sstevel@tonic-gate #include <sys/vfs.h> 420Sstevel@tonic-gate #include <sys/stropts.h> 430Sstevel@tonic-gate #include <sys/tpicommon.h> 440Sstevel@tonic-gate #include <sys/socket.h> 450Sstevel@tonic-gate #include <sys/socketvar.h> 460Sstevel@tonic-gate #include <sys/cred_impl.h> 470Sstevel@tonic-gate #include <inet/udp_impl.h> 480Sstevel@tonic-gate #include <inet/arp_impl.h> 490Sstevel@tonic-gate #include <inet/rawip_impl.h> 500Sstevel@tonic-gate #include <inet/mi.h> 518348SEric.Yu@Sun.COM #include <fs/sockfs/socktpi_impl.h> 52*10491SRishi.Srivatsavai@Sun.COM #include <net/bridge_impl.h> 53*10491SRishi.Srivatsavai@Sun.COM #include <io/trill_impl.h> 54*10491SRishi.Srivatsavai@Sun.COM #include <sys/mac_impl.h> 550Sstevel@tonic-gate 560Sstevel@tonic-gate #define ADDR_V6_WIDTH 23 570Sstevel@tonic-gate #define ADDR_V4_WIDTH 15 580Sstevel@tonic-gate 591676Sjpk #define NETSTAT_ALL 0x01 601676Sjpk #define NETSTAT_VERBOSE 0x02 611676Sjpk #define NETSTAT_ROUTE 0x04 621676Sjpk #define NETSTAT_V4 0x08 631676Sjpk #define NETSTAT_V6 0x10 641676Sjpk #define NETSTAT_UNIX 0x20 651676Sjpk 661676Sjpk #define NETSTAT_FIRST 0x80000000u 670Sstevel@tonic-gate 689089SVasumathi.Sundaram@Sun.COM typedef struct netstat_cb_data_s { 699089SVasumathi.Sundaram@Sun.COM uint_t opts; 709089SVasumathi.Sundaram@Sun.COM conn_t conn; 719089SVasumathi.Sundaram@Sun.COM int af; 729089SVasumathi.Sundaram@Sun.COM } netstat_cb_data_t; 733448Sdh155122 743448Sdh155122 /* Walkers for various *_stack_t */ 753448Sdh155122 int 763448Sdh155122 ar_stacks_walk_init(mdb_walk_state_t *wsp) 773448Sdh155122 { 783448Sdh155122 if (mdb_layered_walk("netstack", wsp) == -1) { 793448Sdh155122 mdb_warn("can't walk 'netstack'"); 803448Sdh155122 return (WALK_ERR); 813448Sdh155122 } 823448Sdh155122 return (WALK_NEXT); 833448Sdh155122 } 843448Sdh155122 853448Sdh155122 int 863448Sdh155122 ar_stacks_walk_step(mdb_walk_state_t *wsp) 873448Sdh155122 { 883448Sdh155122 uintptr_t kaddr; 893448Sdh155122 netstack_t nss; 903448Sdh155122 913448Sdh155122 if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) { 923448Sdh155122 mdb_warn("can't read netstack at %p", wsp->walk_addr); 933448Sdh155122 return (WALK_ERR); 943448Sdh155122 } 953448Sdh155122 kaddr = (uintptr_t)nss.netstack_modules[NS_ARP]; 963448Sdh155122 return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata)); 973448Sdh155122 } 983448Sdh155122 993448Sdh155122 int 1003448Sdh155122 icmp_stacks_walk_init(mdb_walk_state_t *wsp) 1013448Sdh155122 { 1023448Sdh155122 if (mdb_layered_walk("netstack", wsp) == -1) { 1033448Sdh155122 mdb_warn("can't walk 'netstack'"); 1043448Sdh155122 return (WALK_ERR); 1053448Sdh155122 } 1063448Sdh155122 return (WALK_NEXT); 1073448Sdh155122 } 1083448Sdh155122 1093448Sdh155122 int 1103448Sdh155122 icmp_stacks_walk_step(mdb_walk_state_t *wsp) 1113448Sdh155122 { 1123448Sdh155122 uintptr_t kaddr; 1133448Sdh155122 netstack_t nss; 1143448Sdh155122 1153448Sdh155122 if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) { 1163448Sdh155122 mdb_warn("can't read netstack at %p", wsp->walk_addr); 1173448Sdh155122 return (WALK_ERR); 1183448Sdh155122 } 1193448Sdh155122 kaddr = (uintptr_t)nss.netstack_modules[NS_ICMP]; 1203448Sdh155122 return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata)); 1213448Sdh155122 } 1223448Sdh155122 1233448Sdh155122 int 1243448Sdh155122 tcp_stacks_walk_init(mdb_walk_state_t *wsp) 1253448Sdh155122 { 1263448Sdh155122 if (mdb_layered_walk("netstack", wsp) == -1) { 1273448Sdh155122 mdb_warn("can't walk 'netstack'"); 1283448Sdh155122 return (WALK_ERR); 1293448Sdh155122 } 1303448Sdh155122 return (WALK_NEXT); 1313448Sdh155122 } 1323448Sdh155122 1333448Sdh155122 int 1343448Sdh155122 tcp_stacks_walk_step(mdb_walk_state_t *wsp) 1353448Sdh155122 { 1363448Sdh155122 uintptr_t kaddr; 1373448Sdh155122 netstack_t nss; 1383448Sdh155122 1393448Sdh155122 if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) { 1403448Sdh155122 mdb_warn("can't read netstack at %p", wsp->walk_addr); 1413448Sdh155122 return (WALK_ERR); 1423448Sdh155122 } 1433448Sdh155122 kaddr = (uintptr_t)nss.netstack_modules[NS_TCP]; 1443448Sdh155122 return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata)); 1453448Sdh155122 } 1463448Sdh155122 1473448Sdh155122 int 1483448Sdh155122 udp_stacks_walk_init(mdb_walk_state_t *wsp) 1493448Sdh155122 { 1503448Sdh155122 if (mdb_layered_walk("netstack", wsp) == -1) { 1513448Sdh155122 mdb_warn("can't walk 'netstack'"); 1523448Sdh155122 return (WALK_ERR); 1533448Sdh155122 } 1543448Sdh155122 return (WALK_NEXT); 1553448Sdh155122 } 1563448Sdh155122 1573448Sdh155122 int 1583448Sdh155122 udp_stacks_walk_step(mdb_walk_state_t *wsp) 1593448Sdh155122 { 1603448Sdh155122 uintptr_t kaddr; 1613448Sdh155122 netstack_t nss; 1623448Sdh155122 1633448Sdh155122 if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) { 1643448Sdh155122 mdb_warn("can't read netstack at %p", wsp->walk_addr); 1653448Sdh155122 return (WALK_ERR); 1663448Sdh155122 } 1673448Sdh155122 kaddr = (uintptr_t)nss.netstack_modules[NS_UDP]; 1683448Sdh155122 return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata)); 1693448Sdh155122 } 1703448Sdh155122 1710Sstevel@tonic-gate /* 1720Sstevel@tonic-gate * Print an IPv4 address and port number in a compact and easy to read format 1730Sstevel@tonic-gate * The arguments are in network byte order 1740Sstevel@tonic-gate */ 1750Sstevel@tonic-gate static void 1760Sstevel@tonic-gate net_ipv4addrport_pr(const in6_addr_t *nipv6addr, in_port_t nport) 1770Sstevel@tonic-gate { 1780Sstevel@tonic-gate uint32_t naddr = V4_PART_OF_V6((*nipv6addr)); 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate mdb_nhconvert(&nport, &nport, sizeof (nport)); 1810Sstevel@tonic-gate mdb_printf("%*I.%-5hu", ADDR_V4_WIDTH, naddr, nport); 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate /* 1850Sstevel@tonic-gate * Print an IPv6 address and port number in a compact and easy to read format 1860Sstevel@tonic-gate * The arguments are in network byte order 1870Sstevel@tonic-gate */ 1880Sstevel@tonic-gate static void 1890Sstevel@tonic-gate net_ipv6addrport_pr(const in6_addr_t *naddr, in_port_t nport) 1900Sstevel@tonic-gate { 1910Sstevel@tonic-gate mdb_nhconvert(&nport, &nport, sizeof (nport)); 1920Sstevel@tonic-gate mdb_printf("%*N.%-5hu", ADDR_V6_WIDTH, naddr, nport); 1930Sstevel@tonic-gate } 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate static int 1960Sstevel@tonic-gate net_tcp_active(const tcp_t *tcp) 1970Sstevel@tonic-gate { 1980Sstevel@tonic-gate return (tcp->tcp_state >= TCPS_ESTABLISHED); 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate static int 2020Sstevel@tonic-gate net_tcp_ipv4(const tcp_t *tcp) 2030Sstevel@tonic-gate { 2040Sstevel@tonic-gate return ((tcp->tcp_ipversion == IPV4_VERSION) || 2050Sstevel@tonic-gate (IN6_IS_ADDR_UNSPECIFIED(&tcp->tcp_ip_src_v6) && 2060Sstevel@tonic-gate (tcp->tcp_state <= TCPS_LISTEN))); 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate static int 2100Sstevel@tonic-gate net_tcp_ipv6(const tcp_t *tcp) 2110Sstevel@tonic-gate { 2120Sstevel@tonic-gate return (tcp->tcp_ipversion == IPV6_VERSION); 2130Sstevel@tonic-gate } 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate static int 2160Sstevel@tonic-gate net_udp_active(const udp_t *udp) 2170Sstevel@tonic-gate { 218741Smasputra return ((udp->udp_state == TS_IDLE) || 219741Smasputra (udp->udp_state == TS_DATA_XFER)); 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate static int 2230Sstevel@tonic-gate net_udp_ipv4(const udp_t *udp) 2240Sstevel@tonic-gate { 2250Sstevel@tonic-gate return ((udp->udp_ipversion == IPV4_VERSION) || 2260Sstevel@tonic-gate (IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src) && 2270Sstevel@tonic-gate (udp->udp_state <= TS_IDLE))); 2280Sstevel@tonic-gate } 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate static int 2310Sstevel@tonic-gate net_udp_ipv6(const udp_t *udp) 2320Sstevel@tonic-gate { 2330Sstevel@tonic-gate return (udp->udp_ipversion == IPV6_VERSION); 2340Sstevel@tonic-gate } 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate int 2370Sstevel@tonic-gate sonode_walk_init(mdb_walk_state_t *wsp) 2380Sstevel@tonic-gate { 2390Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 2400Sstevel@tonic-gate GElf_Sym sym; 2410Sstevel@tonic-gate struct socklist *slp; 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate if (mdb_lookup_by_obj("sockfs", "socklist", &sym) == -1) { 2440Sstevel@tonic-gate mdb_warn("failed to lookup sockfs`socklist"); 2450Sstevel@tonic-gate return (WALK_ERR); 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate slp = (struct socklist *)(uintptr_t)sym.st_value; 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr), 2510Sstevel@tonic-gate (uintptr_t)&slp->sl_list) == -1) { 2520Sstevel@tonic-gate mdb_warn("failed to read address of initial sonode " 2530Sstevel@tonic-gate "at %p", &slp->sl_list); 2540Sstevel@tonic-gate return (WALK_ERR); 2550Sstevel@tonic-gate } 2560Sstevel@tonic-gate } 2570Sstevel@tonic-gate 2588348SEric.Yu@Sun.COM wsp->walk_data = mdb_alloc(sizeof (struct sotpi_sonode), UM_SLEEP); 2590Sstevel@tonic-gate return (WALK_NEXT); 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate int 2630Sstevel@tonic-gate sonode_walk_step(mdb_walk_state_t *wsp) 2640Sstevel@tonic-gate { 2650Sstevel@tonic-gate int status; 2668348SEric.Yu@Sun.COM struct sotpi_sonode *stp; 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate if (wsp->walk_addr == NULL) 2690Sstevel@tonic-gate return (WALK_DONE); 2700Sstevel@tonic-gate 2718348SEric.Yu@Sun.COM if (mdb_vread(wsp->walk_data, sizeof (struct sotpi_sonode), 2720Sstevel@tonic-gate wsp->walk_addr) == -1) { 2730Sstevel@tonic-gate mdb_warn("failed to read sonode at %p", wsp->walk_addr); 2740Sstevel@tonic-gate return (WALK_ERR); 2750Sstevel@tonic-gate } 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 2780Sstevel@tonic-gate wsp->walk_cbdata); 2790Sstevel@tonic-gate 2808348SEric.Yu@Sun.COM stp = wsp->walk_data; 2810Sstevel@tonic-gate 2828348SEric.Yu@Sun.COM wsp->walk_addr = (uintptr_t)stp->st_info.sti_next_so; 2830Sstevel@tonic-gate return (status); 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate void 2870Sstevel@tonic-gate sonode_walk_fini(mdb_walk_state_t *wsp) 2880Sstevel@tonic-gate { 2898348SEric.Yu@Sun.COM mdb_free(wsp->walk_data, sizeof (struct sotpi_sonode)); 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate struct mi_walk_data { 2930Sstevel@tonic-gate uintptr_t mi_wd_miofirst; 2940Sstevel@tonic-gate MI_O mi_wd_miodata; 2950Sstevel@tonic-gate }; 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate int 2980Sstevel@tonic-gate mi_walk_init(mdb_walk_state_t *wsp) 2990Sstevel@tonic-gate { 3000Sstevel@tonic-gate struct mi_walk_data *wdp; 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 3030Sstevel@tonic-gate mdb_warn("mi doesn't support global walks\n"); 3040Sstevel@tonic-gate return (WALK_ERR); 3050Sstevel@tonic-gate } 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate wdp = mdb_alloc(sizeof (struct mi_walk_data), UM_SLEEP); 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate /* So that we do not immediately return WALK_DONE below */ 3100Sstevel@tonic-gate wdp->mi_wd_miofirst = NULL; 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate wsp->walk_data = wdp; 3130Sstevel@tonic-gate return (WALK_NEXT); 3140Sstevel@tonic-gate } 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate int 3170Sstevel@tonic-gate mi_walk_step(mdb_walk_state_t *wsp) 3180Sstevel@tonic-gate { 3190Sstevel@tonic-gate struct mi_walk_data *wdp = wsp->walk_data; 3200Sstevel@tonic-gate MI_OP miop = &wdp->mi_wd_miodata; 3210Sstevel@tonic-gate int status; 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate /* Always false in the first iteration */ 3240Sstevel@tonic-gate if ((wsp->walk_addr == (uintptr_t)NULL) || 3250Sstevel@tonic-gate (wsp->walk_addr == wdp->mi_wd_miofirst)) { 3260Sstevel@tonic-gate return (WALK_DONE); 3270Sstevel@tonic-gate } 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate if (mdb_vread(miop, sizeof (MI_O), wsp->walk_addr) == -1) { 3300Sstevel@tonic-gate mdb_warn("failed to read MI object at %p", wsp->walk_addr); 3310Sstevel@tonic-gate return (WALK_ERR); 3320Sstevel@tonic-gate } 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate /* Only true in the first iteration */ 3353448Sdh155122 if (wdp->mi_wd_miofirst == NULL) { 3360Sstevel@tonic-gate wdp->mi_wd_miofirst = wsp->walk_addr; 3373448Sdh155122 status = WALK_NEXT; 3383448Sdh155122 } else { 3393448Sdh155122 status = wsp->walk_callback(wsp->walk_addr + sizeof (MI_O), 3403448Sdh155122 &miop[1], wsp->walk_cbdata); 3413448Sdh155122 } 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)miop->mi_o_next; 3440Sstevel@tonic-gate return (status); 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate void 3480Sstevel@tonic-gate mi_walk_fini(mdb_walk_state_t *wsp) 3490Sstevel@tonic-gate { 3500Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (struct mi_walk_data)); 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate typedef struct mi_payload_walk_arg_s { 3543448Sdh155122 const char *mi_pwa_walker; /* Underlying walker */ 3553448Sdh155122 const off_t mi_pwa_head_off; /* Offset for mi_o_head_t * in stack */ 3560Sstevel@tonic-gate const size_t mi_pwa_size; /* size of mi payload */ 3570Sstevel@tonic-gate const uint_t mi_pwa_flags; /* device and/or module */ 3580Sstevel@tonic-gate } mi_payload_walk_arg_t; 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate #define MI_PAYLOAD_DEVICE 0x1 3610Sstevel@tonic-gate #define MI_PAYLOAD_MODULE 0x2 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate int 3640Sstevel@tonic-gate mi_payload_walk_init(mdb_walk_state_t *wsp) 3650Sstevel@tonic-gate { 3660Sstevel@tonic-gate const mi_payload_walk_arg_t *arg = wsp->walk_arg; 3670Sstevel@tonic-gate 3683448Sdh155122 if (mdb_layered_walk(arg->mi_pwa_walker, wsp) == -1) { 3693448Sdh155122 mdb_warn("can't walk '%s'", arg->mi_pwa_walker); 3700Sstevel@tonic-gate return (WALK_ERR); 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate return (WALK_NEXT); 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate int 3760Sstevel@tonic-gate mi_payload_walk_step(mdb_walk_state_t *wsp) 3770Sstevel@tonic-gate { 3780Sstevel@tonic-gate const mi_payload_walk_arg_t *arg = wsp->walk_arg; 3793448Sdh155122 uintptr_t kaddr; 3800Sstevel@tonic-gate 3813448Sdh155122 kaddr = wsp->walk_addr + arg->mi_pwa_head_off; 3820Sstevel@tonic-gate 3833448Sdh155122 if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) { 3843448Sdh155122 mdb_warn("can't read address of mi head at %p for %s", 3853448Sdh155122 kaddr, arg->mi_pwa_walker); 3860Sstevel@tonic-gate return (WALK_ERR); 3870Sstevel@tonic-gate } 3880Sstevel@tonic-gate 3893448Sdh155122 if (kaddr == 0) { 3903448Sdh155122 /* Empty list */ 3913448Sdh155122 return (WALK_DONE); 3923448Sdh155122 } 3930Sstevel@tonic-gate 3943448Sdh155122 if (mdb_pwalk("genunix`mi", wsp->walk_callback, 3953448Sdh155122 wsp->walk_cbdata, kaddr) == -1) { 3963448Sdh155122 mdb_warn("failed to walk genunix`mi"); 3973448Sdh155122 return (WALK_ERR); 3983448Sdh155122 } 3993448Sdh155122 return (WALK_NEXT); 4000Sstevel@tonic-gate } 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate const mi_payload_walk_arg_t mi_ar_arg = { 4033448Sdh155122 "ar_stacks", OFFSETOF(arp_stack_t, as_head), sizeof (ar_t), 4040Sstevel@tonic-gate MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE 4050Sstevel@tonic-gate }; 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate const mi_payload_walk_arg_t mi_icmp_arg = { 4083448Sdh155122 "icmp_stacks", OFFSETOF(icmp_stack_t, is_head), sizeof (icmp_t), 4090Sstevel@tonic-gate MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE 4100Sstevel@tonic-gate }; 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate int 4130Sstevel@tonic-gate sonode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 4140Sstevel@tonic-gate { 4150Sstevel@tonic-gate const char *optf = NULL; 4160Sstevel@tonic-gate const char *optt = NULL; 4170Sstevel@tonic-gate const char *optp = NULL; 4180Sstevel@tonic-gate int family, type, proto; 4190Sstevel@tonic-gate int filter = 0; 4200Sstevel@tonic-gate struct sonode so; 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 4230Sstevel@tonic-gate if (mdb_walk_dcmd("genunix`sonode", "genunix`sonode", argc, 4240Sstevel@tonic-gate argv) == -1) { 4250Sstevel@tonic-gate mdb_warn("failed to walk sonode"); 4260Sstevel@tonic-gate return (DCMD_ERR); 4270Sstevel@tonic-gate } 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate return (DCMD_OK); 4300Sstevel@tonic-gate } 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate if (mdb_getopts(argc, argv, 4330Sstevel@tonic-gate 'f', MDB_OPT_STR, &optf, 4340Sstevel@tonic-gate 't', MDB_OPT_STR, &optt, 4350Sstevel@tonic-gate 'p', MDB_OPT_STR, &optp, 4360Sstevel@tonic-gate NULL) != argc) 4370Sstevel@tonic-gate return (DCMD_USAGE); 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate if (optf != NULL) { 4400Sstevel@tonic-gate if (strcmp("inet", optf) == 0) 4410Sstevel@tonic-gate family = AF_INET; 4420Sstevel@tonic-gate else if (strcmp("inet6", optf) == 0) 4430Sstevel@tonic-gate family = AF_INET6; 4440Sstevel@tonic-gate else if (strcmp("unix", optf) == 0) 4450Sstevel@tonic-gate family = AF_UNIX; 4460Sstevel@tonic-gate else 4470Sstevel@tonic-gate family = mdb_strtoull(optf); 4480Sstevel@tonic-gate filter = 1; 4490Sstevel@tonic-gate } 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate if (optt != NULL) { 4520Sstevel@tonic-gate if (strcmp("stream", optt) == 0) 4530Sstevel@tonic-gate type = SOCK_STREAM; 4540Sstevel@tonic-gate else if (strcmp("dgram", optt) == 0) 4550Sstevel@tonic-gate type = SOCK_DGRAM; 4560Sstevel@tonic-gate else if (strcmp("raw", optt) == 0) 4570Sstevel@tonic-gate type = SOCK_RAW; 4580Sstevel@tonic-gate else 4590Sstevel@tonic-gate type = mdb_strtoull(optt); 4600Sstevel@tonic-gate filter = 1; 4610Sstevel@tonic-gate } 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate if (optp != NULL) { 4640Sstevel@tonic-gate proto = mdb_strtoull(optp); 4650Sstevel@tonic-gate filter = 1; 4660Sstevel@tonic-gate } 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && !filter) { 4690Sstevel@tonic-gate mdb_printf("%<u>%-?s Family Type Proto State Mode Flag " 4700Sstevel@tonic-gate "AccessVP%</u>\n", "Sonode:"); 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate if (mdb_vread(&so, sizeof (so), addr) == -1) { 4740Sstevel@tonic-gate mdb_warn("failed to read sonode at %p", addr); 4750Sstevel@tonic-gate return (DCMD_ERR); 4760Sstevel@tonic-gate } 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate if ((optf != NULL) && (so.so_family != family)) 4790Sstevel@tonic-gate return (DCMD_OK); 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate if ((optt != NULL) && (so.so_type != type)) 4820Sstevel@tonic-gate return (DCMD_OK); 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate if ((optp != NULL) && (so.so_protocol != proto)) 4850Sstevel@tonic-gate return (DCMD_OK); 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate if (filter) { 4880Sstevel@tonic-gate mdb_printf("%0?p\n", addr); 4890Sstevel@tonic-gate return (DCMD_OK); 4900Sstevel@tonic-gate } 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate mdb_printf("%0?p ", addr); 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate switch (so.so_family) { 4955563Snordmark case AF_UNIX: 4960Sstevel@tonic-gate mdb_printf("unix "); 4970Sstevel@tonic-gate break; 4985563Snordmark case AF_INET: 4990Sstevel@tonic-gate mdb_printf("inet "); 5000Sstevel@tonic-gate break; 5015563Snordmark case AF_INET6: 5020Sstevel@tonic-gate mdb_printf("inet6 "); 5030Sstevel@tonic-gate break; 5045563Snordmark default: 5050Sstevel@tonic-gate mdb_printf("%6hi", so.so_family); 5060Sstevel@tonic-gate } 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate switch (so.so_type) { 5095563Snordmark case SOCK_STREAM: 5100Sstevel@tonic-gate mdb_printf(" strm"); 5110Sstevel@tonic-gate break; 5125563Snordmark case SOCK_DGRAM: 5130Sstevel@tonic-gate mdb_printf(" dgrm"); 5140Sstevel@tonic-gate break; 5155563Snordmark case SOCK_RAW: 5160Sstevel@tonic-gate mdb_printf(" raw "); 5170Sstevel@tonic-gate break; 5185563Snordmark default: 5190Sstevel@tonic-gate mdb_printf(" %4hi", so.so_type); 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate 5228348SEric.Yu@Sun.COM mdb_printf(" %5hi %05x %04x %04hx\n", 5230Sstevel@tonic-gate so.so_protocol, so.so_state, so.so_mode, 5248348SEric.Yu@Sun.COM so.so_flag); 5250Sstevel@tonic-gate 5260Sstevel@tonic-gate return (DCMD_OK); 5270Sstevel@tonic-gate } 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate #define MI_PAYLOAD 0x1 5300Sstevel@tonic-gate #define MI_DEVICE 0x2 5310Sstevel@tonic-gate #define MI_MODULE 0x4 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate int 5340Sstevel@tonic-gate mi(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 5350Sstevel@tonic-gate { 5360Sstevel@tonic-gate uint_t opts = 0; 5370Sstevel@tonic-gate MI_O mio; 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 5400Sstevel@tonic-gate return (DCMD_USAGE); 5410Sstevel@tonic-gate 5420Sstevel@tonic-gate if (mdb_getopts(argc, argv, 5430Sstevel@tonic-gate 'p', MDB_OPT_SETBITS, MI_PAYLOAD, &opts, 5440Sstevel@tonic-gate 'd', MDB_OPT_SETBITS, MI_DEVICE, &opts, 5450Sstevel@tonic-gate 'm', MDB_OPT_SETBITS, MI_MODULE, &opts, 5460Sstevel@tonic-gate NULL) != argc) 5470Sstevel@tonic-gate return (DCMD_USAGE); 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate if ((opts & (MI_DEVICE | MI_MODULE)) == (MI_DEVICE | MI_MODULE)) { 5500Sstevel@tonic-gate mdb_warn("at most one filter, d for devices or m " 5510Sstevel@tonic-gate "for modules, may be specified\n"); 5520Sstevel@tonic-gate return (DCMD_USAGE); 5530Sstevel@tonic-gate } 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate if ((opts == 0) && (DCMD_HDRSPEC(flags))) { 5560Sstevel@tonic-gate mdb_printf("%<u>%-?s %-?s %-?s IsDev Dev%</u>\n", 5570Sstevel@tonic-gate "MI_O", "Next", "Prev"); 5580Sstevel@tonic-gate } 5590Sstevel@tonic-gate 5600Sstevel@tonic-gate if (mdb_vread(&mio, sizeof (mio), addr) == -1) { 5610Sstevel@tonic-gate mdb_warn("failed to read mi object MI_O at %p", addr); 5620Sstevel@tonic-gate return (DCMD_ERR); 5630Sstevel@tonic-gate } 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate if (opts != 0) { 5660Sstevel@tonic-gate if (mio.mi_o_isdev == B_FALSE) { 5670Sstevel@tonic-gate /* mio is a module */ 5680Sstevel@tonic-gate if (!(opts & MI_MODULE) && (opts & MI_DEVICE)) 5690Sstevel@tonic-gate return (DCMD_OK); 5700Sstevel@tonic-gate } else { 5710Sstevel@tonic-gate /* mio is a device */ 5720Sstevel@tonic-gate if (!(opts & MI_DEVICE) && (opts & MI_MODULE)) 5730Sstevel@tonic-gate return (DCMD_OK); 5740Sstevel@tonic-gate } 5750Sstevel@tonic-gate 5760Sstevel@tonic-gate if (opts & MI_PAYLOAD) 5770Sstevel@tonic-gate mdb_printf("%p\n", addr + sizeof (MI_O)); 5780Sstevel@tonic-gate else 5790Sstevel@tonic-gate mdb_printf("%p\n", addr); 5800Sstevel@tonic-gate return (DCMD_OK); 5810Sstevel@tonic-gate } 5820Sstevel@tonic-gate 5830Sstevel@tonic-gate mdb_printf("%0?p %0?p %0?p ", addr, mio.mi_o_next, mio.mi_o_prev); 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate if (mio.mi_o_isdev == B_FALSE) 5860Sstevel@tonic-gate mdb_printf("FALSE"); 5870Sstevel@tonic-gate else 5880Sstevel@tonic-gate mdb_printf("TRUE "); 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate mdb_printf(" %0?p\n", mio.mi_o_dev); 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate return (DCMD_OK); 5930Sstevel@tonic-gate } 5940Sstevel@tonic-gate 5953448Sdh155122 static int 5963448Sdh155122 ns_to_stackid(uintptr_t kaddr) 5973448Sdh155122 { 5983448Sdh155122 netstack_t nss; 5993448Sdh155122 6003448Sdh155122 if (mdb_vread(&nss, sizeof (nss), kaddr) == -1) { 6013448Sdh155122 mdb_warn("failed to read netstack_t %p", kaddr); 6023448Sdh155122 return (0); 6033448Sdh155122 } 6043448Sdh155122 return (nss.netstack_stackid); 6053448Sdh155122 } 6063448Sdh155122 6073448Sdh155122 6083448Sdh155122 6090Sstevel@tonic-gate static void 6100Sstevel@tonic-gate netstat_tcp_verbose_pr(const tcp_t *tcp) 6110Sstevel@tonic-gate { 6120Sstevel@tonic-gate mdb_printf(" %5i %08x %08x %5i %08x %08x %5li %5i\n", 6130Sstevel@tonic-gate tcp->tcp_swnd, tcp->tcp_snxt, tcp->tcp_suna, tcp->tcp_rwnd, 6140Sstevel@tonic-gate tcp->tcp_rack, tcp->tcp_rnxt, tcp->tcp_rto, tcp->tcp_mss); 6150Sstevel@tonic-gate } 6160Sstevel@tonic-gate 6170Sstevel@tonic-gate /*ARGSUSED*/ 6180Sstevel@tonic-gate static int 6199089SVasumathi.Sundaram@Sun.COM netstat_tcp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 6200Sstevel@tonic-gate { 6219089SVasumathi.Sundaram@Sun.COM netstat_cb_data_t *ncb = cb_data; 6229089SVasumathi.Sundaram@Sun.COM uint_t opts = ncb->opts; 6239089SVasumathi.Sundaram@Sun.COM int af = ncb->af; 6240Sstevel@tonic-gate uintptr_t tcp_kaddr; 6259089SVasumathi.Sundaram@Sun.COM conn_t *connp = &ncb->conn; 6265563Snordmark tcp_t tcps, *tcp; 6270Sstevel@tonic-gate 6289089SVasumathi.Sundaram@Sun.COM if (mdb_vread(connp, sizeof (conn_t), kaddr) == -1) { 6295563Snordmark mdb_warn("failed to read conn_t at %p", kaddr); 6305563Snordmark return (WALK_ERR); 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate 6335563Snordmark tcp_kaddr = (uintptr_t)connp->conn_tcp; 6345563Snordmark if (mdb_vread(&tcps, sizeof (tcp_t), tcp_kaddr) == -1) { 6355563Snordmark mdb_warn("failed to read tcp_t at %p", kaddr); 6360Sstevel@tonic-gate return (WALK_ERR); 6370Sstevel@tonic-gate } 6380Sstevel@tonic-gate 6395563Snordmark tcp = &tcps; 6400Sstevel@tonic-gate connp->conn_tcp = tcp; 6410Sstevel@tonic-gate tcp->tcp_connp = connp; 6420Sstevel@tonic-gate 643741Smasputra if (!((opts & NETSTAT_ALL) || net_tcp_active(tcp)) || 6440Sstevel@tonic-gate (af == AF_INET && !net_tcp_ipv4(tcp)) || 6450Sstevel@tonic-gate (af == AF_INET6 && !net_tcp_ipv6(tcp))) { 6460Sstevel@tonic-gate return (WALK_NEXT); 6470Sstevel@tonic-gate } 6480Sstevel@tonic-gate 6490Sstevel@tonic-gate mdb_printf("%0?p %2i ", tcp_kaddr, tcp->tcp_state); 6500Sstevel@tonic-gate if (af == AF_INET) { 6510Sstevel@tonic-gate net_ipv4addrport_pr(&tcp->tcp_ip_src_v6, tcp->tcp_lport); 6520Sstevel@tonic-gate mdb_printf(" "); 6530Sstevel@tonic-gate net_ipv4addrport_pr(&tcp->tcp_remote_v6, tcp->tcp_fport); 6540Sstevel@tonic-gate } else if (af == AF_INET6) { 6550Sstevel@tonic-gate net_ipv6addrport_pr(&tcp->tcp_ip_src_v6, tcp->tcp_lport); 6560Sstevel@tonic-gate mdb_printf(" "); 6570Sstevel@tonic-gate net_ipv6addrport_pr(&tcp->tcp_remote_v6, tcp->tcp_fport); 6580Sstevel@tonic-gate } 6599089SVasumathi.Sundaram@Sun.COM mdb_printf(" %5i", ns_to_stackid((uintptr_t)connp->conn_netstack)); 6600Sstevel@tonic-gate mdb_printf(" %4i\n", connp->conn_zoneid); 6610Sstevel@tonic-gate if (opts & NETSTAT_VERBOSE) 6620Sstevel@tonic-gate netstat_tcp_verbose_pr(tcp); 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate return (WALK_NEXT); 6650Sstevel@tonic-gate } 6660Sstevel@tonic-gate 667741Smasputra /*ARGSUSED*/ 6680Sstevel@tonic-gate static int 6699089SVasumathi.Sundaram@Sun.COM netstat_udp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 6700Sstevel@tonic-gate { 6719089SVasumathi.Sundaram@Sun.COM netstat_cb_data_t *ncb = cb_data; 6729089SVasumathi.Sundaram@Sun.COM uint_t opts = ncb->opts; 6739089SVasumathi.Sundaram@Sun.COM int af = ncb->af; 674741Smasputra udp_t udp; 6759089SVasumathi.Sundaram@Sun.COM conn_t *connp = &ncb->conn; 6769089SVasumathi.Sundaram@Sun.COM char *state; 677741Smasputra 6789089SVasumathi.Sundaram@Sun.COM if (mdb_vread(connp, sizeof (conn_t), kaddr) == -1) { 6795563Snordmark mdb_warn("failed to read conn_t at %p", kaddr); 680741Smasputra return (WALK_ERR); 681741Smasputra } 6820Sstevel@tonic-gate 6835563Snordmark if (mdb_vread(&udp, sizeof (udp_t), 6849089SVasumathi.Sundaram@Sun.COM (uintptr_t)connp->conn_udp) == -1) { 6855563Snordmark mdb_warn("failed to read conn_udp at %p", 6869089SVasumathi.Sundaram@Sun.COM (uintptr_t)connp->conn_udp); 687741Smasputra return (WALK_ERR); 688741Smasputra } 6890Sstevel@tonic-gate 690741Smasputra if (!((opts & NETSTAT_ALL) || net_udp_active(&udp)) || 691741Smasputra (af == AF_INET && !net_udp_ipv4(&udp)) || 692741Smasputra (af == AF_INET6 && !net_udp_ipv6(&udp))) { 693741Smasputra return (WALK_NEXT); 694741Smasputra } 695741Smasputra 6969089SVasumathi.Sundaram@Sun.COM if (udp.udp_state == TS_UNBND) 6979089SVasumathi.Sundaram@Sun.COM state = "UNBOUND"; 6989089SVasumathi.Sundaram@Sun.COM else if (udp.udp_state == TS_IDLE) 6999089SVasumathi.Sundaram@Sun.COM state = "IDLE"; 7009089SVasumathi.Sundaram@Sun.COM else if (udp.udp_state == TS_DATA_XFER) 7019089SVasumathi.Sundaram@Sun.COM state = "CONNECTED"; 7029089SVasumathi.Sundaram@Sun.COM else 7039089SVasumathi.Sundaram@Sun.COM state = "UNKNOWN"; 7049089SVasumathi.Sundaram@Sun.COM 7059089SVasumathi.Sundaram@Sun.COM mdb_printf("%0?p %10s ", (uintptr_t)connp->conn_udp, state); 706741Smasputra if (af == AF_INET) { 707741Smasputra net_ipv4addrport_pr(&udp.udp_v6src, udp.udp_port); 708741Smasputra mdb_printf(" "); 709741Smasputra net_ipv4addrport_pr(&udp.udp_v6dst, udp.udp_dstport); 710741Smasputra } else if (af == AF_INET6) { 711741Smasputra net_ipv6addrport_pr(&udp.udp_v6src, udp.udp_port); 712741Smasputra mdb_printf(" "); 713741Smasputra net_ipv6addrport_pr(&udp.udp_v6dst, udp.udp_dstport); 714741Smasputra } 7159089SVasumathi.Sundaram@Sun.COM mdb_printf(" %5i", ns_to_stackid((uintptr_t)connp->conn_netstack)); 7169089SVasumathi.Sundaram@Sun.COM mdb_printf(" %4i\n", connp->conn_zoneid); 7170Sstevel@tonic-gate 7180Sstevel@tonic-gate return (WALK_NEXT); 7190Sstevel@tonic-gate } 7200Sstevel@tonic-gate 7219089SVasumathi.Sundaram@Sun.COM /*ARGSUSED*/ 7220Sstevel@tonic-gate static int 7239089SVasumathi.Sundaram@Sun.COM netstat_icmp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 724741Smasputra { 7259089SVasumathi.Sundaram@Sun.COM netstat_cb_data_t *ncb = cb_data; 7269089SVasumathi.Sundaram@Sun.COM int af = ncb->af; 7279089SVasumathi.Sundaram@Sun.COM icmp_t icmp; 7289089SVasumathi.Sundaram@Sun.COM conn_t *connp = &ncb->conn; 7299089SVasumathi.Sundaram@Sun.COM char *state; 7309089SVasumathi.Sundaram@Sun.COM 7319089SVasumathi.Sundaram@Sun.COM if (mdb_vread(connp, sizeof (conn_t), kaddr) == -1) { 7329089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read conn_t at %p", kaddr); 7339089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 7349089SVasumathi.Sundaram@Sun.COM } 7359089SVasumathi.Sundaram@Sun.COM 7369089SVasumathi.Sundaram@Sun.COM if (mdb_vread(&icmp, sizeof (icmp_t), 7379089SVasumathi.Sundaram@Sun.COM (uintptr_t)connp->conn_icmp) == -1) { 7389089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to read conn_icmp at %p", 7399089SVasumathi.Sundaram@Sun.COM (uintptr_t)connp->conn_icmp); 7409089SVasumathi.Sundaram@Sun.COM return (WALK_ERR); 7419089SVasumathi.Sundaram@Sun.COM } 7429089SVasumathi.Sundaram@Sun.COM 7439089SVasumathi.Sundaram@Sun.COM if ((af == AF_INET && icmp.icmp_ipversion != IPV4_VERSION) || 7449089SVasumathi.Sundaram@Sun.COM (af == AF_INET6 && icmp.icmp_ipversion != IPV6_VERSION)) { 7459089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 7469089SVasumathi.Sundaram@Sun.COM } 747741Smasputra 7489089SVasumathi.Sundaram@Sun.COM if (icmp.icmp_state == TS_UNBND) 7499089SVasumathi.Sundaram@Sun.COM state = "UNBOUND"; 7509089SVasumathi.Sundaram@Sun.COM else if (icmp.icmp_state == TS_IDLE) 7519089SVasumathi.Sundaram@Sun.COM state = "IDLE"; 7529089SVasumathi.Sundaram@Sun.COM else if (icmp.icmp_state == TS_DATA_XFER) 7539089SVasumathi.Sundaram@Sun.COM state = "CONNECTED"; 7549089SVasumathi.Sundaram@Sun.COM else 7559089SVasumathi.Sundaram@Sun.COM state = "UNKNOWN"; 7569089SVasumathi.Sundaram@Sun.COM 7579089SVasumathi.Sundaram@Sun.COM mdb_printf("%0?p %10s ", (uintptr_t)connp->conn_icmp, state); 7589089SVasumathi.Sundaram@Sun.COM if (af == AF_INET) { 7599089SVasumathi.Sundaram@Sun.COM mdb_printf("%*I ", ADDR_V4_WIDTH, 7609089SVasumathi.Sundaram@Sun.COM V4_PART_OF_V6((icmp.icmp_v6src))); 7619089SVasumathi.Sundaram@Sun.COM mdb_printf("%*I ", ADDR_V4_WIDTH, 7629089SVasumathi.Sundaram@Sun.COM V4_PART_OF_V6((icmp.icmp_v6dst.sin6_addr))); 7639089SVasumathi.Sundaram@Sun.COM } else if (af == AF_INET6) { 7649089SVasumathi.Sundaram@Sun.COM mdb_printf("%*N ", ADDR_V6_WIDTH, &icmp.icmp_v6src); 7659089SVasumathi.Sundaram@Sun.COM mdb_printf("%*N ", ADDR_V6_WIDTH, &icmp.icmp_v6dst); 7669089SVasumathi.Sundaram@Sun.COM } 7679089SVasumathi.Sundaram@Sun.COM mdb_printf(" %5i", ns_to_stackid((uintptr_t)connp->conn_netstack)); 7689089SVasumathi.Sundaram@Sun.COM mdb_printf(" %4i\n", icmp.icmp_zoneid); 7699089SVasumathi.Sundaram@Sun.COM 7709089SVasumathi.Sundaram@Sun.COM return (WALK_NEXT); 7710Sstevel@tonic-gate } 7720Sstevel@tonic-gate 7730Sstevel@tonic-gate /* 7740Sstevel@tonic-gate * print the address of a unix domain socket 7750Sstevel@tonic-gate * 7760Sstevel@tonic-gate * so is the address of a AF_UNIX struct sonode in mdb's address space 7770Sstevel@tonic-gate * soa is the address of the struct soaddr to print 7780Sstevel@tonic-gate * 7790Sstevel@tonic-gate * returns 0 on success, -1 otherwise 7800Sstevel@tonic-gate */ 7810Sstevel@tonic-gate static int 7828348SEric.Yu@Sun.COM netstat_unix_name_pr(const struct sotpi_sonode *st, const struct soaddr *soa) 7830Sstevel@tonic-gate { 7848348SEric.Yu@Sun.COM const struct sonode *so = &st->st_sonode; 7850Sstevel@tonic-gate const char none[] = " (none)"; 7860Sstevel@tonic-gate 7870Sstevel@tonic-gate if ((so->so_state & SS_ISBOUND) && (soa->soa_len != 0)) { 7888348SEric.Yu@Sun.COM if (st->st_info.sti_faddr_noxlate) { 7890Sstevel@tonic-gate mdb_printf("%-14s ", " (socketpair)"); 7900Sstevel@tonic-gate } else { 7910Sstevel@tonic-gate if (soa->soa_len > sizeof (sa_family_t)) { 7920Sstevel@tonic-gate char addr[MAXPATHLEN + 1]; 7930Sstevel@tonic-gate 7940Sstevel@tonic-gate if (mdb_readstr(addr, sizeof (addr), 7950Sstevel@tonic-gate (uintptr_t)&soa->soa_sa->sa_data) == -1) { 7960Sstevel@tonic-gate mdb_warn("failed to read unix address " 7970Sstevel@tonic-gate "at %p", &soa->soa_sa->sa_data); 7980Sstevel@tonic-gate return (-1); 7990Sstevel@tonic-gate } 8000Sstevel@tonic-gate 8010Sstevel@tonic-gate mdb_printf("%-14s ", addr); 8020Sstevel@tonic-gate } else { 8030Sstevel@tonic-gate mdb_printf("%-14s ", none); 8040Sstevel@tonic-gate } 8050Sstevel@tonic-gate } 8060Sstevel@tonic-gate } else { 8070Sstevel@tonic-gate mdb_printf("%-14s ", none); 8080Sstevel@tonic-gate } 8090Sstevel@tonic-gate 8100Sstevel@tonic-gate return (0); 8110Sstevel@tonic-gate } 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate /* based on sockfs_snapshot */ 8140Sstevel@tonic-gate /*ARGSUSED*/ 8150Sstevel@tonic-gate static int 8160Sstevel@tonic-gate netstat_unix_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 8170Sstevel@tonic-gate { 8188348SEric.Yu@Sun.COM const struct sotpi_sonode *st = walk_data; 8198348SEric.Yu@Sun.COM const struct sonode *so = &st->st_sonode; 8208348SEric.Yu@Sun.COM const struct sotpi_info *sti = &st->st_info; 8210Sstevel@tonic-gate 8228348SEric.Yu@Sun.COM if (so->so_count == 0) 8230Sstevel@tonic-gate return (WALK_NEXT); 8240Sstevel@tonic-gate 8250Sstevel@tonic-gate if (so->so_family != AF_UNIX) { 8260Sstevel@tonic-gate mdb_warn("sonode of family %hi at %p\n", so->so_family, kaddr); 8270Sstevel@tonic-gate return (WALK_ERR); 8280Sstevel@tonic-gate } 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate mdb_printf("%-?p ", kaddr); 8310Sstevel@tonic-gate 8328348SEric.Yu@Sun.COM switch (sti->sti_serv_type) { 8335563Snordmark case T_CLTS: 8340Sstevel@tonic-gate mdb_printf("%-10s ", "dgram"); 8350Sstevel@tonic-gate break; 8365563Snordmark case T_COTS: 8370Sstevel@tonic-gate mdb_printf("%-10s ", "stream"); 8380Sstevel@tonic-gate break; 8395563Snordmark case T_COTS_ORD: 8400Sstevel@tonic-gate mdb_printf("%-10s ", "stream-ord"); 8410Sstevel@tonic-gate break; 8425563Snordmark default: 8438348SEric.Yu@Sun.COM mdb_printf("%-10i ", sti->sti_serv_type); 8440Sstevel@tonic-gate } 8450Sstevel@tonic-gate 8460Sstevel@tonic-gate if ((so->so_state & SS_ISBOUND) && 8478348SEric.Yu@Sun.COM (sti->sti_ux_laddr.soua_magic == SOU_MAGIC_EXPLICIT)) { 8488348SEric.Yu@Sun.COM mdb_printf("%0?p ", sti->sti_ux_laddr.soua_vp); 8490Sstevel@tonic-gate } else { 8500Sstevel@tonic-gate mdb_printf("%0?p ", NULL); 8510Sstevel@tonic-gate } 8520Sstevel@tonic-gate 8530Sstevel@tonic-gate if ((so->so_state & SS_ISCONNECTED) && 8548348SEric.Yu@Sun.COM (sti->sti_ux_faddr.soua_magic == SOU_MAGIC_EXPLICIT)) { 8558348SEric.Yu@Sun.COM mdb_printf("%0?p ", sti->sti_ux_faddr.soua_vp); 8560Sstevel@tonic-gate } else { 8570Sstevel@tonic-gate mdb_printf("%0?p ", NULL); 8580Sstevel@tonic-gate } 8590Sstevel@tonic-gate 8608348SEric.Yu@Sun.COM if (netstat_unix_name_pr(st, &sti->sti_laddr) == -1) 8610Sstevel@tonic-gate return (WALK_ERR); 8620Sstevel@tonic-gate 8638348SEric.Yu@Sun.COM if (netstat_unix_name_pr(st, &sti->sti_faddr) == -1) 8640Sstevel@tonic-gate return (WALK_ERR); 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate mdb_printf("%4i\n", so->so_zoneid); 8670Sstevel@tonic-gate 8680Sstevel@tonic-gate return (WALK_NEXT); 8690Sstevel@tonic-gate } 8700Sstevel@tonic-gate 8710Sstevel@tonic-gate static void 8720Sstevel@tonic-gate netstat_tcp_verbose_header_pr(void) 8730Sstevel@tonic-gate { 8740Sstevel@tonic-gate mdb_printf(" %<u>%-5s %-8s %-8s %-5s %-8s %-8s %5s %5s%</u>\n", 8750Sstevel@tonic-gate "Swind", "Snext", "Suna", "Rwind", "Rack", "Rnext", "Rto", "Mss"); 8760Sstevel@tonic-gate } 8770Sstevel@tonic-gate 8781676Sjpk static void 8791676Sjpk get_ifname(const ire_t *ire, char *intf) 8801676Sjpk { 8811676Sjpk ill_t ill; 8821676Sjpk 8831676Sjpk *intf = '\0'; 8841676Sjpk if (ire->ire_type == IRE_CACHE) { 8851676Sjpk queue_t stq; 8861676Sjpk 8871676Sjpk if (mdb_vread(&stq, sizeof (stq), (uintptr_t)ire->ire_stq) == 8881676Sjpk -1) 8891676Sjpk return; 8901676Sjpk if (mdb_vread(&ill, sizeof (ill), (uintptr_t)stq.q_ptr) == -1) 8911676Sjpk return; 8921676Sjpk (void) mdb_readstr(intf, MIN(LIFNAMSIZ, ill.ill_name_length), 8931676Sjpk (uintptr_t)ill.ill_name); 8941676Sjpk } else if (ire->ire_ipif != NULL) { 8951676Sjpk ipif_t ipif; 8961676Sjpk char *cp; 8971676Sjpk 8981676Sjpk if (mdb_vread(&ipif, sizeof (ipif), 8991676Sjpk (uintptr_t)ire->ire_ipif) == -1) 9001676Sjpk return; 9011676Sjpk if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ipif.ipif_ill) == 9021676Sjpk -1) 9031676Sjpk return; 9041676Sjpk (void) mdb_readstr(intf, MIN(LIFNAMSIZ, ill.ill_name_length), 9051676Sjpk (uintptr_t)ill.ill_name); 9061676Sjpk if (ipif.ipif_id != 0) { 9071676Sjpk cp = intf + strlen(intf); 9081676Sjpk (void) mdb_snprintf(cp, LIFNAMSIZ + 1 - (cp - intf), 9091676Sjpk ":%u", ipif.ipif_id); 9101676Sjpk } 9111676Sjpk } 9121676Sjpk } 9131676Sjpk 9141676Sjpk static void 9151676Sjpk get_v4flags(const ire_t *ire, char *flags) 9161676Sjpk { 9171676Sjpk (void) strcpy(flags, "U"); 9181676Sjpk if (ire->ire_type == IRE_DEFAULT || ire->ire_type == IRE_PREFIX || 9191676Sjpk ire->ire_type == IRE_HOST || ire->ire_type == IRE_HOST_REDIRECT) 9201676Sjpk (void) strcat(flags, "G"); 9211676Sjpk if (ire->ire_mask == IP_HOST_MASK) 9221676Sjpk (void) strcat(flags, "H"); 9231676Sjpk if (ire->ire_type == IRE_HOST_REDIRECT) 9241676Sjpk (void) strcat(flags, "D"); 9251676Sjpk if (ire->ire_type == IRE_CACHE) 9261676Sjpk (void) strcat(flags, "A"); 9271676Sjpk if (ire->ire_type == IRE_BROADCAST) 9281676Sjpk (void) strcat(flags, "B"); 9291676Sjpk if (ire->ire_type == IRE_LOCAL) 9301676Sjpk (void) strcat(flags, "L"); 9311676Sjpk if (ire->ire_flags & RTF_MULTIRT) 9321676Sjpk (void) strcat(flags, "M"); 9331676Sjpk if (ire->ire_flags & RTF_SETSRC) 9341676Sjpk (void) strcat(flags, "S"); 9351676Sjpk } 9361676Sjpk 9371676Sjpk static int 9381676Sjpk netstat_irev4_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 9391676Sjpk { 9401676Sjpk const ire_t *ire = walk_data; 9411676Sjpk uint_t *opts = cb_data; 9421676Sjpk ipaddr_t gate; 9431676Sjpk char flags[10], intf[LIFNAMSIZ + 1]; 9441676Sjpk 9454823Sseb if (ire->ire_ipversion != IPV4_VERSION) 9461676Sjpk return (WALK_NEXT); 9471676Sjpk 9481676Sjpk if (!(*opts & NETSTAT_ALL) && (ire->ire_type == IRE_CACHE || 9491676Sjpk ire->ire_type == IRE_BROADCAST || ire->ire_type == IRE_LOCAL)) 9501676Sjpk return (WALK_NEXT); 9511676Sjpk 9521676Sjpk if (*opts & NETSTAT_FIRST) { 9531676Sjpk *opts &= ~NETSTAT_FIRST; 9541676Sjpk mdb_printf("%<u>%s Table: IPv4%</u>\n", 9551676Sjpk (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing"); 9561676Sjpk if (*opts & NETSTAT_VERBOSE) { 9571676Sjpk mdb_printf("%<u>%-?s %-*s %-*s %-*s Device Mxfrg Rtt " 9581676Sjpk " Ref Flg Out In/Fwd%</u>\n", 9591676Sjpk "Address", ADDR_V4_WIDTH, "Destination", 9601676Sjpk ADDR_V4_WIDTH, "Mask", ADDR_V4_WIDTH, "Gateway"); 9611676Sjpk } else { 9621676Sjpk mdb_printf("%<u>%-?s %-*s %-*s Flags Ref Use " 9631676Sjpk "Interface%</u>\n", 9641676Sjpk "Address", ADDR_V4_WIDTH, "Destination", 9651676Sjpk ADDR_V4_WIDTH, "Gateway"); 9661676Sjpk } 9671676Sjpk } 9681676Sjpk 9691676Sjpk gate = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK|IRE_BROADCAST)) ? 9701676Sjpk ire->ire_src_addr : ire->ire_gateway_addr; 9711676Sjpk 9721676Sjpk get_v4flags(ire, flags); 9731676Sjpk 9741676Sjpk get_ifname(ire, intf); 9751676Sjpk 9761676Sjpk if (*opts & NETSTAT_VERBOSE) { 9771676Sjpk mdb_printf("%?p %-*I %-*I %-*I %-6s %5u%c %4u %3u %-3s %5u " 9781676Sjpk "%u\n", kaddr, ADDR_V4_WIDTH, ire->ire_addr, ADDR_V4_WIDTH, 9791676Sjpk ire->ire_mask, ADDR_V4_WIDTH, gate, intf, 9801676Sjpk ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ', 9811676Sjpk ire->ire_uinfo.iulp_rtt, ire->ire_refcnt, flags, 9821676Sjpk ire->ire_ob_pkt_count, ire->ire_ib_pkt_count); 9831676Sjpk } else { 9841676Sjpk mdb_printf("%?p %-*I %-*I %-5s %4u %5u %s\n", kaddr, 9851676Sjpk ADDR_V4_WIDTH, ire->ire_addr, ADDR_V4_WIDTH, gate, flags, 9861676Sjpk ire->ire_refcnt, 9871676Sjpk ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf); 9881676Sjpk } 9891676Sjpk 9901676Sjpk return (WALK_NEXT); 9911676Sjpk } 9921676Sjpk 9931676Sjpk int 9941676Sjpk ip_mask_to_plen_v6(const in6_addr_t *v6mask) 9951676Sjpk { 9961676Sjpk int plen; 9971676Sjpk int i; 9981676Sjpk uint32_t val; 9991676Sjpk 10001676Sjpk for (i = 3; i >= 0; i--) 10011676Sjpk if (v6mask->s6_addr32[i] != 0) 10021676Sjpk break; 10031676Sjpk if (i < 0) 10041676Sjpk return (0); 10051676Sjpk plen = 32 + 32 * i; 10061676Sjpk val = v6mask->s6_addr32[i]; 10071676Sjpk while (!(val & 1)) { 10081676Sjpk val >>= 1; 10091676Sjpk plen--; 10101676Sjpk } 10111676Sjpk 10121676Sjpk return (plen); 10131676Sjpk } 10141676Sjpk 10151676Sjpk static int 10161676Sjpk netstat_irev6_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 10171676Sjpk { 10181676Sjpk const ire_t *ire = walk_data; 10191676Sjpk uint_t *opts = cb_data; 10201676Sjpk const in6_addr_t *gatep; 10211676Sjpk char deststr[ADDR_V6_WIDTH + 5]; 10221676Sjpk char flags[10], intf[LIFNAMSIZ + 1]; 10231676Sjpk int masklen; 10241676Sjpk 10251676Sjpk if (ire->ire_ipversion != IPV6_VERSION) 10261676Sjpk return (WALK_NEXT); 10271676Sjpk 10281676Sjpk if (!(*opts & NETSTAT_ALL) && ire->ire_type == IRE_CACHE) 10291676Sjpk return (WALK_NEXT); 10301676Sjpk 10311676Sjpk if (*opts & NETSTAT_FIRST) { 10321676Sjpk *opts &= ~NETSTAT_FIRST; 10331676Sjpk mdb_printf("\n%<u>%s Table: IPv6%</u>\n", 10341676Sjpk (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing"); 10351676Sjpk if (*opts & NETSTAT_VERBOSE) { 10361676Sjpk mdb_printf("%<u>%-?s %-*s %-*s If PMTU Rtt Ref " 10371676Sjpk "Flags Out In/Fwd%</u>\n", 10381676Sjpk "Address", ADDR_V6_WIDTH+4, "Destination/Mask", 10391676Sjpk ADDR_V6_WIDTH, "Gateway"); 10401676Sjpk } else { 10411676Sjpk mdb_printf("%<u>%-?s %-*s %-*s Flags Ref Use If" 10421676Sjpk "%</u>\n", 10431676Sjpk "Address", ADDR_V6_WIDTH+4, "Destination/Mask", 10441676Sjpk ADDR_V6_WIDTH, "Gateway"); 10451676Sjpk } 10461676Sjpk } 10471676Sjpk 10481676Sjpk gatep = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK)) ? 10491676Sjpk &ire->ire_src_addr_v6 : &ire->ire_gateway_addr_v6; 10501676Sjpk 10511676Sjpk masklen = ip_mask_to_plen_v6(&ire->ire_mask_v6); 10521676Sjpk (void) mdb_snprintf(deststr, sizeof (deststr), "%N/%d", 10531676Sjpk &ire->ire_addr_v6, masklen); 10541676Sjpk 10551676Sjpk (void) strcpy(flags, "U"); 10561676Sjpk if (ire->ire_type == IRE_DEFAULT || ire->ire_type == IRE_PREFIX || 10571676Sjpk ire->ire_type == IRE_HOST || ire->ire_type == IRE_HOST_REDIRECT) 10581676Sjpk (void) strcat(flags, "G"); 10591676Sjpk if (masklen == IPV6_ABITS) 10601676Sjpk (void) strcat(flags, "H"); 10611676Sjpk if (ire->ire_type == IRE_HOST_REDIRECT) 10621676Sjpk (void) strcat(flags, "D"); 10631676Sjpk if (ire->ire_type == IRE_CACHE) 10641676Sjpk (void) strcat(flags, "A"); 10651676Sjpk if (ire->ire_type == IRE_LOCAL) 10661676Sjpk (void) strcat(flags, "L"); 10671676Sjpk if (ire->ire_flags & RTF_MULTIRT) 10681676Sjpk (void) strcat(flags, "M"); 10691676Sjpk if (ire->ire_flags & RTF_SETSRC) 10701676Sjpk (void) strcat(flags, "S"); 10711676Sjpk 10721676Sjpk get_ifname(ire, intf); 10731676Sjpk 10741676Sjpk if (*opts & NETSTAT_VERBOSE) { 10751676Sjpk mdb_printf("%?p %-*s %-*N %-5s %5u%c %5u %3u %-5s %6u %u\n", 10761676Sjpk kaddr, ADDR_V6_WIDTH+4, deststr, ADDR_V6_WIDTH, gatep, 10771676Sjpk intf, ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ', 10781676Sjpk ire->ire_uinfo.iulp_rtt, ire->ire_refcnt, 10791676Sjpk flags, ire->ire_ob_pkt_count, ire->ire_ib_pkt_count); 10801676Sjpk } else { 10811676Sjpk mdb_printf("%?p %-*s %-*N %-5s %3u %6u %s\n", kaddr, 10821676Sjpk ADDR_V6_WIDTH+4, deststr, ADDR_V6_WIDTH, gatep, flags, 10831676Sjpk ire->ire_refcnt, 10841676Sjpk ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf); 10851676Sjpk } 10861676Sjpk 10871676Sjpk return (WALK_NEXT); 10881676Sjpk } 10891676Sjpk 10909089SVasumathi.Sundaram@Sun.COM static void 10919089SVasumathi.Sundaram@Sun.COM netstat_header_v4(int proto) 10929089SVasumathi.Sundaram@Sun.COM { 10939089SVasumathi.Sundaram@Sun.COM if (proto == IPPROTO_TCP) 10949089SVasumathi.Sundaram@Sun.COM mdb_printf("%<u>%-?s ", "TCPv4"); 10959089SVasumathi.Sundaram@Sun.COM else if (proto == IPPROTO_UDP) 10969089SVasumathi.Sundaram@Sun.COM mdb_printf("%<u>%-?s ", "UDPv4"); 10979089SVasumathi.Sundaram@Sun.COM else if (proto == IPPROTO_ICMP) 10989089SVasumathi.Sundaram@Sun.COM mdb_printf("%<u>%-?s ", "ICMPv4"); 10999089SVasumathi.Sundaram@Sun.COM mdb_printf("State %6s%*s %6s%*s %-5s %-4s%</u>\n", 11009089SVasumathi.Sundaram@Sun.COM "", ADDR_V4_WIDTH, "Local Address", 11019089SVasumathi.Sundaram@Sun.COM "", ADDR_V4_WIDTH, "Remote Address", "Stack", "Zone"); 11029089SVasumathi.Sundaram@Sun.COM } 11039089SVasumathi.Sundaram@Sun.COM 11049089SVasumathi.Sundaram@Sun.COM static void 11059089SVasumathi.Sundaram@Sun.COM netstat_header_v6(int proto) 11069089SVasumathi.Sundaram@Sun.COM { 11079089SVasumathi.Sundaram@Sun.COM if (proto == IPPROTO_TCP) 11089089SVasumathi.Sundaram@Sun.COM mdb_printf("%<u>%-?s ", "TCPv6"); 11099089SVasumathi.Sundaram@Sun.COM else if (proto == IPPROTO_UDP) 11109089SVasumathi.Sundaram@Sun.COM mdb_printf("%<u>%-?s ", "UDPv6"); 11119089SVasumathi.Sundaram@Sun.COM else if (proto == IPPROTO_ICMP) 11129089SVasumathi.Sundaram@Sun.COM mdb_printf("%<u>%-?s ", "ICMPv6"); 11139089SVasumathi.Sundaram@Sun.COM mdb_printf("State %6s%*s %6s%*s %-5s %-4s%</u>\n", 11149089SVasumathi.Sundaram@Sun.COM "", ADDR_V6_WIDTH, "Local Address", 11159089SVasumathi.Sundaram@Sun.COM "", ADDR_V6_WIDTH, "Remote Address", "Stack", "Zone"); 11169089SVasumathi.Sundaram@Sun.COM } 11179089SVasumathi.Sundaram@Sun.COM 11189089SVasumathi.Sundaram@Sun.COM static int 11199089SVasumathi.Sundaram@Sun.COM netstat_print_conn(const char *cache, int proto, mdb_walk_cb_t cbfunc, 11209089SVasumathi.Sundaram@Sun.COM void *cbdata) 11219089SVasumathi.Sundaram@Sun.COM { 11229089SVasumathi.Sundaram@Sun.COM netstat_cb_data_t *ncb = cbdata; 11239089SVasumathi.Sundaram@Sun.COM 11249089SVasumathi.Sundaram@Sun.COM if ((ncb->opts & NETSTAT_VERBOSE) && proto == IPPROTO_TCP) 11259089SVasumathi.Sundaram@Sun.COM netstat_tcp_verbose_header_pr(); 11269089SVasumathi.Sundaram@Sun.COM if (mdb_walk(cache, cbfunc, cbdata) == -1) { 11279089SVasumathi.Sundaram@Sun.COM mdb_warn("failed to walk %s", cache); 11289089SVasumathi.Sundaram@Sun.COM return (DCMD_ERR); 11299089SVasumathi.Sundaram@Sun.COM } 11309089SVasumathi.Sundaram@Sun.COM return (DCMD_OK); 11319089SVasumathi.Sundaram@Sun.COM } 11329089SVasumathi.Sundaram@Sun.COM 11339089SVasumathi.Sundaram@Sun.COM static int 11349089SVasumathi.Sundaram@Sun.COM netstat_print_common(const char *cache, int proto, mdb_walk_cb_t cbfunc, 11359089SVasumathi.Sundaram@Sun.COM void *cbdata) 11369089SVasumathi.Sundaram@Sun.COM { 11379089SVasumathi.Sundaram@Sun.COM netstat_cb_data_t *ncb = cbdata; 11389089SVasumathi.Sundaram@Sun.COM int af = ncb->af; 11399089SVasumathi.Sundaram@Sun.COM int status = DCMD_OK; 11409089SVasumathi.Sundaram@Sun.COM 11419089SVasumathi.Sundaram@Sun.COM if (af != AF_INET6) { 11429089SVasumathi.Sundaram@Sun.COM ncb->af = AF_INET; 11439089SVasumathi.Sundaram@Sun.COM netstat_header_v4(proto); 11449089SVasumathi.Sundaram@Sun.COM status = netstat_print_conn(cache, proto, cbfunc, cbdata); 11459089SVasumathi.Sundaram@Sun.COM } 11469089SVasumathi.Sundaram@Sun.COM if (status == DCMD_OK && af != AF_INET) { 11479089SVasumathi.Sundaram@Sun.COM ncb->af = AF_INET6; 11489089SVasumathi.Sundaram@Sun.COM netstat_header_v6(proto); 11499089SVasumathi.Sundaram@Sun.COM status = netstat_print_conn(cache, proto, cbfunc, cbdata); 11509089SVasumathi.Sundaram@Sun.COM } 11519089SVasumathi.Sundaram@Sun.COM ncb->af = af; 11529089SVasumathi.Sundaram@Sun.COM return (status); 11539089SVasumathi.Sundaram@Sun.COM } 11549089SVasumathi.Sundaram@Sun.COM 11550Sstevel@tonic-gate /*ARGSUSED*/ 11560Sstevel@tonic-gate int 11570Sstevel@tonic-gate netstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 11580Sstevel@tonic-gate { 11590Sstevel@tonic-gate uint_t opts = 0; 11600Sstevel@tonic-gate const char *optf = NULL; 11610Sstevel@tonic-gate const char *optP = NULL; 11629089SVasumathi.Sundaram@Sun.COM netstat_cb_data_t *cbdata; 11639089SVasumathi.Sundaram@Sun.COM int status; 11649089SVasumathi.Sundaram@Sun.COM int af = 0; 11650Sstevel@tonic-gate 11660Sstevel@tonic-gate if (mdb_getopts(argc, argv, 11670Sstevel@tonic-gate 'a', MDB_OPT_SETBITS, NETSTAT_ALL, &opts, 11680Sstevel@tonic-gate 'f', MDB_OPT_STR, &optf, 11690Sstevel@tonic-gate 'P', MDB_OPT_STR, &optP, 11701676Sjpk 'r', MDB_OPT_SETBITS, NETSTAT_ROUTE, &opts, 11711676Sjpk 'v', MDB_OPT_SETBITS, NETSTAT_VERBOSE, &opts, 11720Sstevel@tonic-gate NULL) != argc) 11730Sstevel@tonic-gate return (DCMD_USAGE); 11740Sstevel@tonic-gate 11750Sstevel@tonic-gate if (optP != NULL) { 11769089SVasumathi.Sundaram@Sun.COM if ((strcmp("tcp", optP) != 0) && (strcmp("udp", optP) != 0) && 11779089SVasumathi.Sundaram@Sun.COM (strcmp("icmp", optP) != 0)) 11780Sstevel@tonic-gate return (DCMD_USAGE); 11791676Sjpk if (opts & NETSTAT_ROUTE) 11801676Sjpk return (DCMD_USAGE); 11810Sstevel@tonic-gate } 11820Sstevel@tonic-gate 11831676Sjpk if (optf == NULL) 11841676Sjpk opts |= NETSTAT_V4 | NETSTAT_V6 | NETSTAT_UNIX; 11851676Sjpk else if (strcmp("inet", optf) == 0) 11861676Sjpk opts |= NETSTAT_V4; 11871676Sjpk else if (strcmp("inet6", optf) == 0) 11881676Sjpk opts |= NETSTAT_V6; 11891676Sjpk else if (strcmp("unix", optf) == 0) 11901676Sjpk opts |= NETSTAT_UNIX; 11911676Sjpk else 11921676Sjpk return (DCMD_USAGE); 11931676Sjpk 11941676Sjpk if (opts & NETSTAT_ROUTE) { 11951676Sjpk if (!(opts & (NETSTAT_V4|NETSTAT_V6))) 11960Sstevel@tonic-gate return (DCMD_USAGE); 11971676Sjpk if (opts & NETSTAT_V4) { 11981676Sjpk opts |= NETSTAT_FIRST; 11991676Sjpk if (mdb_walk("ip`ire", netstat_irev4_cb, &opts) == -1) { 12001676Sjpk mdb_warn("failed to walk ip`ire"); 12011676Sjpk return (DCMD_ERR); 12021676Sjpk } 12031676Sjpk } 12041676Sjpk if (opts & NETSTAT_V6) { 12051676Sjpk opts |= NETSTAT_FIRST; 12061676Sjpk if (mdb_walk("ip`ire", netstat_irev6_cb, &opts) == -1) { 12071676Sjpk mdb_warn("failed to walk ip`ire"); 12081676Sjpk return (DCMD_ERR); 12091676Sjpk } 12101676Sjpk } 12111676Sjpk return (DCMD_OK); 12120Sstevel@tonic-gate } 12130Sstevel@tonic-gate 12149089SVasumathi.Sundaram@Sun.COM if ((opts & NETSTAT_UNIX) && (optP == NULL)) { 12150Sstevel@tonic-gate /* Print Unix Domain Sockets */ 12160Sstevel@tonic-gate mdb_printf("%<u>%-?s %-10s %-?s %-?s %-14s %-14s %s%</u>\n", 12170Sstevel@tonic-gate "AF_UNIX", "Type", "Vnode", "Conn", "Local Addr", 12180Sstevel@tonic-gate "Remote Addr", "Zone"); 12190Sstevel@tonic-gate 12200Sstevel@tonic-gate if (mdb_walk("genunix`sonode", netstat_unix_cb, NULL) == -1) { 12210Sstevel@tonic-gate mdb_warn("failed to walk genunix`sonode"); 12220Sstevel@tonic-gate return (DCMD_ERR); 12230Sstevel@tonic-gate } 12249089SVasumathi.Sundaram@Sun.COM if (!(opts & (NETSTAT_V4 | NETSTAT_V6))) 12259089SVasumathi.Sundaram@Sun.COM return (DCMD_OK); 12260Sstevel@tonic-gate } 12270Sstevel@tonic-gate 12289089SVasumathi.Sundaram@Sun.COM cbdata = mdb_alloc(sizeof (netstat_cb_data_t), UM_SLEEP); 12299089SVasumathi.Sundaram@Sun.COM cbdata->opts = opts; 12309089SVasumathi.Sundaram@Sun.COM if ((optf != NULL) && (opts & NETSTAT_V4)) 12319089SVasumathi.Sundaram@Sun.COM af = AF_INET; 12329089SVasumathi.Sundaram@Sun.COM else if ((optf != NULL) && (opts & NETSTAT_V6)) 12339089SVasumathi.Sundaram@Sun.COM af = AF_INET6; 12349089SVasumathi.Sundaram@Sun.COM 12359089SVasumathi.Sundaram@Sun.COM cbdata->af = af; 12369089SVasumathi.Sundaram@Sun.COM if ((optP == NULL) || (strcmp("tcp", optP) == 0)) { 12379089SVasumathi.Sundaram@Sun.COM status = netstat_print_common("tcp_conn_cache", IPPROTO_TCP, 12389089SVasumathi.Sundaram@Sun.COM netstat_tcp_cb, cbdata); 12399089SVasumathi.Sundaram@Sun.COM if (status != DCMD_OK) 12409089SVasumathi.Sundaram@Sun.COM goto out; 12419089SVasumathi.Sundaram@Sun.COM } 12429089SVasumathi.Sundaram@Sun.COM 12439089SVasumathi.Sundaram@Sun.COM if ((optP == NULL) || (strcmp("udp", optP) == 0)) { 12449089SVasumathi.Sundaram@Sun.COM status = netstat_print_common("udp_conn_cache", IPPROTO_UDP, 12459089SVasumathi.Sundaram@Sun.COM netstat_udp_cb, cbdata); 12469089SVasumathi.Sundaram@Sun.COM if (status != DCMD_OK) 12479089SVasumathi.Sundaram@Sun.COM goto out; 12489089SVasumathi.Sundaram@Sun.COM } 12499089SVasumathi.Sundaram@Sun.COM 12509089SVasumathi.Sundaram@Sun.COM if ((optP == NULL) || (strcmp("icmp", optP) == 0)) { 12519089SVasumathi.Sundaram@Sun.COM status = netstat_print_common("rawip_conn_cache", IPPROTO_ICMP, 12529089SVasumathi.Sundaram@Sun.COM netstat_icmp_cb, cbdata); 12539089SVasumathi.Sundaram@Sun.COM if (status != DCMD_OK) 12549089SVasumathi.Sundaram@Sun.COM goto out; 12559089SVasumathi.Sundaram@Sun.COM } 12569089SVasumathi.Sundaram@Sun.COM out: 12579089SVasumathi.Sundaram@Sun.COM mdb_free(cbdata, sizeof (netstat_cb_data_t)); 12589089SVasumathi.Sundaram@Sun.COM return (status); 12590Sstevel@tonic-gate } 1260*10491SRishi.Srivatsavai@Sun.COM 1261*10491SRishi.Srivatsavai@Sun.COM /* 1262*10491SRishi.Srivatsavai@Sun.COM * "::dladm show-bridge" support 1263*10491SRishi.Srivatsavai@Sun.COM */ 1264*10491SRishi.Srivatsavai@Sun.COM typedef struct { 1265*10491SRishi.Srivatsavai@Sun.COM uint_t opt_l; 1266*10491SRishi.Srivatsavai@Sun.COM uint_t opt_f; 1267*10491SRishi.Srivatsavai@Sun.COM uint_t opt_t; 1268*10491SRishi.Srivatsavai@Sun.COM const char *name; 1269*10491SRishi.Srivatsavai@Sun.COM clock_t lbolt; 1270*10491SRishi.Srivatsavai@Sun.COM boolean_t found; 1271*10491SRishi.Srivatsavai@Sun.COM uint_t nlinks; 1272*10491SRishi.Srivatsavai@Sun.COM uint_t nfwd; 1273*10491SRishi.Srivatsavai@Sun.COM 1274*10491SRishi.Srivatsavai@Sun.COM /* 1275*10491SRishi.Srivatsavai@Sun.COM * These structures are kept inside the 'args' for allocation reasons. 1276*10491SRishi.Srivatsavai@Sun.COM * They're all large data structures (over 1K), and may cause the stack 1277*10491SRishi.Srivatsavai@Sun.COM * to explode. mdb and kmdb will fail in these cases, and thus we 1278*10491SRishi.Srivatsavai@Sun.COM * allocate them from the heap. 1279*10491SRishi.Srivatsavai@Sun.COM */ 1280*10491SRishi.Srivatsavai@Sun.COM trill_inst_t ti; 1281*10491SRishi.Srivatsavai@Sun.COM bridge_link_t bl; 1282*10491SRishi.Srivatsavai@Sun.COM mac_impl_t mi; 1283*10491SRishi.Srivatsavai@Sun.COM } show_bridge_args_t; 1284*10491SRishi.Srivatsavai@Sun.COM 1285*10491SRishi.Srivatsavai@Sun.COM static void 1286*10491SRishi.Srivatsavai@Sun.COM show_vlans(const uint8_t *vlans) 1287*10491SRishi.Srivatsavai@Sun.COM { 1288*10491SRishi.Srivatsavai@Sun.COM int i, bit; 1289*10491SRishi.Srivatsavai@Sun.COM uint8_t val; 1290*10491SRishi.Srivatsavai@Sun.COM int rstart = -1, rnext = -1; 1291*10491SRishi.Srivatsavai@Sun.COM 1292*10491SRishi.Srivatsavai@Sun.COM for (i = 0; i < BRIDGE_VLAN_ARR_SIZE; i++) { 1293*10491SRishi.Srivatsavai@Sun.COM val = vlans[i]; 1294*10491SRishi.Srivatsavai@Sun.COM if (i == 0) 1295*10491SRishi.Srivatsavai@Sun.COM val &= ~1; 1296*10491SRishi.Srivatsavai@Sun.COM while ((bit = mdb_ffs(val)) != 0) { 1297*10491SRishi.Srivatsavai@Sun.COM bit--; 1298*10491SRishi.Srivatsavai@Sun.COM val &= ~(1 << bit); 1299*10491SRishi.Srivatsavai@Sun.COM bit += i * sizeof (*vlans) * NBBY; 1300*10491SRishi.Srivatsavai@Sun.COM if (bit != rnext) { 1301*10491SRishi.Srivatsavai@Sun.COM if (rnext != -1 && rstart + 1 != rnext) 1302*10491SRishi.Srivatsavai@Sun.COM mdb_printf("-%d", rnext - 1); 1303*10491SRishi.Srivatsavai@Sun.COM if (rstart != -1) 1304*10491SRishi.Srivatsavai@Sun.COM mdb_printf(","); 1305*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%d", bit); 1306*10491SRishi.Srivatsavai@Sun.COM rstart = bit; 1307*10491SRishi.Srivatsavai@Sun.COM } 1308*10491SRishi.Srivatsavai@Sun.COM rnext = bit + 1; 1309*10491SRishi.Srivatsavai@Sun.COM } 1310*10491SRishi.Srivatsavai@Sun.COM } 1311*10491SRishi.Srivatsavai@Sun.COM if (rnext != -1 && rstart + 1 != rnext) 1312*10491SRishi.Srivatsavai@Sun.COM mdb_printf("-%d", rnext - 1); 1313*10491SRishi.Srivatsavai@Sun.COM mdb_printf("\n"); 1314*10491SRishi.Srivatsavai@Sun.COM } 1315*10491SRishi.Srivatsavai@Sun.COM 1316*10491SRishi.Srivatsavai@Sun.COM /* 1317*10491SRishi.Srivatsavai@Sun.COM * This callback is invoked by a walk of the links attached to a bridge. If 1318*10491SRishi.Srivatsavai@Sun.COM * we're showing link details, then they're printed here. If not, then we just 1319*10491SRishi.Srivatsavai@Sun.COM * count up the links for the bridge summary. 1320*10491SRishi.Srivatsavai@Sun.COM */ 1321*10491SRishi.Srivatsavai@Sun.COM static int 1322*10491SRishi.Srivatsavai@Sun.COM do_bridge_links(uintptr_t addr, const void *data, void *ptr) 1323*10491SRishi.Srivatsavai@Sun.COM { 1324*10491SRishi.Srivatsavai@Sun.COM show_bridge_args_t *args = ptr; 1325*10491SRishi.Srivatsavai@Sun.COM const bridge_link_t *blp = data; 1326*10491SRishi.Srivatsavai@Sun.COM char macaddr[ETHERADDRL * 3]; 1327*10491SRishi.Srivatsavai@Sun.COM const char *name; 1328*10491SRishi.Srivatsavai@Sun.COM 1329*10491SRishi.Srivatsavai@Sun.COM args->nlinks++; 1330*10491SRishi.Srivatsavai@Sun.COM 1331*10491SRishi.Srivatsavai@Sun.COM if (!args->opt_l) 1332*10491SRishi.Srivatsavai@Sun.COM return (WALK_NEXT); 1333*10491SRishi.Srivatsavai@Sun.COM 1334*10491SRishi.Srivatsavai@Sun.COM if (mdb_vread(&args->mi, sizeof (args->mi), 1335*10491SRishi.Srivatsavai@Sun.COM (uintptr_t)blp->bl_mh) == -1) { 1336*10491SRishi.Srivatsavai@Sun.COM mdb_warn("cannot read mac data at %p", blp->bl_mh); 1337*10491SRishi.Srivatsavai@Sun.COM name = "?"; 1338*10491SRishi.Srivatsavai@Sun.COM } else { 1339*10491SRishi.Srivatsavai@Sun.COM name = args->mi.mi_name; 1340*10491SRishi.Srivatsavai@Sun.COM } 1341*10491SRishi.Srivatsavai@Sun.COM 1342*10491SRishi.Srivatsavai@Sun.COM mdb_mac_addr(blp->bl_local_mac, ETHERADDRL, macaddr, 1343*10491SRishi.Srivatsavai@Sun.COM sizeof (macaddr)); 1344*10491SRishi.Srivatsavai@Sun.COM 1345*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%-?p %-16s %-17s %03X %-4d ", addr, name, macaddr, 1346*10491SRishi.Srivatsavai@Sun.COM blp->bl_flags, blp->bl_pvid); 1347*10491SRishi.Srivatsavai@Sun.COM 1348*10491SRishi.Srivatsavai@Sun.COM if (blp->bl_trilldata == NULL) { 1349*10491SRishi.Srivatsavai@Sun.COM switch (blp->bl_state) { 1350*10491SRishi.Srivatsavai@Sun.COM case BLS_BLOCKLISTEN: 1351*10491SRishi.Srivatsavai@Sun.COM name = "BLOCK"; 1352*10491SRishi.Srivatsavai@Sun.COM break; 1353*10491SRishi.Srivatsavai@Sun.COM case BLS_LEARNING: 1354*10491SRishi.Srivatsavai@Sun.COM name = "LEARN"; 1355*10491SRishi.Srivatsavai@Sun.COM break; 1356*10491SRishi.Srivatsavai@Sun.COM case BLS_FORWARDING: 1357*10491SRishi.Srivatsavai@Sun.COM name = "FWD"; 1358*10491SRishi.Srivatsavai@Sun.COM break; 1359*10491SRishi.Srivatsavai@Sun.COM default: 1360*10491SRishi.Srivatsavai@Sun.COM name = "?"; 1361*10491SRishi.Srivatsavai@Sun.COM } 1362*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%-5s ", name); 1363*10491SRishi.Srivatsavai@Sun.COM show_vlans(blp->bl_vlans); 1364*10491SRishi.Srivatsavai@Sun.COM } else { 1365*10491SRishi.Srivatsavai@Sun.COM show_vlans(blp->bl_afs); 1366*10491SRishi.Srivatsavai@Sun.COM } 1367*10491SRishi.Srivatsavai@Sun.COM 1368*10491SRishi.Srivatsavai@Sun.COM return (WALK_NEXT); 1369*10491SRishi.Srivatsavai@Sun.COM } 1370*10491SRishi.Srivatsavai@Sun.COM 1371*10491SRishi.Srivatsavai@Sun.COM /* 1372*10491SRishi.Srivatsavai@Sun.COM * It seems a shame to duplicate this code, but merging it with the link 1373*10491SRishi.Srivatsavai@Sun.COM * printing code above is more trouble than it would be worth. 1374*10491SRishi.Srivatsavai@Sun.COM */ 1375*10491SRishi.Srivatsavai@Sun.COM static void 1376*10491SRishi.Srivatsavai@Sun.COM print_link_name(show_bridge_args_t *args, uintptr_t addr, char sep) 1377*10491SRishi.Srivatsavai@Sun.COM { 1378*10491SRishi.Srivatsavai@Sun.COM const char *name; 1379*10491SRishi.Srivatsavai@Sun.COM 1380*10491SRishi.Srivatsavai@Sun.COM if (mdb_vread(&args->bl, sizeof (args->bl), addr) == -1) { 1381*10491SRishi.Srivatsavai@Sun.COM mdb_warn("cannot read bridge link at %p", addr); 1382*10491SRishi.Srivatsavai@Sun.COM return; 1383*10491SRishi.Srivatsavai@Sun.COM } 1384*10491SRishi.Srivatsavai@Sun.COM 1385*10491SRishi.Srivatsavai@Sun.COM if (mdb_vread(&args->mi, sizeof (args->mi), 1386*10491SRishi.Srivatsavai@Sun.COM (uintptr_t)args->bl.bl_mh) == -1) { 1387*10491SRishi.Srivatsavai@Sun.COM name = "?"; 1388*10491SRishi.Srivatsavai@Sun.COM } else { 1389*10491SRishi.Srivatsavai@Sun.COM name = args->mi.mi_name; 1390*10491SRishi.Srivatsavai@Sun.COM } 1391*10491SRishi.Srivatsavai@Sun.COM 1392*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%s%c", name, sep); 1393*10491SRishi.Srivatsavai@Sun.COM } 1394*10491SRishi.Srivatsavai@Sun.COM 1395*10491SRishi.Srivatsavai@Sun.COM static int 1396*10491SRishi.Srivatsavai@Sun.COM do_bridge_fwd(uintptr_t addr, const void *data, void *ptr) 1397*10491SRishi.Srivatsavai@Sun.COM { 1398*10491SRishi.Srivatsavai@Sun.COM show_bridge_args_t *args = ptr; 1399*10491SRishi.Srivatsavai@Sun.COM const bridge_fwd_t *bfp = data; 1400*10491SRishi.Srivatsavai@Sun.COM char macaddr[ETHERADDRL * 3]; 1401*10491SRishi.Srivatsavai@Sun.COM int i; 1402*10491SRishi.Srivatsavai@Sun.COM #define MAX_FWD_LINKS 16 1403*10491SRishi.Srivatsavai@Sun.COM bridge_link_t *links[MAX_FWD_LINKS]; 1404*10491SRishi.Srivatsavai@Sun.COM uint_t nlinks; 1405*10491SRishi.Srivatsavai@Sun.COM 1406*10491SRishi.Srivatsavai@Sun.COM args->nfwd++; 1407*10491SRishi.Srivatsavai@Sun.COM 1408*10491SRishi.Srivatsavai@Sun.COM if (!args->opt_f) 1409*10491SRishi.Srivatsavai@Sun.COM return (WALK_NEXT); 1410*10491SRishi.Srivatsavai@Sun.COM 1411*10491SRishi.Srivatsavai@Sun.COM if ((nlinks = bfp->bf_nlinks) > MAX_FWD_LINKS) 1412*10491SRishi.Srivatsavai@Sun.COM nlinks = MAX_FWD_LINKS; 1413*10491SRishi.Srivatsavai@Sun.COM 1414*10491SRishi.Srivatsavai@Sun.COM if (mdb_vread(links, sizeof (links[0]) * nlinks, 1415*10491SRishi.Srivatsavai@Sun.COM (uintptr_t)bfp->bf_links) == -1) { 1416*10491SRishi.Srivatsavai@Sun.COM mdb_warn("cannot read bridge forwarding links at %p", 1417*10491SRishi.Srivatsavai@Sun.COM bfp->bf_links); 1418*10491SRishi.Srivatsavai@Sun.COM return (WALK_ERR); 1419*10491SRishi.Srivatsavai@Sun.COM } 1420*10491SRishi.Srivatsavai@Sun.COM 1421*10491SRishi.Srivatsavai@Sun.COM mdb_mac_addr(bfp->bf_dest, ETHERADDRL, macaddr, sizeof (macaddr)); 1422*10491SRishi.Srivatsavai@Sun.COM 1423*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%-?p %-17s ", addr, macaddr); 1424*10491SRishi.Srivatsavai@Sun.COM if (bfp->bf_flags & BFF_LOCALADDR) 1425*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%-7s", "[self]"); 1426*10491SRishi.Srivatsavai@Sun.COM else 1427*10491SRishi.Srivatsavai@Sun.COM mdb_printf("t-%-5d", args->lbolt - bfp->bf_lastheard); 1428*10491SRishi.Srivatsavai@Sun.COM mdb_printf(" %-7u ", bfp->bf_refs); 1429*10491SRishi.Srivatsavai@Sun.COM 1430*10491SRishi.Srivatsavai@Sun.COM if (bfp->bf_trill_nick != 0) { 1431*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%d\n", bfp->bf_trill_nick); 1432*10491SRishi.Srivatsavai@Sun.COM } else { 1433*10491SRishi.Srivatsavai@Sun.COM for (i = 0; i < bfp->bf_nlinks; i++) { 1434*10491SRishi.Srivatsavai@Sun.COM print_link_name(args, (uintptr_t)links[i], 1435*10491SRishi.Srivatsavai@Sun.COM i == bfp->bf_nlinks - 1 ? '\n' : ' '); 1436*10491SRishi.Srivatsavai@Sun.COM } 1437*10491SRishi.Srivatsavai@Sun.COM } 1438*10491SRishi.Srivatsavai@Sun.COM 1439*10491SRishi.Srivatsavai@Sun.COM return (WALK_NEXT); 1440*10491SRishi.Srivatsavai@Sun.COM } 1441*10491SRishi.Srivatsavai@Sun.COM 1442*10491SRishi.Srivatsavai@Sun.COM static int 1443*10491SRishi.Srivatsavai@Sun.COM do_show_bridge(uintptr_t addr, const void *data, void *ptr) 1444*10491SRishi.Srivatsavai@Sun.COM { 1445*10491SRishi.Srivatsavai@Sun.COM show_bridge_args_t *args = ptr; 1446*10491SRishi.Srivatsavai@Sun.COM bridge_inst_t bi; 1447*10491SRishi.Srivatsavai@Sun.COM const bridge_inst_t *bip; 1448*10491SRishi.Srivatsavai@Sun.COM trill_node_t tn; 1449*10491SRishi.Srivatsavai@Sun.COM trill_sock_t tsp; 1450*10491SRishi.Srivatsavai@Sun.COM trill_nickinfo_t tni; 1451*10491SRishi.Srivatsavai@Sun.COM char bname[MAXLINKNAMELEN]; 1452*10491SRishi.Srivatsavai@Sun.COM char macaddr[ETHERADDRL * 3]; 1453*10491SRishi.Srivatsavai@Sun.COM char *cp; 1454*10491SRishi.Srivatsavai@Sun.COM uint_t nnicks; 1455*10491SRishi.Srivatsavai@Sun.COM int i; 1456*10491SRishi.Srivatsavai@Sun.COM 1457*10491SRishi.Srivatsavai@Sun.COM if (data != NULL) { 1458*10491SRishi.Srivatsavai@Sun.COM bip = data; 1459*10491SRishi.Srivatsavai@Sun.COM } else { 1460*10491SRishi.Srivatsavai@Sun.COM if (mdb_vread(&bi, sizeof (bi), addr) == -1) { 1461*10491SRishi.Srivatsavai@Sun.COM mdb_warn("cannot read bridge instance at %p", addr); 1462*10491SRishi.Srivatsavai@Sun.COM return (WALK_ERR); 1463*10491SRishi.Srivatsavai@Sun.COM } 1464*10491SRishi.Srivatsavai@Sun.COM bip = &bi; 1465*10491SRishi.Srivatsavai@Sun.COM } 1466*10491SRishi.Srivatsavai@Sun.COM 1467*10491SRishi.Srivatsavai@Sun.COM (void) strncpy(bname, bip->bi_name, sizeof (bname) - 1); 1468*10491SRishi.Srivatsavai@Sun.COM bname[MAXLINKNAMELEN - 1] = '\0'; 1469*10491SRishi.Srivatsavai@Sun.COM cp = bname + strlen(bname); 1470*10491SRishi.Srivatsavai@Sun.COM if (cp > bname && cp[-1] == '0') 1471*10491SRishi.Srivatsavai@Sun.COM cp[-1] = '\0'; 1472*10491SRishi.Srivatsavai@Sun.COM 1473*10491SRishi.Srivatsavai@Sun.COM if (args->name != NULL && strcmp(args->name, bname) != 0) 1474*10491SRishi.Srivatsavai@Sun.COM return (WALK_NEXT); 1475*10491SRishi.Srivatsavai@Sun.COM 1476*10491SRishi.Srivatsavai@Sun.COM args->found = B_TRUE; 1477*10491SRishi.Srivatsavai@Sun.COM args->nlinks = args->nfwd = 0; 1478*10491SRishi.Srivatsavai@Sun.COM 1479*10491SRishi.Srivatsavai@Sun.COM if (args->opt_l) { 1480*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%-?s %-16s %-17s %3s %-4s ", "ADDR", "LINK", 1481*10491SRishi.Srivatsavai@Sun.COM "MAC-ADDR", "FLG", "PVID"); 1482*10491SRishi.Srivatsavai@Sun.COM if (bip->bi_trilldata == NULL) 1483*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%-5s %s\n", "STATE", "VLANS"); 1484*10491SRishi.Srivatsavai@Sun.COM else 1485*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%s\n", "FWD-VLANS"); 1486*10491SRishi.Srivatsavai@Sun.COM } 1487*10491SRishi.Srivatsavai@Sun.COM 1488*10491SRishi.Srivatsavai@Sun.COM if (!args->opt_f && !args->opt_t && 1489*10491SRishi.Srivatsavai@Sun.COM mdb_pwalk("list", do_bridge_links, args, 1490*10491SRishi.Srivatsavai@Sun.COM addr + offsetof(bridge_inst_t, bi_links)) != DCMD_OK) 1491*10491SRishi.Srivatsavai@Sun.COM return (WALK_ERR); 1492*10491SRishi.Srivatsavai@Sun.COM 1493*10491SRishi.Srivatsavai@Sun.COM if (args->opt_f) 1494*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%-?s %-17s %-7s %-7s %s\n", "ADDR", "DEST", "TIME", 1495*10491SRishi.Srivatsavai@Sun.COM "REFS", "OUTPUT"); 1496*10491SRishi.Srivatsavai@Sun.COM 1497*10491SRishi.Srivatsavai@Sun.COM if (!args->opt_l && !args->opt_t && 1498*10491SRishi.Srivatsavai@Sun.COM mdb_pwalk("avl", do_bridge_fwd, args, 1499*10491SRishi.Srivatsavai@Sun.COM addr + offsetof(bridge_inst_t, bi_fwd)) != DCMD_OK) 1500*10491SRishi.Srivatsavai@Sun.COM return (WALK_ERR); 1501*10491SRishi.Srivatsavai@Sun.COM 1502*10491SRishi.Srivatsavai@Sun.COM nnicks = 0; 1503*10491SRishi.Srivatsavai@Sun.COM if (bip->bi_trilldata != NULL && !args->opt_l && !args->opt_f) { 1504*10491SRishi.Srivatsavai@Sun.COM if (mdb_vread(&args->ti, sizeof (args->ti), 1505*10491SRishi.Srivatsavai@Sun.COM (uintptr_t)bip->bi_trilldata) == -1) { 1506*10491SRishi.Srivatsavai@Sun.COM mdb_warn("cannot read trill instance at %p", 1507*10491SRishi.Srivatsavai@Sun.COM bip->bi_trilldata); 1508*10491SRishi.Srivatsavai@Sun.COM return (WALK_ERR); 1509*10491SRishi.Srivatsavai@Sun.COM } 1510*10491SRishi.Srivatsavai@Sun.COM if (args->opt_t) 1511*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%-?s %-5s %-17s %s\n", "ADDR", 1512*10491SRishi.Srivatsavai@Sun.COM "NICK", "NEXT-HOP", "LINK"); 1513*10491SRishi.Srivatsavai@Sun.COM for (i = 0; i < RBRIDGE_NICKNAME_MAX; i++) { 1514*10491SRishi.Srivatsavai@Sun.COM if (args->ti.ti_nodes[i] == NULL) 1515*10491SRishi.Srivatsavai@Sun.COM continue; 1516*10491SRishi.Srivatsavai@Sun.COM if (args->opt_t) { 1517*10491SRishi.Srivatsavai@Sun.COM if (mdb_vread(&tn, sizeof (tn), 1518*10491SRishi.Srivatsavai@Sun.COM (uintptr_t)args->ti.ti_nodes[i]) == -1) { 1519*10491SRishi.Srivatsavai@Sun.COM mdb_warn("cannot read trill node %d at " 1520*10491SRishi.Srivatsavai@Sun.COM "%p", i, args->ti.ti_nodes[i]); 1521*10491SRishi.Srivatsavai@Sun.COM return (WALK_ERR); 1522*10491SRishi.Srivatsavai@Sun.COM } 1523*10491SRishi.Srivatsavai@Sun.COM if (mdb_vread(&tni, sizeof (tni), 1524*10491SRishi.Srivatsavai@Sun.COM (uintptr_t)tn.tn_ni) == -1) { 1525*10491SRishi.Srivatsavai@Sun.COM mdb_warn("cannot read trill node info " 1526*10491SRishi.Srivatsavai@Sun.COM "%d at %p", i, tn.tn_ni); 1527*10491SRishi.Srivatsavai@Sun.COM return (WALK_ERR); 1528*10491SRishi.Srivatsavai@Sun.COM } 1529*10491SRishi.Srivatsavai@Sun.COM mdb_mac_addr(tni.tni_adjsnpa, ETHERADDRL, 1530*10491SRishi.Srivatsavai@Sun.COM macaddr, sizeof (macaddr)); 1531*10491SRishi.Srivatsavai@Sun.COM if (tni.tni_nick == args->ti.ti_nick) { 1532*10491SRishi.Srivatsavai@Sun.COM (void) strcpy(macaddr, "[self]"); 1533*10491SRishi.Srivatsavai@Sun.COM } 1534*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%-?p %-5u %-17s ", 1535*10491SRishi.Srivatsavai@Sun.COM args->ti.ti_nodes[i], tni.tni_nick, 1536*10491SRishi.Srivatsavai@Sun.COM macaddr); 1537*10491SRishi.Srivatsavai@Sun.COM if (tn.tn_tsp != NULL) { 1538*10491SRishi.Srivatsavai@Sun.COM if (mdb_vread(&tsp, sizeof (tsp), 1539*10491SRishi.Srivatsavai@Sun.COM (uintptr_t)tn.tn_tsp) == -1) { 1540*10491SRishi.Srivatsavai@Sun.COM mdb_warn("cannot read trill " 1541*10491SRishi.Srivatsavai@Sun.COM "socket info at %p", 1542*10491SRishi.Srivatsavai@Sun.COM tn.tn_tsp); 1543*10491SRishi.Srivatsavai@Sun.COM return (WALK_ERR); 1544*10491SRishi.Srivatsavai@Sun.COM } 1545*10491SRishi.Srivatsavai@Sun.COM if (tsp.ts_link != NULL) { 1546*10491SRishi.Srivatsavai@Sun.COM print_link_name(args, 1547*10491SRishi.Srivatsavai@Sun.COM (uintptr_t)tsp.ts_link, 1548*10491SRishi.Srivatsavai@Sun.COM '\n'); 1549*10491SRishi.Srivatsavai@Sun.COM continue; 1550*10491SRishi.Srivatsavai@Sun.COM } 1551*10491SRishi.Srivatsavai@Sun.COM } 1552*10491SRishi.Srivatsavai@Sun.COM mdb_printf("--\n"); 1553*10491SRishi.Srivatsavai@Sun.COM } else { 1554*10491SRishi.Srivatsavai@Sun.COM nnicks++; 1555*10491SRishi.Srivatsavai@Sun.COM } 1556*10491SRishi.Srivatsavai@Sun.COM } 1557*10491SRishi.Srivatsavai@Sun.COM } else { 1558*10491SRishi.Srivatsavai@Sun.COM if (args->opt_t) 1559*10491SRishi.Srivatsavai@Sun.COM mdb_printf("bridge is not running TRILL\n"); 1560*10491SRishi.Srivatsavai@Sun.COM } 1561*10491SRishi.Srivatsavai@Sun.COM 1562*10491SRishi.Srivatsavai@Sun.COM if (!args->opt_l && !args->opt_f && !args->opt_t) { 1563*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%-?p %-7s %-16s %-7u %-7u", addr, 1564*10491SRishi.Srivatsavai@Sun.COM bip->bi_trilldata == NULL ? "stp" : "trill", bname, 1565*10491SRishi.Srivatsavai@Sun.COM args->nlinks, args->nfwd); 1566*10491SRishi.Srivatsavai@Sun.COM if (bip->bi_trilldata != NULL) 1567*10491SRishi.Srivatsavai@Sun.COM mdb_printf(" %-7u %u\n", nnicks, args->ti.ti_nick); 1568*10491SRishi.Srivatsavai@Sun.COM else 1569*10491SRishi.Srivatsavai@Sun.COM mdb_printf(" %-7s %s\n", "--", "--"); 1570*10491SRishi.Srivatsavai@Sun.COM } 1571*10491SRishi.Srivatsavai@Sun.COM return (WALK_NEXT); 1572*10491SRishi.Srivatsavai@Sun.COM } 1573*10491SRishi.Srivatsavai@Sun.COM 1574*10491SRishi.Srivatsavai@Sun.COM static int 1575*10491SRishi.Srivatsavai@Sun.COM dladm_show_bridge(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1576*10491SRishi.Srivatsavai@Sun.COM { 1577*10491SRishi.Srivatsavai@Sun.COM show_bridge_args_t *args; 1578*10491SRishi.Srivatsavai@Sun.COM GElf_Sym sym; 1579*10491SRishi.Srivatsavai@Sun.COM int i; 1580*10491SRishi.Srivatsavai@Sun.COM 1581*10491SRishi.Srivatsavai@Sun.COM args = mdb_zalloc(sizeof (*args), UM_SLEEP); 1582*10491SRishi.Srivatsavai@Sun.COM 1583*10491SRishi.Srivatsavai@Sun.COM i = mdb_getopts(argc, argv, 1584*10491SRishi.Srivatsavai@Sun.COM 'l', MDB_OPT_SETBITS, 1, &args->opt_l, 1585*10491SRishi.Srivatsavai@Sun.COM 'f', MDB_OPT_SETBITS, 1, &args->opt_f, 1586*10491SRishi.Srivatsavai@Sun.COM 't', MDB_OPT_SETBITS, 1, &args->opt_t, 1587*10491SRishi.Srivatsavai@Sun.COM NULL); 1588*10491SRishi.Srivatsavai@Sun.COM 1589*10491SRishi.Srivatsavai@Sun.COM argc -= i; 1590*10491SRishi.Srivatsavai@Sun.COM argv += i; 1591*10491SRishi.Srivatsavai@Sun.COM 1592*10491SRishi.Srivatsavai@Sun.COM if (argc > 1 || (argc == 1 && argv[0].a_type != MDB_TYPE_STRING)) { 1593*10491SRishi.Srivatsavai@Sun.COM mdb_free(args, sizeof (*args)); 1594*10491SRishi.Srivatsavai@Sun.COM return (DCMD_USAGE); 1595*10491SRishi.Srivatsavai@Sun.COM } 1596*10491SRishi.Srivatsavai@Sun.COM if (argc == 1) 1597*10491SRishi.Srivatsavai@Sun.COM args->name = argv[0].a_un.a_str; 1598*10491SRishi.Srivatsavai@Sun.COM 1599*10491SRishi.Srivatsavai@Sun.COM if (mdb_readvar(&args->lbolt, 1600*10491SRishi.Srivatsavai@Sun.COM mdb_prop_postmortem ? "panic_lbolt" : "lbolt") == -1) { 1601*10491SRishi.Srivatsavai@Sun.COM mdb_warn("failed to read lbolt"); 1602*10491SRishi.Srivatsavai@Sun.COM goto err; 1603*10491SRishi.Srivatsavai@Sun.COM } 1604*10491SRishi.Srivatsavai@Sun.COM 1605*10491SRishi.Srivatsavai@Sun.COM if (flags & DCMD_ADDRSPEC) { 1606*10491SRishi.Srivatsavai@Sun.COM if (args->name != NULL) { 1607*10491SRishi.Srivatsavai@Sun.COM mdb_printf("bridge name and address are mutually " 1608*10491SRishi.Srivatsavai@Sun.COM "exclusive\n"); 1609*10491SRishi.Srivatsavai@Sun.COM goto err; 1610*10491SRishi.Srivatsavai@Sun.COM } 1611*10491SRishi.Srivatsavai@Sun.COM if (!args->opt_l && !args->opt_f && !args->opt_t) 1612*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%-?s %-7s %-16s %-7s %-7s\n", "ADDR", 1613*10491SRishi.Srivatsavai@Sun.COM "PROTECT", "NAME", "NLINKS", "NFWD"); 1614*10491SRishi.Srivatsavai@Sun.COM if (do_show_bridge(addr, NULL, args) != WALK_NEXT) 1615*10491SRishi.Srivatsavai@Sun.COM goto err; 1616*10491SRishi.Srivatsavai@Sun.COM mdb_free(args, sizeof (*args)); 1617*10491SRishi.Srivatsavai@Sun.COM return (DCMD_OK); 1618*10491SRishi.Srivatsavai@Sun.COM } else { 1619*10491SRishi.Srivatsavai@Sun.COM if ((args->opt_l || args->opt_f || args->opt_t) && 1620*10491SRishi.Srivatsavai@Sun.COM args->name == NULL) { 1621*10491SRishi.Srivatsavai@Sun.COM mdb_printf("need bridge name or address with -[lft]\n"); 1622*10491SRishi.Srivatsavai@Sun.COM goto err; 1623*10491SRishi.Srivatsavai@Sun.COM } 1624*10491SRishi.Srivatsavai@Sun.COM if (mdb_lookup_by_obj("bridge", "inst_list", &sym) == -1) { 1625*10491SRishi.Srivatsavai@Sun.COM mdb_warn("failed to find 'bridge`inst_list'"); 1626*10491SRishi.Srivatsavai@Sun.COM goto err; 1627*10491SRishi.Srivatsavai@Sun.COM } 1628*10491SRishi.Srivatsavai@Sun.COM if (!args->opt_l && !args->opt_f && !args->opt_t) 1629*10491SRishi.Srivatsavai@Sun.COM mdb_printf("%-?s %-7s %-16s %-7s %-7s %-7s %s\n", 1630*10491SRishi.Srivatsavai@Sun.COM "ADDR", "PROTECT", "NAME", "NLINKS", "NFWD", 1631*10491SRishi.Srivatsavai@Sun.COM "NNICKS", "NICK"); 1632*10491SRishi.Srivatsavai@Sun.COM if (mdb_pwalk("list", do_show_bridge, args, 1633*10491SRishi.Srivatsavai@Sun.COM (uintptr_t)sym.st_value) != DCMD_OK) 1634*10491SRishi.Srivatsavai@Sun.COM goto err; 1635*10491SRishi.Srivatsavai@Sun.COM if (!args->found && args->name != NULL) { 1636*10491SRishi.Srivatsavai@Sun.COM mdb_printf("bridge instance %s not found\n", 1637*10491SRishi.Srivatsavai@Sun.COM args->name); 1638*10491SRishi.Srivatsavai@Sun.COM goto err; 1639*10491SRishi.Srivatsavai@Sun.COM } 1640*10491SRishi.Srivatsavai@Sun.COM mdb_free(args, sizeof (*args)); 1641*10491SRishi.Srivatsavai@Sun.COM return (DCMD_OK); 1642*10491SRishi.Srivatsavai@Sun.COM } 1643*10491SRishi.Srivatsavai@Sun.COM 1644*10491SRishi.Srivatsavai@Sun.COM err: 1645*10491SRishi.Srivatsavai@Sun.COM mdb_free(args, sizeof (*args)); 1646*10491SRishi.Srivatsavai@Sun.COM return (DCMD_ERR); 1647*10491SRishi.Srivatsavai@Sun.COM } 1648*10491SRishi.Srivatsavai@Sun.COM 1649*10491SRishi.Srivatsavai@Sun.COM /* 1650*10491SRishi.Srivatsavai@Sun.COM * Support for the "::dladm" dcmd 1651*10491SRishi.Srivatsavai@Sun.COM */ 1652*10491SRishi.Srivatsavai@Sun.COM int 1653*10491SRishi.Srivatsavai@Sun.COM dladm(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1654*10491SRishi.Srivatsavai@Sun.COM { 1655*10491SRishi.Srivatsavai@Sun.COM if (argc < 1 || argv[0].a_type != MDB_TYPE_STRING) 1656*10491SRishi.Srivatsavai@Sun.COM return (DCMD_USAGE); 1657*10491SRishi.Srivatsavai@Sun.COM 1658*10491SRishi.Srivatsavai@Sun.COM /* 1659*10491SRishi.Srivatsavai@Sun.COM * This could be a bit more elaborate, once we support more of the 1660*10491SRishi.Srivatsavai@Sun.COM * dladm show-* subcommands. 1661*10491SRishi.Srivatsavai@Sun.COM */ 1662*10491SRishi.Srivatsavai@Sun.COM argc--; 1663*10491SRishi.Srivatsavai@Sun.COM argv++; 1664*10491SRishi.Srivatsavai@Sun.COM if (strcmp(argv[-1].a_un.a_str, "show-bridge") == 0) 1665*10491SRishi.Srivatsavai@Sun.COM return (dladm_show_bridge(addr, flags, argc, argv)); 1666*10491SRishi.Srivatsavai@Sun.COM 1667*10491SRishi.Srivatsavai@Sun.COM return (DCMD_USAGE); 1668*10491SRishi.Srivatsavai@Sun.COM } 1669*10491SRishi.Srivatsavai@Sun.COM 1670*10491SRishi.Srivatsavai@Sun.COM void 1671*10491SRishi.Srivatsavai@Sun.COM dladm_help(void) 1672*10491SRishi.Srivatsavai@Sun.COM { 1673*10491SRishi.Srivatsavai@Sun.COM mdb_printf("Subcommands:\n" 1674*10491SRishi.Srivatsavai@Sun.COM " show-bridge [-flt] [<name>]\n" 1675*10491SRishi.Srivatsavai@Sun.COM "\t Show bridge information; -l for links and -f for " 1676*10491SRishi.Srivatsavai@Sun.COM "forwarding\n" 1677*10491SRishi.Srivatsavai@Sun.COM "\t entries, and -t for TRILL nicknames. Address is required " 1678*10491SRishi.Srivatsavai@Sun.COM "if name\n" 1679*10491SRishi.Srivatsavai@Sun.COM "\t is not specified.\n"); 1680*10491SRishi.Srivatsavai@Sun.COM } 1681