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 5*1676Sjpk * Common Development and Distribution License (the "License"). 6*1676Sjpk * 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 /* 22*1676Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 290Sstevel@tonic-gate #include <mdb/mdb_ks.h> 300Sstevel@tonic-gate #include <mdb/mdb_ctf.h> 310Sstevel@tonic-gate #include <sys/types.h> 320Sstevel@tonic-gate #include <sys/tihdr.h> 330Sstevel@tonic-gate #include <inet/led.h> 340Sstevel@tonic-gate #include <inet/common.h> 350Sstevel@tonic-gate #include <netinet/in.h> 360Sstevel@tonic-gate #include <netinet/ip6.h> 370Sstevel@tonic-gate #include <netinet/icmp6.h> 380Sstevel@tonic-gate #include <inet/ip.h> 390Sstevel@tonic-gate #include <inet/ip6.h> 400Sstevel@tonic-gate #include <inet/ipclassifier.h> 410Sstevel@tonic-gate #include <inet/tcp.h> 420Sstevel@tonic-gate #include <sys/stream.h> 430Sstevel@tonic-gate #include <sys/vfs.h> 440Sstevel@tonic-gate #include <sys/stropts.h> 450Sstevel@tonic-gate #include <sys/tpicommon.h> 460Sstevel@tonic-gate #include <sys/socket.h> 470Sstevel@tonic-gate #include <sys/socketvar.h> 480Sstevel@tonic-gate #include <sys/cred_impl.h> 490Sstevel@tonic-gate #include <inet/udp_impl.h> 500Sstevel@tonic-gate #include <inet/arp_impl.h> 510Sstevel@tonic-gate #include <inet/rawip_impl.h> 520Sstevel@tonic-gate #include <inet/mi.h> 530Sstevel@tonic-gate 540Sstevel@tonic-gate #define MIH2MIO(mihp) (&(mihp)->mh_o) 550Sstevel@tonic-gate 560Sstevel@tonic-gate #define ADDR_V6_WIDTH 23 570Sstevel@tonic-gate #define ADDR_V4_WIDTH 15 580Sstevel@tonic-gate 59*1676Sjpk #define NETSTAT_ALL 0x01 60*1676Sjpk #define NETSTAT_VERBOSE 0x02 61*1676Sjpk #define NETSTAT_ROUTE 0x04 62*1676Sjpk #define NETSTAT_V4 0x08 63*1676Sjpk #define NETSTAT_V6 0x10 64*1676Sjpk #define NETSTAT_UNIX 0x20 65*1676Sjpk 66*1676Sjpk #define NETSTAT_FIRST 0x80000000u 670Sstevel@tonic-gate 680Sstevel@tonic-gate /* 690Sstevel@tonic-gate * Print an IPv4 address and port number in a compact and easy to read format 700Sstevel@tonic-gate * The arguments are in network byte order 710Sstevel@tonic-gate */ 720Sstevel@tonic-gate static void 730Sstevel@tonic-gate net_ipv4addrport_pr(const in6_addr_t *nipv6addr, in_port_t nport) 740Sstevel@tonic-gate { 750Sstevel@tonic-gate uint32_t naddr = V4_PART_OF_V6((*nipv6addr)); 760Sstevel@tonic-gate 770Sstevel@tonic-gate mdb_nhconvert(&nport, &nport, sizeof (nport)); 780Sstevel@tonic-gate mdb_printf("%*I.%-5hu", ADDR_V4_WIDTH, naddr, nport); 790Sstevel@tonic-gate } 800Sstevel@tonic-gate 810Sstevel@tonic-gate /* 820Sstevel@tonic-gate * Print an IPv6 address and port number in a compact and easy to read format 830Sstevel@tonic-gate * The arguments are in network byte order 840Sstevel@tonic-gate */ 850Sstevel@tonic-gate static void 860Sstevel@tonic-gate net_ipv6addrport_pr(const in6_addr_t *naddr, in_port_t nport) 870Sstevel@tonic-gate { 880Sstevel@tonic-gate mdb_nhconvert(&nport, &nport, sizeof (nport)); 890Sstevel@tonic-gate mdb_printf("%*N.%-5hu", ADDR_V6_WIDTH, naddr, nport); 900Sstevel@tonic-gate } 910Sstevel@tonic-gate 920Sstevel@tonic-gate static int 930Sstevel@tonic-gate net_tcp_active(const tcp_t *tcp) 940Sstevel@tonic-gate { 950Sstevel@tonic-gate return (tcp->tcp_state >= TCPS_ESTABLISHED); 960Sstevel@tonic-gate } 970Sstevel@tonic-gate 980Sstevel@tonic-gate static int 990Sstevel@tonic-gate net_tcp_ipv4(const tcp_t *tcp) 1000Sstevel@tonic-gate { 1010Sstevel@tonic-gate return ((tcp->tcp_ipversion == IPV4_VERSION) || 1020Sstevel@tonic-gate (IN6_IS_ADDR_UNSPECIFIED(&tcp->tcp_ip_src_v6) && 1030Sstevel@tonic-gate (tcp->tcp_state <= TCPS_LISTEN))); 1040Sstevel@tonic-gate } 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate static int 1070Sstevel@tonic-gate net_tcp_ipv6(const tcp_t *tcp) 1080Sstevel@tonic-gate { 1090Sstevel@tonic-gate return (tcp->tcp_ipversion == IPV6_VERSION); 1100Sstevel@tonic-gate } 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate static int 1130Sstevel@tonic-gate net_udp_active(const udp_t *udp) 1140Sstevel@tonic-gate { 115741Smasputra return ((udp->udp_state == TS_IDLE) || 116741Smasputra (udp->udp_state == TS_DATA_XFER)); 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate static int 1200Sstevel@tonic-gate net_udp_ipv4(const udp_t *udp) 1210Sstevel@tonic-gate { 1220Sstevel@tonic-gate return ((udp->udp_ipversion == IPV4_VERSION) || 1230Sstevel@tonic-gate (IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src) && 1240Sstevel@tonic-gate (udp->udp_state <= TS_IDLE))); 1250Sstevel@tonic-gate } 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate static int 1280Sstevel@tonic-gate net_udp_ipv6(const udp_t *udp) 1290Sstevel@tonic-gate { 1300Sstevel@tonic-gate return (udp->udp_ipversion == IPV6_VERSION); 1310Sstevel@tonic-gate } 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate int 1340Sstevel@tonic-gate sonode_walk_init(mdb_walk_state_t *wsp) 1350Sstevel@tonic-gate { 1360Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 1370Sstevel@tonic-gate GElf_Sym sym; 1380Sstevel@tonic-gate struct socklist *slp; 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate if (mdb_lookup_by_obj("sockfs", "socklist", &sym) == -1) { 1410Sstevel@tonic-gate mdb_warn("failed to lookup sockfs`socklist"); 1420Sstevel@tonic-gate return (WALK_ERR); 1430Sstevel@tonic-gate } 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate slp = (struct socklist *)(uintptr_t)sym.st_value; 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr), 1480Sstevel@tonic-gate (uintptr_t)&slp->sl_list) == -1) { 1490Sstevel@tonic-gate mdb_warn("failed to read address of initial sonode " 1500Sstevel@tonic-gate "at %p", &slp->sl_list); 1510Sstevel@tonic-gate return (WALK_ERR); 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate } 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate wsp->walk_data = mdb_alloc(sizeof (struct sonode), UM_SLEEP); 1560Sstevel@tonic-gate return (WALK_NEXT); 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate int 1600Sstevel@tonic-gate sonode_walk_step(mdb_walk_state_t *wsp) 1610Sstevel@tonic-gate { 1620Sstevel@tonic-gate int status; 1630Sstevel@tonic-gate struct sonode *sonodep; 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate if (wsp->walk_addr == NULL) 1660Sstevel@tonic-gate return (WALK_DONE); 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate if (mdb_vread(wsp->walk_data, sizeof (struct sonode), 1690Sstevel@tonic-gate wsp->walk_addr) == -1) { 1700Sstevel@tonic-gate mdb_warn("failed to read sonode at %p", wsp->walk_addr); 1710Sstevel@tonic-gate return (WALK_ERR); 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 1750Sstevel@tonic-gate wsp->walk_cbdata); 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate sonodep = wsp->walk_data; 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)sonodep->so_next; 1800Sstevel@tonic-gate return (status); 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate void 1840Sstevel@tonic-gate sonode_walk_fini(mdb_walk_state_t *wsp) 1850Sstevel@tonic-gate { 1860Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (struct sonode)); 1870Sstevel@tonic-gate } 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate struct mi_walk_data { 1900Sstevel@tonic-gate uintptr_t mi_wd_miofirst; 1910Sstevel@tonic-gate MI_O mi_wd_miodata; 1920Sstevel@tonic-gate }; 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate int 1950Sstevel@tonic-gate mi_walk_init(mdb_walk_state_t *wsp) 1960Sstevel@tonic-gate { 1970Sstevel@tonic-gate struct mi_walk_data *wdp; 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 2000Sstevel@tonic-gate mdb_warn("mi doesn't support global walks\n"); 2010Sstevel@tonic-gate return (WALK_ERR); 2020Sstevel@tonic-gate } 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate wdp = mdb_alloc(sizeof (struct mi_walk_data), UM_SLEEP); 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate /* So that we do not immediately return WALK_DONE below */ 2070Sstevel@tonic-gate wdp->mi_wd_miofirst = NULL; 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate wsp->walk_data = wdp; 2100Sstevel@tonic-gate return (WALK_NEXT); 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate int 2140Sstevel@tonic-gate mi_walk_step(mdb_walk_state_t *wsp) 2150Sstevel@tonic-gate { 2160Sstevel@tonic-gate struct mi_walk_data *wdp = wsp->walk_data; 2170Sstevel@tonic-gate MI_OP miop = &wdp->mi_wd_miodata; 2180Sstevel@tonic-gate int status; 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate /* Always false in the first iteration */ 2210Sstevel@tonic-gate if ((wsp->walk_addr == (uintptr_t)NULL) || 2220Sstevel@tonic-gate (wsp->walk_addr == wdp->mi_wd_miofirst)) { 2230Sstevel@tonic-gate return (WALK_DONE); 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate if (mdb_vread(miop, sizeof (MI_O), wsp->walk_addr) == -1) { 2270Sstevel@tonic-gate mdb_warn("failed to read MI object at %p", wsp->walk_addr); 2280Sstevel@tonic-gate return (WALK_ERR); 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, miop, wsp->walk_cbdata); 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate /* Only true in the first iteration */ 2340Sstevel@tonic-gate if (wdp->mi_wd_miofirst == NULL) 2350Sstevel@tonic-gate wdp->mi_wd_miofirst = wsp->walk_addr; 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)miop->mi_o_next; 2380Sstevel@tonic-gate return (status); 2390Sstevel@tonic-gate } 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate void 2420Sstevel@tonic-gate mi_walk_fini(mdb_walk_state_t *wsp) 2430Sstevel@tonic-gate { 2440Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (struct mi_walk_data)); 2450Sstevel@tonic-gate } 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate typedef struct mi_payload_walk_data_s { 2480Sstevel@tonic-gate uintptr_t mi_pwd_first; 2490Sstevel@tonic-gate void *mi_pwd_data; 2500Sstevel@tonic-gate } mi_payload_walk_data_t; 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate static void 2530Sstevel@tonic-gate delete_mi_payload_walk_data(mi_payload_walk_data_t *pwdp, size_t payload_size) 2540Sstevel@tonic-gate { 2550Sstevel@tonic-gate mdb_free(pwdp->mi_pwd_data, payload_size); 2560Sstevel@tonic-gate mdb_free(pwdp, sizeof (mi_payload_walk_data_t)); 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate typedef struct mi_payload_walk_arg_s { 2600Sstevel@tonic-gate const char *mi_pwa_obj; /* load object of mi_o_head_t * */ 2610Sstevel@tonic-gate const char *mi_pwa_sym; /* symbol name of mi_o_head_t * */ 2620Sstevel@tonic-gate const size_t mi_pwa_size; /* size of mi payload */ 2630Sstevel@tonic-gate const uint_t mi_pwa_flags; /* device and/or module */ 2640Sstevel@tonic-gate } mi_payload_walk_arg_t; 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate #define MI_PAYLOAD_DEVICE 0x1 2670Sstevel@tonic-gate #define MI_PAYLOAD_MODULE 0x2 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate int 2700Sstevel@tonic-gate mi_payload_walk_init(mdb_walk_state_t *wsp) 2710Sstevel@tonic-gate { 2720Sstevel@tonic-gate const mi_payload_walk_arg_t *arg = wsp->walk_arg; 2730Sstevel@tonic-gate mi_payload_walk_data_t *pwdp; 2740Sstevel@tonic-gate GElf_Sym sym; 2750Sstevel@tonic-gate mi_head_t *mihp; 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate /* Determine the address to start or end the walk with */ 2780Sstevel@tonic-gate if (mdb_lookup_by_obj(arg->mi_pwa_obj, arg->mi_pwa_sym, &sym) == -1) { 2790Sstevel@tonic-gate mdb_warn("failed to lookup %s`%s", 2800Sstevel@tonic-gate arg->mi_pwa_obj, arg->mi_pwa_sym); 2810Sstevel@tonic-gate return (WALK_ERR); 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate if (mdb_vread(&mihp, sizeof (mihp), (uintptr_t)sym.st_value) == -1) { 2850Sstevel@tonic-gate mdb_warn("failed to read address of global MI Head " 2860Sstevel@tonic-gate "mi_o_head_t at %p", (uintptr_t)sym.st_value); 2870Sstevel@tonic-gate return (WALK_ERR); 2880Sstevel@tonic-gate } 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate pwdp = mdb_alloc(sizeof (mi_payload_walk_data_t), UM_SLEEP); 2910Sstevel@tonic-gate pwdp->mi_pwd_data = mdb_alloc(arg->mi_pwa_size, UM_SLEEP); 2920Sstevel@tonic-gate wsp->walk_data = pwdp; 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 2950Sstevel@tonic-gate /* Do not immediately return WALK_DONE below */ 2960Sstevel@tonic-gate pwdp->mi_pwd_first = NULL; 2970Sstevel@tonic-gate /* We determined where to begin */ 2980Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)MIH2MIO(mihp); 2990Sstevel@tonic-gate } else { 3000Sstevel@tonic-gate /* Do not cycle through all of the MI_O objects */ 3010Sstevel@tonic-gate pwdp->mi_pwd_first = (uintptr_t)MIH2MIO(mihp); 3020Sstevel@tonic-gate /* We were given where to begin */ 3030Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)((MI_OP)wsp->walk_addr - 1); 3040Sstevel@tonic-gate } 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate if (mdb_layered_walk("genunix`mi", wsp) == -1) { 3070Sstevel@tonic-gate mdb_warn("failed to walk genunix`mi"); 3080Sstevel@tonic-gate delete_mi_payload_walk_data(pwdp, arg->mi_pwa_size); 3090Sstevel@tonic-gate return (WALK_ERR); 3100Sstevel@tonic-gate } 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate return (WALK_NEXT); 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate int 3160Sstevel@tonic-gate mi_payload_walk_step(mdb_walk_state_t *wsp) 3170Sstevel@tonic-gate { 3180Sstevel@tonic-gate const mi_payload_walk_arg_t *arg = wsp->walk_arg; 3190Sstevel@tonic-gate mi_payload_walk_data_t *pwdp = wsp->walk_data; 3200Sstevel@tonic-gate void *payload = pwdp->mi_pwd_data; 3210Sstevel@tonic-gate uintptr_t payload_kaddr = (uintptr_t)((MI_OP)wsp->walk_addr + 1); 3220Sstevel@tonic-gate const MI_O *mio = wsp->walk_layer; 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate /* If this is a local walk, prevent cycling */ 3250Sstevel@tonic-gate if (wsp->walk_addr == pwdp->mi_pwd_first) 3260Sstevel@tonic-gate return (WALK_DONE); 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate /* 3290Sstevel@tonic-gate * This was a global walk, prevent reading this payload as the 3300Sstevel@tonic-gate * initial MI_O is the head of the list and is not the header 3310Sstevel@tonic-gate * to a valid payload 3320Sstevel@tonic-gate */ 3330Sstevel@tonic-gate if (pwdp->mi_pwd_first == NULL) { 3340Sstevel@tonic-gate pwdp->mi_pwd_first = wsp->walk_addr; 3350Sstevel@tonic-gate return (WALK_NEXT); 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate if (mio->mi_o_isdev == B_FALSE) { 3390Sstevel@tonic-gate /* mio is a module */ 3400Sstevel@tonic-gate if (!(arg->mi_pwa_flags & MI_PAYLOAD_MODULE)) 3410Sstevel@tonic-gate return (WALK_NEXT); 3420Sstevel@tonic-gate } else { 3430Sstevel@tonic-gate /* mio is a device */ 3440Sstevel@tonic-gate if (!(arg->mi_pwa_flags & MI_PAYLOAD_DEVICE)) 3450Sstevel@tonic-gate return (WALK_NEXT); 3460Sstevel@tonic-gate } 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate if (mdb_vread(payload, arg->mi_pwa_size, payload_kaddr) == -1) { 3490Sstevel@tonic-gate mdb_warn("failed to read payload at %p", payload_kaddr); 3500Sstevel@tonic-gate return (WALK_ERR); 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate return (wsp->walk_callback(payload_kaddr, payload, wsp->walk_cbdata)); 3540Sstevel@tonic-gate } 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate void 3570Sstevel@tonic-gate mi_payload_walk_fini(mdb_walk_state_t *wsp) 3580Sstevel@tonic-gate { 3590Sstevel@tonic-gate const mi_payload_walk_arg_t *arg = wsp->walk_arg; 3600Sstevel@tonic-gate 3610Sstevel@tonic-gate delete_mi_payload_walk_data(wsp->walk_data, arg->mi_pwa_size); 3620Sstevel@tonic-gate } 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate const mi_payload_walk_arg_t mi_ar_arg = { 3650Sstevel@tonic-gate "arp", "ar_g_head", sizeof (ar_t), 3660Sstevel@tonic-gate MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE 3670Sstevel@tonic-gate }; 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate const mi_payload_walk_arg_t mi_icmp_arg = { 3700Sstevel@tonic-gate "icmp", "icmp_g_head", sizeof (icmp_t), 3710Sstevel@tonic-gate MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE 3720Sstevel@tonic-gate }; 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate const mi_payload_walk_arg_t mi_ill_arg = 3750Sstevel@tonic-gate { "ip", "ip_g_head", sizeof (ill_t), MI_PAYLOAD_MODULE }; 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate int 3780Sstevel@tonic-gate sonode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3790Sstevel@tonic-gate { 3800Sstevel@tonic-gate const char *optf = NULL; 3810Sstevel@tonic-gate const char *optt = NULL; 3820Sstevel@tonic-gate const char *optp = NULL; 3830Sstevel@tonic-gate int family, type, proto; 3840Sstevel@tonic-gate int filter = 0; 3850Sstevel@tonic-gate struct sonode so; 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 3880Sstevel@tonic-gate if (mdb_walk_dcmd("genunix`sonode", "genunix`sonode", argc, 3890Sstevel@tonic-gate argv) == -1) { 3900Sstevel@tonic-gate mdb_warn("failed to walk sonode"); 3910Sstevel@tonic-gate return (DCMD_ERR); 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate return (DCMD_OK); 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate if (mdb_getopts(argc, argv, 3980Sstevel@tonic-gate 'f', MDB_OPT_STR, &optf, 3990Sstevel@tonic-gate 't', MDB_OPT_STR, &optt, 4000Sstevel@tonic-gate 'p', MDB_OPT_STR, &optp, 4010Sstevel@tonic-gate NULL) != argc) 4020Sstevel@tonic-gate return (DCMD_USAGE); 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate if (optf != NULL) { 4050Sstevel@tonic-gate if (strcmp("inet", optf) == 0) 4060Sstevel@tonic-gate family = AF_INET; 4070Sstevel@tonic-gate else if (strcmp("inet6", optf) == 0) 4080Sstevel@tonic-gate family = AF_INET6; 4090Sstevel@tonic-gate else if (strcmp("unix", optf) == 0) 4100Sstevel@tonic-gate family = AF_UNIX; 4110Sstevel@tonic-gate else 4120Sstevel@tonic-gate family = mdb_strtoull(optf); 4130Sstevel@tonic-gate filter = 1; 4140Sstevel@tonic-gate } 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate if (optt != NULL) { 4170Sstevel@tonic-gate if (strcmp("stream", optt) == 0) 4180Sstevel@tonic-gate type = SOCK_STREAM; 4190Sstevel@tonic-gate else if (strcmp("dgram", optt) == 0) 4200Sstevel@tonic-gate type = SOCK_DGRAM; 4210Sstevel@tonic-gate else if (strcmp("raw", optt) == 0) 4220Sstevel@tonic-gate type = SOCK_RAW; 4230Sstevel@tonic-gate else 4240Sstevel@tonic-gate type = mdb_strtoull(optt); 4250Sstevel@tonic-gate filter = 1; 4260Sstevel@tonic-gate } 4270Sstevel@tonic-gate 4280Sstevel@tonic-gate if (optp != NULL) { 4290Sstevel@tonic-gate proto = mdb_strtoull(optp); 4300Sstevel@tonic-gate filter = 1; 4310Sstevel@tonic-gate } 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && !filter) { 4340Sstevel@tonic-gate mdb_printf("%<u>%-?s Family Type Proto State Mode Flag " 4350Sstevel@tonic-gate "AccessVP%</u>\n", "Sonode:"); 4360Sstevel@tonic-gate } 4370Sstevel@tonic-gate 4380Sstevel@tonic-gate if (mdb_vread(&so, sizeof (so), addr) == -1) { 4390Sstevel@tonic-gate mdb_warn("failed to read sonode at %p", addr); 4400Sstevel@tonic-gate return (DCMD_ERR); 4410Sstevel@tonic-gate } 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate if ((optf != NULL) && (so.so_family != family)) 4440Sstevel@tonic-gate return (DCMD_OK); 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate if ((optt != NULL) && (so.so_type != type)) 4470Sstevel@tonic-gate return (DCMD_OK); 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate if ((optp != NULL) && (so.so_protocol != proto)) 4500Sstevel@tonic-gate return (DCMD_OK); 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate if (filter) { 4530Sstevel@tonic-gate mdb_printf("%0?p\n", addr); 4540Sstevel@tonic-gate return (DCMD_OK); 4550Sstevel@tonic-gate } 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate mdb_printf("%0?p ", addr); 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate switch (so.so_family) { 4600Sstevel@tonic-gate case AF_UNIX: 4610Sstevel@tonic-gate mdb_printf("unix "); 4620Sstevel@tonic-gate break; 4630Sstevel@tonic-gate case AF_INET: 4640Sstevel@tonic-gate mdb_printf("inet "); 4650Sstevel@tonic-gate break; 4660Sstevel@tonic-gate case AF_INET6: 4670Sstevel@tonic-gate mdb_printf("inet6 "); 4680Sstevel@tonic-gate break; 4690Sstevel@tonic-gate default: 4700Sstevel@tonic-gate mdb_printf("%6hi", so.so_family); 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate switch (so.so_type) { 4740Sstevel@tonic-gate case SOCK_STREAM: 4750Sstevel@tonic-gate mdb_printf(" strm"); 4760Sstevel@tonic-gate break; 4770Sstevel@tonic-gate case SOCK_DGRAM: 4780Sstevel@tonic-gate mdb_printf(" dgrm"); 4790Sstevel@tonic-gate break; 4800Sstevel@tonic-gate case SOCK_RAW: 4810Sstevel@tonic-gate mdb_printf(" raw "); 4820Sstevel@tonic-gate break; 4830Sstevel@tonic-gate default: 4840Sstevel@tonic-gate mdb_printf(" %4hi", so.so_type); 4850Sstevel@tonic-gate } 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate mdb_printf(" %5hi %05x %04x %04hx %0?p\n", 4880Sstevel@tonic-gate so.so_protocol, so.so_state, so.so_mode, 4890Sstevel@tonic-gate so.so_flag, so.so_accessvp); 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate return (DCMD_OK); 4920Sstevel@tonic-gate } 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate #define MI_PAYLOAD 0x1 4950Sstevel@tonic-gate #define MI_DEVICE 0x2 4960Sstevel@tonic-gate #define MI_MODULE 0x4 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate int 4990Sstevel@tonic-gate mi(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 5000Sstevel@tonic-gate { 5010Sstevel@tonic-gate uint_t opts = 0; 5020Sstevel@tonic-gate MI_O mio; 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 5050Sstevel@tonic-gate return (DCMD_USAGE); 5060Sstevel@tonic-gate 5070Sstevel@tonic-gate if (mdb_getopts(argc, argv, 5080Sstevel@tonic-gate 'p', MDB_OPT_SETBITS, MI_PAYLOAD, &opts, 5090Sstevel@tonic-gate 'd', MDB_OPT_SETBITS, MI_DEVICE, &opts, 5100Sstevel@tonic-gate 'm', MDB_OPT_SETBITS, MI_MODULE, &opts, 5110Sstevel@tonic-gate NULL) != argc) 5120Sstevel@tonic-gate return (DCMD_USAGE); 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate if ((opts & (MI_DEVICE | MI_MODULE)) == (MI_DEVICE | MI_MODULE)) { 5150Sstevel@tonic-gate mdb_warn("at most one filter, d for devices or m " 5160Sstevel@tonic-gate "for modules, may be specified\n"); 5170Sstevel@tonic-gate return (DCMD_USAGE); 5180Sstevel@tonic-gate } 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate if ((opts == 0) && (DCMD_HDRSPEC(flags))) { 5210Sstevel@tonic-gate mdb_printf("%<u>%-?s %-?s %-?s IsDev Dev%</u>\n", 5220Sstevel@tonic-gate "MI_O", "Next", "Prev"); 5230Sstevel@tonic-gate } 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate if (mdb_vread(&mio, sizeof (mio), addr) == -1) { 5260Sstevel@tonic-gate mdb_warn("failed to read mi object MI_O at %p", addr); 5270Sstevel@tonic-gate return (DCMD_ERR); 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate if (opts != 0) { 5310Sstevel@tonic-gate if (mio.mi_o_isdev == B_FALSE) { 5320Sstevel@tonic-gate /* mio is a module */ 5330Sstevel@tonic-gate if (!(opts & MI_MODULE) && (opts & MI_DEVICE)) 5340Sstevel@tonic-gate return (DCMD_OK); 5350Sstevel@tonic-gate } else { 5360Sstevel@tonic-gate /* mio is a device */ 5370Sstevel@tonic-gate if (!(opts & MI_DEVICE) && (opts & MI_MODULE)) 5380Sstevel@tonic-gate return (DCMD_OK); 5390Sstevel@tonic-gate } 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate if (opts & MI_PAYLOAD) 5420Sstevel@tonic-gate mdb_printf("%p\n", addr + sizeof (MI_O)); 5430Sstevel@tonic-gate else 5440Sstevel@tonic-gate mdb_printf("%p\n", addr); 5450Sstevel@tonic-gate return (DCMD_OK); 5460Sstevel@tonic-gate } 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate mdb_printf("%0?p %0?p %0?p ", addr, mio.mi_o_next, mio.mi_o_prev); 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate if (mio.mi_o_isdev == B_FALSE) 5510Sstevel@tonic-gate mdb_printf("FALSE"); 5520Sstevel@tonic-gate else 5530Sstevel@tonic-gate mdb_printf("TRUE "); 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate mdb_printf(" %0?p\n", mio.mi_o_dev); 5560Sstevel@tonic-gate 5570Sstevel@tonic-gate return (DCMD_OK); 5580Sstevel@tonic-gate } 5590Sstevel@tonic-gate 5600Sstevel@tonic-gate static void 5610Sstevel@tonic-gate netstat_tcp_verbose_pr(const tcp_t *tcp) 5620Sstevel@tonic-gate { 5630Sstevel@tonic-gate mdb_printf(" %5i %08x %08x %5i %08x %08x %5li %5i\n", 5640Sstevel@tonic-gate tcp->tcp_swnd, tcp->tcp_snxt, tcp->tcp_suna, tcp->tcp_rwnd, 5650Sstevel@tonic-gate tcp->tcp_rack, tcp->tcp_rnxt, tcp->tcp_rto, tcp->tcp_mss); 5660Sstevel@tonic-gate } 5670Sstevel@tonic-gate 5680Sstevel@tonic-gate /*ARGSUSED*/ 5690Sstevel@tonic-gate static int 5700Sstevel@tonic-gate netstat_tcp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data, int af) 5710Sstevel@tonic-gate { 5720Sstevel@tonic-gate const uintptr_t opts = (uintptr_t)cb_data; 5730Sstevel@tonic-gate static size_t itc_size = 0; 5740Sstevel@tonic-gate uintptr_t tcp_kaddr; 5750Sstevel@tonic-gate conn_t *connp; 5760Sstevel@tonic-gate tcp_t *tcp; 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate if (itc_size == 0) { 5790Sstevel@tonic-gate mdb_ctf_id_t id; 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate if (mdb_ctf_lookup_by_name("itc_t", &id) != 0) { 5820Sstevel@tonic-gate mdb_warn("failed to lookup type 'itc_t'"); 5830Sstevel@tonic-gate return (WALK_ERR); 5840Sstevel@tonic-gate } 5850Sstevel@tonic-gate itc_size = mdb_ctf_type_size(id); 5860Sstevel@tonic-gate } 5870Sstevel@tonic-gate 5880Sstevel@tonic-gate connp = (conn_t *)mdb_alloc(itc_size, UM_SLEEP | UM_GC); 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate if (mdb_vread(connp, itc_size, kaddr) == -1) { 5910Sstevel@tonic-gate mdb_warn("failed to read connection info at %p", kaddr); 5920Sstevel@tonic-gate return (WALK_ERR); 5930Sstevel@tonic-gate } 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate tcp_kaddr = (uintptr_t)connp->conn_tcp; 5960Sstevel@tonic-gate tcp = (tcp_t *)((uintptr_t)connp + (tcp_kaddr - kaddr)); 5970Sstevel@tonic-gate 5980Sstevel@tonic-gate if ((uintptr_t)tcp < (uintptr_t)connp || 599741Smasputra (uintptr_t)(tcp + 1) > (uintptr_t)connp + itc_size || 6000Sstevel@tonic-gate (uintptr_t)tcp->tcp_connp != kaddr) { 6010Sstevel@tonic-gate mdb_warn("conn_tcp %p is invalid", tcp_kaddr); 6020Sstevel@tonic-gate return (WALK_NEXT); 6030Sstevel@tonic-gate } 6040Sstevel@tonic-gate connp->conn_tcp = tcp; 6050Sstevel@tonic-gate tcp->tcp_connp = connp; 6060Sstevel@tonic-gate 607741Smasputra if (!((opts & NETSTAT_ALL) || net_tcp_active(tcp)) || 6080Sstevel@tonic-gate (af == AF_INET && !net_tcp_ipv4(tcp)) || 6090Sstevel@tonic-gate (af == AF_INET6 && !net_tcp_ipv6(tcp))) { 6100Sstevel@tonic-gate return (WALK_NEXT); 6110Sstevel@tonic-gate } 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate mdb_printf("%0?p %2i ", tcp_kaddr, tcp->tcp_state); 6140Sstevel@tonic-gate if (af == AF_INET) { 6150Sstevel@tonic-gate net_ipv4addrport_pr(&tcp->tcp_ip_src_v6, tcp->tcp_lport); 6160Sstevel@tonic-gate mdb_printf(" "); 6170Sstevel@tonic-gate net_ipv4addrport_pr(&tcp->tcp_remote_v6, tcp->tcp_fport); 6180Sstevel@tonic-gate } else if (af == AF_INET6) { 6190Sstevel@tonic-gate net_ipv6addrport_pr(&tcp->tcp_ip_src_v6, tcp->tcp_lport); 6200Sstevel@tonic-gate mdb_printf(" "); 6210Sstevel@tonic-gate net_ipv6addrport_pr(&tcp->tcp_remote_v6, tcp->tcp_fport); 6220Sstevel@tonic-gate } 6230Sstevel@tonic-gate mdb_printf(" %4i\n", connp->conn_zoneid); 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate if (opts & NETSTAT_VERBOSE) 6260Sstevel@tonic-gate netstat_tcp_verbose_pr(tcp); 6270Sstevel@tonic-gate 6280Sstevel@tonic-gate return (WALK_NEXT); 6290Sstevel@tonic-gate } 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate static int 6320Sstevel@tonic-gate netstat_tcpv4_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 6330Sstevel@tonic-gate { 6340Sstevel@tonic-gate return (netstat_tcp_cb(kaddr, walk_data, cb_data, AF_INET)); 6350Sstevel@tonic-gate } 6360Sstevel@tonic-gate 6370Sstevel@tonic-gate static int 6380Sstevel@tonic-gate netstat_tcpv6_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 6390Sstevel@tonic-gate { 6400Sstevel@tonic-gate return (netstat_tcp_cb(kaddr, walk_data, cb_data, AF_INET6)); 6410Sstevel@tonic-gate } 6420Sstevel@tonic-gate 643741Smasputra /*ARGSUSED*/ 6440Sstevel@tonic-gate static int 645741Smasputra netstat_udp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data, int af) 6460Sstevel@tonic-gate { 6470Sstevel@tonic-gate const uintptr_t opts = (uintptr_t)cb_data; 648741Smasputra udp_t udp; 649741Smasputra conn_t connp; 650741Smasputra 651741Smasputra if (mdb_vread(&udp, sizeof (udp_t), kaddr) == -1) { 652741Smasputra mdb_warn("failed to read udp at %p", kaddr); 653741Smasputra return (WALK_ERR); 654741Smasputra } 6550Sstevel@tonic-gate 656741Smasputra if (mdb_vread(&connp, sizeof (conn_t), 657741Smasputra (uintptr_t)udp.udp_connp) == -1) { 658741Smasputra mdb_warn("failed to read udp_connp at %p", 659741Smasputra (uintptr_t)udp.udp_connp); 660741Smasputra return (WALK_ERR); 661741Smasputra } 6620Sstevel@tonic-gate 663741Smasputra if (!((opts & NETSTAT_ALL) || net_udp_active(&udp)) || 664741Smasputra (af == AF_INET && !net_udp_ipv4(&udp)) || 665741Smasputra (af == AF_INET6 && !net_udp_ipv6(&udp))) { 666741Smasputra return (WALK_NEXT); 667741Smasputra } 668741Smasputra 669741Smasputra mdb_printf("%0?p %2i ", kaddr, udp.udp_state); 670741Smasputra if (af == AF_INET) { 671741Smasputra net_ipv4addrport_pr(&udp.udp_v6src, udp.udp_port); 672741Smasputra mdb_printf(" "); 673741Smasputra net_ipv4addrport_pr(&udp.udp_v6dst, udp.udp_dstport); 674741Smasputra } else if (af == AF_INET6) { 675741Smasputra net_ipv6addrport_pr(&udp.udp_v6src, udp.udp_port); 676741Smasputra mdb_printf(" "); 677741Smasputra net_ipv6addrport_pr(&udp.udp_v6dst, udp.udp_dstport); 678741Smasputra } 679741Smasputra mdb_printf(" %4i\n", connp.conn_zoneid); 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate return (WALK_NEXT); 6820Sstevel@tonic-gate } 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate static int 685741Smasputra netstat_udpv4_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 686741Smasputra { 687741Smasputra return (netstat_udp_cb(kaddr, walk_data, cb_data, AF_INET)); 688741Smasputra } 689741Smasputra 690741Smasputra static int 6910Sstevel@tonic-gate netstat_udpv6_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 6920Sstevel@tonic-gate { 693741Smasputra return (netstat_udp_cb(kaddr, walk_data, cb_data, AF_INET6)); 6940Sstevel@tonic-gate } 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate /* 6970Sstevel@tonic-gate * print the address of a unix domain socket 6980Sstevel@tonic-gate * 6990Sstevel@tonic-gate * so is the address of a AF_UNIX struct sonode in mdb's address space 7000Sstevel@tonic-gate * soa is the address of the struct soaddr to print 7010Sstevel@tonic-gate * 7020Sstevel@tonic-gate * returns 0 on success, -1 otherwise 7030Sstevel@tonic-gate */ 7040Sstevel@tonic-gate static int 7050Sstevel@tonic-gate netstat_unix_name_pr(const struct sonode *so, const struct soaddr *soa) 7060Sstevel@tonic-gate { 7070Sstevel@tonic-gate const char none[] = " (none)"; 7080Sstevel@tonic-gate 7090Sstevel@tonic-gate if ((so->so_state & SS_ISBOUND) && (soa->soa_len != 0)) { 7100Sstevel@tonic-gate if (so->so_state & SS_FADDR_NOXLATE) { 7110Sstevel@tonic-gate mdb_printf("%-14s ", " (socketpair)"); 7120Sstevel@tonic-gate } else { 7130Sstevel@tonic-gate if (soa->soa_len > sizeof (sa_family_t)) { 7140Sstevel@tonic-gate char addr[MAXPATHLEN + 1]; 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate if (mdb_readstr(addr, sizeof (addr), 7170Sstevel@tonic-gate (uintptr_t)&soa->soa_sa->sa_data) == -1) { 7180Sstevel@tonic-gate mdb_warn("failed to read unix address " 7190Sstevel@tonic-gate "at %p", &soa->soa_sa->sa_data); 7200Sstevel@tonic-gate return (-1); 7210Sstevel@tonic-gate } 7220Sstevel@tonic-gate 7230Sstevel@tonic-gate mdb_printf("%-14s ", addr); 7240Sstevel@tonic-gate } else { 7250Sstevel@tonic-gate mdb_printf("%-14s ", none); 7260Sstevel@tonic-gate } 7270Sstevel@tonic-gate } 7280Sstevel@tonic-gate } else { 7290Sstevel@tonic-gate mdb_printf("%-14s ", none); 7300Sstevel@tonic-gate } 7310Sstevel@tonic-gate 7320Sstevel@tonic-gate return (0); 7330Sstevel@tonic-gate } 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate /* based on sockfs_snapshot */ 7360Sstevel@tonic-gate /*ARGSUSED*/ 7370Sstevel@tonic-gate static int 7380Sstevel@tonic-gate netstat_unix_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 7390Sstevel@tonic-gate { 7400Sstevel@tonic-gate const struct sonode *so = walk_data; 7410Sstevel@tonic-gate 7420Sstevel@tonic-gate if (so->so_accessvp == NULL) 7430Sstevel@tonic-gate return (WALK_NEXT); 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate if (so->so_family != AF_UNIX) { 7460Sstevel@tonic-gate mdb_warn("sonode of family %hi at %p\n", so->so_family, kaddr); 7470Sstevel@tonic-gate return (WALK_ERR); 7480Sstevel@tonic-gate } 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate mdb_printf("%-?p ", kaddr); 7510Sstevel@tonic-gate 7520Sstevel@tonic-gate switch (so->so_serv_type) { 7530Sstevel@tonic-gate case T_CLTS: 7540Sstevel@tonic-gate mdb_printf("%-10s ", "dgram"); 7550Sstevel@tonic-gate break; 7560Sstevel@tonic-gate case T_COTS: 7570Sstevel@tonic-gate mdb_printf("%-10s ", "stream"); 7580Sstevel@tonic-gate break; 7590Sstevel@tonic-gate case T_COTS_ORD: 7600Sstevel@tonic-gate mdb_printf("%-10s ", "stream-ord"); 7610Sstevel@tonic-gate break; 7620Sstevel@tonic-gate default: 7630Sstevel@tonic-gate mdb_printf("%-10i ", so->so_serv_type); 7640Sstevel@tonic-gate } 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate if ((so->so_state & SS_ISBOUND) && 7670Sstevel@tonic-gate (so->so_ux_laddr.soua_magic == SOU_MAGIC_EXPLICIT)) { 7680Sstevel@tonic-gate mdb_printf("%0?p ", so->so_ux_laddr.soua_vp); 7690Sstevel@tonic-gate } else { 7700Sstevel@tonic-gate mdb_printf("%0?p ", NULL); 7710Sstevel@tonic-gate } 7720Sstevel@tonic-gate 7730Sstevel@tonic-gate if ((so->so_state & SS_ISCONNECTED) && 7740Sstevel@tonic-gate (so->so_ux_faddr.soua_magic == SOU_MAGIC_EXPLICIT)) { 7750Sstevel@tonic-gate mdb_printf("%0?p ", so->so_ux_faddr.soua_vp); 7760Sstevel@tonic-gate } else { 7770Sstevel@tonic-gate mdb_printf("%0?p ", NULL); 7780Sstevel@tonic-gate } 7790Sstevel@tonic-gate 7800Sstevel@tonic-gate if (netstat_unix_name_pr(so, &so->so_laddr) == -1) 7810Sstevel@tonic-gate return (WALK_ERR); 7820Sstevel@tonic-gate 7830Sstevel@tonic-gate if (netstat_unix_name_pr(so, &so->so_faddr) == -1) 7840Sstevel@tonic-gate return (WALK_ERR); 7850Sstevel@tonic-gate 7860Sstevel@tonic-gate mdb_printf("%4i\n", so->so_zoneid); 7870Sstevel@tonic-gate 7880Sstevel@tonic-gate return (WALK_NEXT); 7890Sstevel@tonic-gate } 7900Sstevel@tonic-gate 7910Sstevel@tonic-gate static void 7920Sstevel@tonic-gate netstat_tcp_verbose_header_pr(void) 7930Sstevel@tonic-gate { 7940Sstevel@tonic-gate mdb_printf(" %<u>%-5s %-8s %-8s %-5s %-8s %-8s %5s %5s%</u>\n", 7950Sstevel@tonic-gate "Swind", "Snext", "Suna", "Rwind", "Rack", "Rnext", "Rto", "Mss"); 7960Sstevel@tonic-gate } 7970Sstevel@tonic-gate 798*1676Sjpk static void 799*1676Sjpk get_ifname(const ire_t *ire, char *intf) 800*1676Sjpk { 801*1676Sjpk ill_t ill; 802*1676Sjpk 803*1676Sjpk *intf = '\0'; 804*1676Sjpk if (ire->ire_type == IRE_CACHE) { 805*1676Sjpk queue_t stq; 806*1676Sjpk 807*1676Sjpk if (mdb_vread(&stq, sizeof (stq), (uintptr_t)ire->ire_stq) == 808*1676Sjpk -1) 809*1676Sjpk return; 810*1676Sjpk if (mdb_vread(&ill, sizeof (ill), (uintptr_t)stq.q_ptr) == -1) 811*1676Sjpk return; 812*1676Sjpk (void) mdb_readstr(intf, MIN(LIFNAMSIZ, ill.ill_name_length), 813*1676Sjpk (uintptr_t)ill.ill_name); 814*1676Sjpk } else if (ire->ire_ipif != NULL) { 815*1676Sjpk ipif_t ipif; 816*1676Sjpk char *cp; 817*1676Sjpk 818*1676Sjpk if (mdb_vread(&ipif, sizeof (ipif), 819*1676Sjpk (uintptr_t)ire->ire_ipif) == -1) 820*1676Sjpk return; 821*1676Sjpk if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ipif.ipif_ill) == 822*1676Sjpk -1) 823*1676Sjpk return; 824*1676Sjpk (void) mdb_readstr(intf, MIN(LIFNAMSIZ, ill.ill_name_length), 825*1676Sjpk (uintptr_t)ill.ill_name); 826*1676Sjpk if (ipif.ipif_id != 0) { 827*1676Sjpk cp = intf + strlen(intf); 828*1676Sjpk (void) mdb_snprintf(cp, LIFNAMSIZ + 1 - (cp - intf), 829*1676Sjpk ":%u", ipif.ipif_id); 830*1676Sjpk } 831*1676Sjpk } 832*1676Sjpk } 833*1676Sjpk 834*1676Sjpk static void 835*1676Sjpk get_v4flags(const ire_t *ire, char *flags) 836*1676Sjpk { 837*1676Sjpk (void) strcpy(flags, "U"); 838*1676Sjpk if (ire->ire_type == IRE_DEFAULT || ire->ire_type == IRE_PREFIX || 839*1676Sjpk ire->ire_type == IRE_HOST || ire->ire_type == IRE_HOST_REDIRECT) 840*1676Sjpk (void) strcat(flags, "G"); 841*1676Sjpk if (ire->ire_mask == IP_HOST_MASK) 842*1676Sjpk (void) strcat(flags, "H"); 843*1676Sjpk if (ire->ire_type == IRE_HOST_REDIRECT) 844*1676Sjpk (void) strcat(flags, "D"); 845*1676Sjpk if (ire->ire_type == IRE_CACHE) 846*1676Sjpk (void) strcat(flags, "A"); 847*1676Sjpk if (ire->ire_type == IRE_BROADCAST) 848*1676Sjpk (void) strcat(flags, "B"); 849*1676Sjpk if (ire->ire_type == IRE_LOCAL) 850*1676Sjpk (void) strcat(flags, "L"); 851*1676Sjpk if (ire->ire_flags & RTF_MULTIRT) 852*1676Sjpk (void) strcat(flags, "M"); 853*1676Sjpk if (ire->ire_flags & RTF_SETSRC) 854*1676Sjpk (void) strcat(flags, "S"); 855*1676Sjpk } 856*1676Sjpk 857*1676Sjpk static int 858*1676Sjpk ip_mask_to_plen(ipaddr_t mask) 859*1676Sjpk { 860*1676Sjpk int i; 861*1676Sjpk 862*1676Sjpk if (mask == 0) 863*1676Sjpk return (0); 864*1676Sjpk for (i = 32; i > 0; i--, mask >>= 1) 865*1676Sjpk if (mask & 1) 866*1676Sjpk break; 867*1676Sjpk return (i); 868*1676Sjpk } 869*1676Sjpk 870*1676Sjpk static int 871*1676Sjpk netstat_irev4_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 872*1676Sjpk { 873*1676Sjpk const ire_t *ire = walk_data; 874*1676Sjpk uint_t *opts = cb_data; 875*1676Sjpk ipaddr_t gate; 876*1676Sjpk char flags[10], intf[LIFNAMSIZ + 1]; 877*1676Sjpk 878*1676Sjpk if (ire->ire_ipversion != IPV4_VERSION || ire->ire_in_src_addr != 0 || 879*1676Sjpk ire->ire_in_ill != NULL) 880*1676Sjpk return (WALK_NEXT); 881*1676Sjpk 882*1676Sjpk if (!(*opts & NETSTAT_ALL) && (ire->ire_type == IRE_CACHE || 883*1676Sjpk ire->ire_type == IRE_BROADCAST || ire->ire_type == IRE_LOCAL)) 884*1676Sjpk return (WALK_NEXT); 885*1676Sjpk 886*1676Sjpk if (*opts & NETSTAT_FIRST) { 887*1676Sjpk *opts &= ~NETSTAT_FIRST; 888*1676Sjpk mdb_printf("%<u>%s Table: IPv4%</u>\n", 889*1676Sjpk (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing"); 890*1676Sjpk if (*opts & NETSTAT_VERBOSE) { 891*1676Sjpk mdb_printf("%<u>%-?s %-*s %-*s %-*s Device Mxfrg Rtt " 892*1676Sjpk " Ref Flg Out In/Fwd%</u>\n", 893*1676Sjpk "Address", ADDR_V4_WIDTH, "Destination", 894*1676Sjpk ADDR_V4_WIDTH, "Mask", ADDR_V4_WIDTH, "Gateway"); 895*1676Sjpk } else { 896*1676Sjpk mdb_printf("%<u>%-?s %-*s %-*s Flags Ref Use " 897*1676Sjpk "Interface%</u>\n", 898*1676Sjpk "Address", ADDR_V4_WIDTH, "Destination", 899*1676Sjpk ADDR_V4_WIDTH, "Gateway"); 900*1676Sjpk } 901*1676Sjpk } 902*1676Sjpk 903*1676Sjpk gate = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK|IRE_BROADCAST)) ? 904*1676Sjpk ire->ire_src_addr : ire->ire_gateway_addr; 905*1676Sjpk 906*1676Sjpk get_v4flags(ire, flags); 907*1676Sjpk 908*1676Sjpk get_ifname(ire, intf); 909*1676Sjpk 910*1676Sjpk if (*opts & NETSTAT_VERBOSE) { 911*1676Sjpk mdb_printf("%?p %-*I %-*I %-*I %-6s %5u%c %4u %3u %-3s %5u " 912*1676Sjpk "%u\n", kaddr, ADDR_V4_WIDTH, ire->ire_addr, ADDR_V4_WIDTH, 913*1676Sjpk ire->ire_mask, ADDR_V4_WIDTH, gate, intf, 914*1676Sjpk ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ', 915*1676Sjpk ire->ire_uinfo.iulp_rtt, ire->ire_refcnt, flags, 916*1676Sjpk ire->ire_ob_pkt_count, ire->ire_ib_pkt_count); 917*1676Sjpk } else { 918*1676Sjpk mdb_printf("%?p %-*I %-*I %-5s %4u %5u %s\n", kaddr, 919*1676Sjpk ADDR_V4_WIDTH, ire->ire_addr, ADDR_V4_WIDTH, gate, flags, 920*1676Sjpk ire->ire_refcnt, 921*1676Sjpk ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf); 922*1676Sjpk } 923*1676Sjpk 924*1676Sjpk return (WALK_NEXT); 925*1676Sjpk } 926*1676Sjpk 927*1676Sjpk static int 928*1676Sjpk netstat_irev4src_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 929*1676Sjpk { 930*1676Sjpk const ire_t *ire = walk_data; 931*1676Sjpk uint_t *opts = cb_data; 932*1676Sjpk ipaddr_t gate; 933*1676Sjpk char flags[10], intf[LIFNAMSIZ + 1], srcif[LIFNAMSIZ + 1]; 934*1676Sjpk char dest[ADDR_V4_WIDTH + 3 + 1]; 935*1676Sjpk ill_t ill; 936*1676Sjpk 937*1676Sjpk if (ire->ire_ipversion != IPV4_VERSION || 938*1676Sjpk (ire->ire_in_src_addr == 0 && ire->ire_in_ill == NULL)) 939*1676Sjpk return (WALK_NEXT); 940*1676Sjpk 941*1676Sjpk if (!(*opts & NETSTAT_ALL) && (ire->ire_type == IRE_CACHE || 942*1676Sjpk ire->ire_type == IRE_BROADCAST || ire->ire_type == IRE_LOCAL)) 943*1676Sjpk return (WALK_NEXT); 944*1676Sjpk 945*1676Sjpk if (*opts & NETSTAT_FIRST) { 946*1676Sjpk *opts &= ~NETSTAT_FIRST; 947*1676Sjpk mdb_printf("\n%<u>%s Table: IPv4 Source-Specific%</u>\n", 948*1676Sjpk (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing"); 949*1676Sjpk if (*opts & NETSTAT_VERBOSE) { 950*1676Sjpk mdb_printf("%<u>%-?s %-*s In If %-*s %-*s " 951*1676Sjpk "Out If Mxfrg Rtt Ref Flg Out In/Fwd" 952*1676Sjpk "%</u>\n", 953*1676Sjpk "Address", ADDR_V4_WIDTH+3, "Destination", 954*1676Sjpk ADDR_V4_WIDTH, "Source", ADDR_V4_WIDTH, "Gateway"); 955*1676Sjpk } else { 956*1676Sjpk mdb_printf("%<u>%-?s %-*s In If %-*s %-*s Flags " 957*1676Sjpk "Ref Use Out If%</u>\n", 958*1676Sjpk "Address", ADDR_V4_WIDTH+3, "Destination", 959*1676Sjpk ADDR_V4_WIDTH, "Source", ADDR_V4_WIDTH, "Gateway"); 960*1676Sjpk } 961*1676Sjpk } 962*1676Sjpk 963*1676Sjpk gate = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK|IRE_BROADCAST)) ? 964*1676Sjpk ire->ire_src_addr : ire->ire_gateway_addr; 965*1676Sjpk 966*1676Sjpk get_v4flags(ire, flags); 967*1676Sjpk 968*1676Sjpk get_ifname(ire, intf); 969*1676Sjpk 970*1676Sjpk srcif[0] = '\0'; 971*1676Sjpk if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ire->ire_in_ill) != -1) 972*1676Sjpk (void) mdb_readstr(srcif, MIN(LIFNAMSIZ, ill.ill_name_length), 973*1676Sjpk (uintptr_t)ill.ill_name); 974*1676Sjpk 975*1676Sjpk if (ire->ire_in_src_addr != 0 && ire->ire_addr == 0 && 976*1676Sjpk ire->ire_mask == 0) 977*1676Sjpk strcpy(dest, " --"); 978*1676Sjpk else 979*1676Sjpk mdb_snprintf(dest, sizeof (dest), "%I/%d", ire->ire_addr, 980*1676Sjpk ip_mask_to_plen(ire->ire_mask)); 981*1676Sjpk 982*1676Sjpk if (*opts & NETSTAT_VERBOSE) { 983*1676Sjpk mdb_printf("%?p %-*s %-11s %-*I %-*I %-11s %5u%c %4u %3u %-3s " 984*1676Sjpk "%5u %u\n", kaddr, ADDR_V4_WIDTH+3, dest, srcif, 985*1676Sjpk ADDR_V4_WIDTH, ire->ire_in_src_addr, ADDR_V4_WIDTH, gate, 986*1676Sjpk intf, ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ', 987*1676Sjpk ire->ire_uinfo.iulp_rtt, ire->ire_refcnt, flags, 988*1676Sjpk ire->ire_ob_pkt_count, ire->ire_ib_pkt_count); 989*1676Sjpk } else { 990*1676Sjpk mdb_printf("%?p %-*s %-8s %-*I %-*I %-5s %4u %5u %s\n", kaddr, 991*1676Sjpk ADDR_V4_WIDTH+3, dest, srcif, ADDR_V4_WIDTH, 992*1676Sjpk ire->ire_in_src_addr, ADDR_V4_WIDTH, gate, flags, 993*1676Sjpk ire->ire_refcnt, 994*1676Sjpk ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf); 995*1676Sjpk } 996*1676Sjpk 997*1676Sjpk return (WALK_NEXT); 998*1676Sjpk } 999*1676Sjpk 1000*1676Sjpk int 1001*1676Sjpk ip_mask_to_plen_v6(const in6_addr_t *v6mask) 1002*1676Sjpk { 1003*1676Sjpk int plen; 1004*1676Sjpk int i; 1005*1676Sjpk uint32_t val; 1006*1676Sjpk 1007*1676Sjpk for (i = 3; i >= 0; i--) 1008*1676Sjpk if (v6mask->s6_addr32[i] != 0) 1009*1676Sjpk break; 1010*1676Sjpk if (i < 0) 1011*1676Sjpk return (0); 1012*1676Sjpk plen = 32 + 32 * i; 1013*1676Sjpk val = v6mask->s6_addr32[i]; 1014*1676Sjpk while (!(val & 1)) { 1015*1676Sjpk val >>= 1; 1016*1676Sjpk plen--; 1017*1676Sjpk } 1018*1676Sjpk 1019*1676Sjpk return (plen); 1020*1676Sjpk } 1021*1676Sjpk 1022*1676Sjpk static int 1023*1676Sjpk netstat_irev6_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 1024*1676Sjpk { 1025*1676Sjpk const ire_t *ire = walk_data; 1026*1676Sjpk uint_t *opts = cb_data; 1027*1676Sjpk const in6_addr_t *gatep; 1028*1676Sjpk char deststr[ADDR_V6_WIDTH + 5]; 1029*1676Sjpk char flags[10], intf[LIFNAMSIZ + 1]; 1030*1676Sjpk int masklen; 1031*1676Sjpk 1032*1676Sjpk if (ire->ire_ipversion != IPV6_VERSION) 1033*1676Sjpk return (WALK_NEXT); 1034*1676Sjpk 1035*1676Sjpk if (!(*opts & NETSTAT_ALL) && ire->ire_type == IRE_CACHE) 1036*1676Sjpk return (WALK_NEXT); 1037*1676Sjpk 1038*1676Sjpk if (*opts & NETSTAT_FIRST) { 1039*1676Sjpk *opts &= ~NETSTAT_FIRST; 1040*1676Sjpk mdb_printf("\n%<u>%s Table: IPv6%</u>\n", 1041*1676Sjpk (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing"); 1042*1676Sjpk if (*opts & NETSTAT_VERBOSE) { 1043*1676Sjpk mdb_printf("%<u>%-?s %-*s %-*s If PMTU Rtt Ref " 1044*1676Sjpk "Flags Out In/Fwd%</u>\n", 1045*1676Sjpk "Address", ADDR_V6_WIDTH+4, "Destination/Mask", 1046*1676Sjpk ADDR_V6_WIDTH, "Gateway"); 1047*1676Sjpk } else { 1048*1676Sjpk mdb_printf("%<u>%-?s %-*s %-*s Flags Ref Use If" 1049*1676Sjpk "%</u>\n", 1050*1676Sjpk "Address", ADDR_V6_WIDTH+4, "Destination/Mask", 1051*1676Sjpk ADDR_V6_WIDTH, "Gateway"); 1052*1676Sjpk } 1053*1676Sjpk } 1054*1676Sjpk 1055*1676Sjpk gatep = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK)) ? 1056*1676Sjpk &ire->ire_src_addr_v6 : &ire->ire_gateway_addr_v6; 1057*1676Sjpk 1058*1676Sjpk masklen = ip_mask_to_plen_v6(&ire->ire_mask_v6); 1059*1676Sjpk (void) mdb_snprintf(deststr, sizeof (deststr), "%N/%d", 1060*1676Sjpk &ire->ire_addr_v6, masklen); 1061*1676Sjpk 1062*1676Sjpk (void) strcpy(flags, "U"); 1063*1676Sjpk if (ire->ire_type == IRE_DEFAULT || ire->ire_type == IRE_PREFIX || 1064*1676Sjpk ire->ire_type == IRE_HOST || ire->ire_type == IRE_HOST_REDIRECT) 1065*1676Sjpk (void) strcat(flags, "G"); 1066*1676Sjpk if (masklen == IPV6_ABITS) 1067*1676Sjpk (void) strcat(flags, "H"); 1068*1676Sjpk if (ire->ire_type == IRE_HOST_REDIRECT) 1069*1676Sjpk (void) strcat(flags, "D"); 1070*1676Sjpk if (ire->ire_type == IRE_CACHE) 1071*1676Sjpk (void) strcat(flags, "A"); 1072*1676Sjpk if (ire->ire_type == IRE_LOCAL) 1073*1676Sjpk (void) strcat(flags, "L"); 1074*1676Sjpk if (ire->ire_flags & RTF_MULTIRT) 1075*1676Sjpk (void) strcat(flags, "M"); 1076*1676Sjpk if (ire->ire_flags & RTF_SETSRC) 1077*1676Sjpk (void) strcat(flags, "S"); 1078*1676Sjpk 1079*1676Sjpk get_ifname(ire, intf); 1080*1676Sjpk 1081*1676Sjpk if (*opts & NETSTAT_VERBOSE) { 1082*1676Sjpk mdb_printf("%?p %-*s %-*N %-5s %5u%c %5u %3u %-5s %6u %u\n", 1083*1676Sjpk kaddr, ADDR_V6_WIDTH+4, deststr, ADDR_V6_WIDTH, gatep, 1084*1676Sjpk intf, ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ', 1085*1676Sjpk ire->ire_uinfo.iulp_rtt, ire->ire_refcnt, 1086*1676Sjpk flags, ire->ire_ob_pkt_count, ire->ire_ib_pkt_count); 1087*1676Sjpk } else { 1088*1676Sjpk mdb_printf("%?p %-*s %-*N %-5s %3u %6u %s\n", kaddr, 1089*1676Sjpk ADDR_V6_WIDTH+4, deststr, ADDR_V6_WIDTH, gatep, flags, 1090*1676Sjpk ire->ire_refcnt, 1091*1676Sjpk ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf); 1092*1676Sjpk } 1093*1676Sjpk 1094*1676Sjpk return (WALK_NEXT); 1095*1676Sjpk } 1096*1676Sjpk 10970Sstevel@tonic-gate /*ARGSUSED*/ 10980Sstevel@tonic-gate int 10990Sstevel@tonic-gate netstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 11000Sstevel@tonic-gate { 11010Sstevel@tonic-gate uint_t opts = 0; 11020Sstevel@tonic-gate const char *optf = NULL; 11030Sstevel@tonic-gate const char *optP = NULL; 11040Sstevel@tonic-gate 11050Sstevel@tonic-gate if (mdb_getopts(argc, argv, 11060Sstevel@tonic-gate 'a', MDB_OPT_SETBITS, NETSTAT_ALL, &opts, 11070Sstevel@tonic-gate 'f', MDB_OPT_STR, &optf, 11080Sstevel@tonic-gate 'P', MDB_OPT_STR, &optP, 1109*1676Sjpk 'r', MDB_OPT_SETBITS, NETSTAT_ROUTE, &opts, 1110*1676Sjpk 'v', MDB_OPT_SETBITS, NETSTAT_VERBOSE, &opts, 11110Sstevel@tonic-gate NULL) != argc) 11120Sstevel@tonic-gate return (DCMD_USAGE); 11130Sstevel@tonic-gate 11140Sstevel@tonic-gate if (optP != NULL) { 11150Sstevel@tonic-gate if ((strcmp("tcp", optP) != 0) && (strcmp("udp", optP) != 0)) 11160Sstevel@tonic-gate return (DCMD_USAGE); 1117*1676Sjpk if (opts & NETSTAT_ROUTE) 1118*1676Sjpk return (DCMD_USAGE); 11190Sstevel@tonic-gate } 11200Sstevel@tonic-gate 1121*1676Sjpk if (optf == NULL) 1122*1676Sjpk opts |= NETSTAT_V4 | NETSTAT_V6 | NETSTAT_UNIX; 1123*1676Sjpk else if (strcmp("inet", optf) == 0) 1124*1676Sjpk opts |= NETSTAT_V4; 1125*1676Sjpk else if (strcmp("inet6", optf) == 0) 1126*1676Sjpk opts |= NETSTAT_V6; 1127*1676Sjpk else if (strcmp("unix", optf) == 0) 1128*1676Sjpk opts |= NETSTAT_UNIX; 1129*1676Sjpk else 1130*1676Sjpk return (DCMD_USAGE); 1131*1676Sjpk 1132*1676Sjpk if (opts & NETSTAT_ROUTE) { 1133*1676Sjpk if (!(opts & (NETSTAT_V4|NETSTAT_V6))) 11340Sstevel@tonic-gate return (DCMD_USAGE); 1135*1676Sjpk if (opts & NETSTAT_V4) { 1136*1676Sjpk opts |= NETSTAT_FIRST; 1137*1676Sjpk if (mdb_walk("ip`ire", netstat_irev4_cb, &opts) == -1) { 1138*1676Sjpk mdb_warn("failed to walk ip`ire"); 1139*1676Sjpk return (DCMD_ERR); 1140*1676Sjpk } 1141*1676Sjpk opts |= NETSTAT_FIRST; 1142*1676Sjpk if (mdb_walk("ip`ire", netstat_irev4src_cb, 1143*1676Sjpk &opts) == -1) { 1144*1676Sjpk mdb_warn("failed to walk ip`ire"); 1145*1676Sjpk return (DCMD_ERR); 1146*1676Sjpk } 1147*1676Sjpk } 1148*1676Sjpk if (opts & NETSTAT_V6) { 1149*1676Sjpk opts |= NETSTAT_FIRST; 1150*1676Sjpk if (mdb_walk("ip`ire", netstat_irev6_cb, &opts) == -1) { 1151*1676Sjpk mdb_warn("failed to walk ip`ire"); 1152*1676Sjpk return (DCMD_ERR); 1153*1676Sjpk } 1154*1676Sjpk } 1155*1676Sjpk return (DCMD_OK); 11560Sstevel@tonic-gate } 11570Sstevel@tonic-gate 11580Sstevel@tonic-gate if ((optP == NULL) || (strcmp("tcp", optP) == 0)) { 11590Sstevel@tonic-gate if ((optf == NULL) || (strcmp("inet", optf) == 0)) { 11600Sstevel@tonic-gate /* Print TCPv4 connection */ 11610Sstevel@tonic-gate mdb_printf( 11620Sstevel@tonic-gate "%<u>%-?s St %*s %*s %s%</u>\n", 11630Sstevel@tonic-gate "TCPv4", ADDR_V4_WIDTH, "Local Address", 11640Sstevel@tonic-gate ADDR_V4_WIDTH, "Remote Address", "Zone"); 11650Sstevel@tonic-gate 11660Sstevel@tonic-gate if (opts & NETSTAT_VERBOSE) 11670Sstevel@tonic-gate netstat_tcp_verbose_header_pr(); 11680Sstevel@tonic-gate 11690Sstevel@tonic-gate if (mdb_walk("ipcl_tcpconn_cache", netstat_tcpv4_cb, 11700Sstevel@tonic-gate (void *)(uintptr_t)opts) == -1) { 11710Sstevel@tonic-gate mdb_warn("failed to walk ipcl_tcpconn_cache"); 11720Sstevel@tonic-gate return (DCMD_ERR); 11730Sstevel@tonic-gate } 11740Sstevel@tonic-gate } 11750Sstevel@tonic-gate 11760Sstevel@tonic-gate if ((optf == NULL) || (strcmp("inet6", optf) == 0)) { 11770Sstevel@tonic-gate /* Print TCPv6 connection */ 11780Sstevel@tonic-gate mdb_printf( 11790Sstevel@tonic-gate "%<u>%-?s St %*s %*s %s\n%</u>", 11800Sstevel@tonic-gate "TCPv6", ADDR_V6_WIDTH, "Local Address", 11810Sstevel@tonic-gate ADDR_V6_WIDTH, "Remote Address", "Zone"); 11820Sstevel@tonic-gate 11830Sstevel@tonic-gate if (opts & NETSTAT_VERBOSE) 11840Sstevel@tonic-gate netstat_tcp_verbose_header_pr(); 11850Sstevel@tonic-gate 11860Sstevel@tonic-gate if (mdb_walk("ipcl_tcpconn_cache", netstat_tcpv6_cb, 11870Sstevel@tonic-gate (void *)(uintptr_t)opts) == -1) { 11880Sstevel@tonic-gate mdb_warn("failed to walk ipcl_tcpconn_cache"); 11890Sstevel@tonic-gate return (DCMD_ERR); 11900Sstevel@tonic-gate } 11910Sstevel@tonic-gate } 11920Sstevel@tonic-gate } 11930Sstevel@tonic-gate 11940Sstevel@tonic-gate if ((optP == NULL) || (strcmp("udp", optP) == 0)) { 11950Sstevel@tonic-gate if ((optf == NULL) || (strcmp("inet", optf) == 0)) { 11960Sstevel@tonic-gate /* Print UDPv4 connection */ 11970Sstevel@tonic-gate mdb_printf( 11980Sstevel@tonic-gate "%<u>%-?s St %*s %*s %s\n%</u>", 11990Sstevel@tonic-gate "UDPv4", ADDR_V4_WIDTH, "Local Address", 12000Sstevel@tonic-gate ADDR_V4_WIDTH, "Remote Address", "Zone"); 12010Sstevel@tonic-gate 1202741Smasputra if (mdb_walk("udp_cache", netstat_udpv4_cb, 12030Sstevel@tonic-gate (void *)(uintptr_t)opts) == -1) { 12040Sstevel@tonic-gate mdb_warn("failed to walk genunix`udp"); 12050Sstevel@tonic-gate return (DCMD_ERR); 12060Sstevel@tonic-gate } 12070Sstevel@tonic-gate 12080Sstevel@tonic-gate } 12090Sstevel@tonic-gate 12100Sstevel@tonic-gate if ((optf == NULL) || (strcmp("inet6", optf) == 0)) { 12110Sstevel@tonic-gate /* Print UDPv6 connection */ 12120Sstevel@tonic-gate mdb_printf( 12130Sstevel@tonic-gate "%<u>%-?s St %*s %*s %s\n%</u>", 12140Sstevel@tonic-gate "UDPv6", ADDR_V6_WIDTH, "Local Address", 12150Sstevel@tonic-gate ADDR_V6_WIDTH, "Remote Address", "Zone"); 12160Sstevel@tonic-gate 1217741Smasputra if (mdb_walk("udp_cache", netstat_udpv6_cb, 12180Sstevel@tonic-gate (void *)(uintptr_t)opts) == -1) { 12190Sstevel@tonic-gate mdb_warn("failed to walk genunix`udp"); 12200Sstevel@tonic-gate return (DCMD_ERR); 12210Sstevel@tonic-gate } 12220Sstevel@tonic-gate } 12230Sstevel@tonic-gate } 12240Sstevel@tonic-gate 12250Sstevel@tonic-gate if (((optf == NULL) || (strcmp("unix", optf) == 0)) && (optP == NULL)) { 12260Sstevel@tonic-gate /* Print Unix Domain Sockets */ 12270Sstevel@tonic-gate mdb_printf("%<u>%-?s %-10s %-?s %-?s %-14s %-14s %s%</u>\n", 12280Sstevel@tonic-gate "AF_UNIX", "Type", "Vnode", "Conn", "Local Addr", 12290Sstevel@tonic-gate "Remote Addr", "Zone"); 12300Sstevel@tonic-gate 12310Sstevel@tonic-gate if (mdb_walk("genunix`sonode", netstat_unix_cb, NULL) == -1) { 12320Sstevel@tonic-gate mdb_warn("failed to walk genunix`sonode"); 12330Sstevel@tonic-gate return (DCMD_ERR); 12340Sstevel@tonic-gate } 12350Sstevel@tonic-gate } 12360Sstevel@tonic-gate 12370Sstevel@tonic-gate return (DCMD_OK); 12380Sstevel@tonic-gate } 1239