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 /*
22*9089SVasumathi.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>
520Sstevel@tonic-gate 
530Sstevel@tonic-gate #define	ADDR_V6_WIDTH	23
540Sstevel@tonic-gate #define	ADDR_V4_WIDTH	15
550Sstevel@tonic-gate 
561676Sjpk #define	NETSTAT_ALL	0x01
571676Sjpk #define	NETSTAT_VERBOSE	0x02
581676Sjpk #define	NETSTAT_ROUTE	0x04
591676Sjpk #define	NETSTAT_V4	0x08
601676Sjpk #define	NETSTAT_V6	0x10
611676Sjpk #define	NETSTAT_UNIX	0x20
621676Sjpk 
631676Sjpk #define	NETSTAT_FIRST	0x80000000u
640Sstevel@tonic-gate 
65*9089SVasumathi.Sundaram@Sun.COM typedef struct netstat_cb_data_s {
66*9089SVasumathi.Sundaram@Sun.COM 	uint_t	opts;
67*9089SVasumathi.Sundaram@Sun.COM 	conn_t	conn;
68*9089SVasumathi.Sundaram@Sun.COM 	int	af;
69*9089SVasumathi.Sundaram@Sun.COM } netstat_cb_data_t;
703448Sdh155122 
713448Sdh155122 /* Walkers for various *_stack_t */
723448Sdh155122 int
733448Sdh155122 ar_stacks_walk_init(mdb_walk_state_t *wsp)
743448Sdh155122 {
753448Sdh155122 	if (mdb_layered_walk("netstack", wsp) == -1) {
763448Sdh155122 		mdb_warn("can't walk 'netstack'");
773448Sdh155122 		return (WALK_ERR);
783448Sdh155122 	}
793448Sdh155122 	return (WALK_NEXT);
803448Sdh155122 }
813448Sdh155122 
823448Sdh155122 int
833448Sdh155122 ar_stacks_walk_step(mdb_walk_state_t *wsp)
843448Sdh155122 {
853448Sdh155122 	uintptr_t kaddr;
863448Sdh155122 	netstack_t nss;
873448Sdh155122 
883448Sdh155122 	if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
893448Sdh155122 		mdb_warn("can't read netstack at %p", wsp->walk_addr);
903448Sdh155122 		return (WALK_ERR);
913448Sdh155122 	}
923448Sdh155122 	kaddr = (uintptr_t)nss.netstack_modules[NS_ARP];
933448Sdh155122 	return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
943448Sdh155122 }
953448Sdh155122 
963448Sdh155122 int
973448Sdh155122 icmp_stacks_walk_init(mdb_walk_state_t *wsp)
983448Sdh155122 {
993448Sdh155122 	if (mdb_layered_walk("netstack", wsp) == -1) {
1003448Sdh155122 		mdb_warn("can't walk 'netstack'");
1013448Sdh155122 		return (WALK_ERR);
1023448Sdh155122 	}
1033448Sdh155122 	return (WALK_NEXT);
1043448Sdh155122 }
1053448Sdh155122 
1063448Sdh155122 int
1073448Sdh155122 icmp_stacks_walk_step(mdb_walk_state_t *wsp)
1083448Sdh155122 {
1093448Sdh155122 	uintptr_t kaddr;
1103448Sdh155122 	netstack_t nss;
1113448Sdh155122 
1123448Sdh155122 	if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
1133448Sdh155122 		mdb_warn("can't read netstack at %p", wsp->walk_addr);
1143448Sdh155122 		return (WALK_ERR);
1153448Sdh155122 	}
1163448Sdh155122 	kaddr = (uintptr_t)nss.netstack_modules[NS_ICMP];
1173448Sdh155122 	return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
1183448Sdh155122 }
1193448Sdh155122 
1203448Sdh155122 int
1213448Sdh155122 tcp_stacks_walk_init(mdb_walk_state_t *wsp)
1223448Sdh155122 {
1233448Sdh155122 	if (mdb_layered_walk("netstack", wsp) == -1) {
1243448Sdh155122 		mdb_warn("can't walk 'netstack'");
1253448Sdh155122 		return (WALK_ERR);
1263448Sdh155122 	}
1273448Sdh155122 	return (WALK_NEXT);
1283448Sdh155122 }
1293448Sdh155122 
1303448Sdh155122 int
1313448Sdh155122 tcp_stacks_walk_step(mdb_walk_state_t *wsp)
1323448Sdh155122 {
1333448Sdh155122 	uintptr_t kaddr;
1343448Sdh155122 	netstack_t nss;
1353448Sdh155122 
1363448Sdh155122 	if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
1373448Sdh155122 		mdb_warn("can't read netstack at %p", wsp->walk_addr);
1383448Sdh155122 		return (WALK_ERR);
1393448Sdh155122 	}
1403448Sdh155122 	kaddr = (uintptr_t)nss.netstack_modules[NS_TCP];
1413448Sdh155122 	return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
1423448Sdh155122 }
1433448Sdh155122 
1443448Sdh155122 int
1453448Sdh155122 udp_stacks_walk_init(mdb_walk_state_t *wsp)
1463448Sdh155122 {
1473448Sdh155122 	if (mdb_layered_walk("netstack", wsp) == -1) {
1483448Sdh155122 		mdb_warn("can't walk 'netstack'");
1493448Sdh155122 		return (WALK_ERR);
1503448Sdh155122 	}
1513448Sdh155122 	return (WALK_NEXT);
1523448Sdh155122 }
1533448Sdh155122 
1543448Sdh155122 int
1553448Sdh155122 udp_stacks_walk_step(mdb_walk_state_t *wsp)
1563448Sdh155122 {
1573448Sdh155122 	uintptr_t kaddr;
1583448Sdh155122 	netstack_t nss;
1593448Sdh155122 
1603448Sdh155122 	if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
1613448Sdh155122 		mdb_warn("can't read netstack at %p", wsp->walk_addr);
1623448Sdh155122 		return (WALK_ERR);
1633448Sdh155122 	}
1643448Sdh155122 	kaddr = (uintptr_t)nss.netstack_modules[NS_UDP];
1653448Sdh155122 	return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
1663448Sdh155122 }
1673448Sdh155122 
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate  * Print an IPv4 address and port number in a compact and easy to read format
1700Sstevel@tonic-gate  * The arguments are in network byte order
1710Sstevel@tonic-gate  */
1720Sstevel@tonic-gate static void
1730Sstevel@tonic-gate net_ipv4addrport_pr(const in6_addr_t *nipv6addr, in_port_t nport)
1740Sstevel@tonic-gate {
1750Sstevel@tonic-gate 	uint32_t naddr = V4_PART_OF_V6((*nipv6addr));
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	mdb_nhconvert(&nport, &nport, sizeof (nport));
1780Sstevel@tonic-gate 	mdb_printf("%*I.%-5hu", ADDR_V4_WIDTH, naddr, nport);
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate /*
1820Sstevel@tonic-gate  * Print an IPv6 address and port number in a compact and easy to read format
1830Sstevel@tonic-gate  * The arguments are in network byte order
1840Sstevel@tonic-gate  */
1850Sstevel@tonic-gate static void
1860Sstevel@tonic-gate net_ipv6addrport_pr(const in6_addr_t *naddr, in_port_t nport)
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate 	mdb_nhconvert(&nport, &nport, sizeof (nport));
1890Sstevel@tonic-gate 	mdb_printf("%*N.%-5hu", ADDR_V6_WIDTH, naddr, nport);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate static int
1930Sstevel@tonic-gate net_tcp_active(const tcp_t *tcp)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate 	return (tcp->tcp_state >= TCPS_ESTABLISHED);
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate static int
1990Sstevel@tonic-gate net_tcp_ipv4(const tcp_t *tcp)
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate 	return ((tcp->tcp_ipversion == IPV4_VERSION) ||
2020Sstevel@tonic-gate 	    (IN6_IS_ADDR_UNSPECIFIED(&tcp->tcp_ip_src_v6) &&
2030Sstevel@tonic-gate 	    (tcp->tcp_state <= TCPS_LISTEN)));
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate static int
2070Sstevel@tonic-gate net_tcp_ipv6(const tcp_t *tcp)
2080Sstevel@tonic-gate {
2090Sstevel@tonic-gate 	return (tcp->tcp_ipversion == IPV6_VERSION);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate static int
2130Sstevel@tonic-gate net_udp_active(const udp_t *udp)
2140Sstevel@tonic-gate {
215741Smasputra 	return ((udp->udp_state == TS_IDLE) ||
216741Smasputra 	    (udp->udp_state == TS_DATA_XFER));
2170Sstevel@tonic-gate }
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate static int
2200Sstevel@tonic-gate net_udp_ipv4(const udp_t *udp)
2210Sstevel@tonic-gate {
2220Sstevel@tonic-gate 	return ((udp->udp_ipversion == IPV4_VERSION) ||
2230Sstevel@tonic-gate 	    (IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src) &&
2240Sstevel@tonic-gate 	    (udp->udp_state <= TS_IDLE)));
2250Sstevel@tonic-gate }
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate static int
2280Sstevel@tonic-gate net_udp_ipv6(const udp_t *udp)
2290Sstevel@tonic-gate {
2300Sstevel@tonic-gate 	return (udp->udp_ipversion == IPV6_VERSION);
2310Sstevel@tonic-gate }
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate int
2340Sstevel@tonic-gate sonode_walk_init(mdb_walk_state_t *wsp)
2350Sstevel@tonic-gate {
2360Sstevel@tonic-gate 	if (wsp->walk_addr == NULL) {
2370Sstevel@tonic-gate 		GElf_Sym sym;
2380Sstevel@tonic-gate 		struct socklist *slp;
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 		if (mdb_lookup_by_obj("sockfs", "socklist", &sym) == -1) {
2410Sstevel@tonic-gate 			mdb_warn("failed to lookup sockfs`socklist");
2420Sstevel@tonic-gate 			return (WALK_ERR);
2430Sstevel@tonic-gate 		}
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 		slp = (struct socklist *)(uintptr_t)sym.st_value;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 		if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr),
2480Sstevel@tonic-gate 		    (uintptr_t)&slp->sl_list) == -1) {
2490Sstevel@tonic-gate 			mdb_warn("failed to read address of initial sonode "
2500Sstevel@tonic-gate 			    "at %p", &slp->sl_list);
2510Sstevel@tonic-gate 			return (WALK_ERR);
2520Sstevel@tonic-gate 		}
2530Sstevel@tonic-gate 	}
2540Sstevel@tonic-gate 
2558348SEric.Yu@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (struct sotpi_sonode), UM_SLEEP);
2560Sstevel@tonic-gate 	return (WALK_NEXT);
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate int
2600Sstevel@tonic-gate sonode_walk_step(mdb_walk_state_t *wsp)
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate 	int status;
2638348SEric.Yu@Sun.COM 	struct sotpi_sonode *stp;
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	if (wsp->walk_addr == NULL)
2660Sstevel@tonic-gate 		return (WALK_DONE);
2670Sstevel@tonic-gate 
2688348SEric.Yu@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (struct sotpi_sonode),
2690Sstevel@tonic-gate 	    wsp->walk_addr) == -1) {
2700Sstevel@tonic-gate 		mdb_warn("failed to read sonode at %p", wsp->walk_addr);
2710Sstevel@tonic-gate 		return (WALK_ERR);
2720Sstevel@tonic-gate 	}
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
2750Sstevel@tonic-gate 	    wsp->walk_cbdata);
2760Sstevel@tonic-gate 
2778348SEric.Yu@Sun.COM 	stp = wsp->walk_data;
2780Sstevel@tonic-gate 
2798348SEric.Yu@Sun.COM 	wsp->walk_addr = (uintptr_t)stp->st_info.sti_next_so;
2800Sstevel@tonic-gate 	return (status);
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate void
2840Sstevel@tonic-gate sonode_walk_fini(mdb_walk_state_t *wsp)
2850Sstevel@tonic-gate {
2868348SEric.Yu@Sun.COM 	mdb_free(wsp->walk_data, sizeof (struct sotpi_sonode));
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate struct mi_walk_data {
2900Sstevel@tonic-gate 	uintptr_t mi_wd_miofirst;
2910Sstevel@tonic-gate 	MI_O mi_wd_miodata;
2920Sstevel@tonic-gate };
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate int
2950Sstevel@tonic-gate mi_walk_init(mdb_walk_state_t *wsp)
2960Sstevel@tonic-gate {
2970Sstevel@tonic-gate 	struct mi_walk_data *wdp;
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	if (wsp->walk_addr == NULL) {
3000Sstevel@tonic-gate 		mdb_warn("mi doesn't support global walks\n");
3010Sstevel@tonic-gate 		return (WALK_ERR);
3020Sstevel@tonic-gate 	}
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	wdp = mdb_alloc(sizeof (struct mi_walk_data), UM_SLEEP);
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	/* So that we do not immediately return WALK_DONE below */
3070Sstevel@tonic-gate 	wdp->mi_wd_miofirst = NULL;
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	wsp->walk_data = wdp;
3100Sstevel@tonic-gate 	return (WALK_NEXT);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate int
3140Sstevel@tonic-gate mi_walk_step(mdb_walk_state_t *wsp)
3150Sstevel@tonic-gate {
3160Sstevel@tonic-gate 	struct mi_walk_data *wdp = wsp->walk_data;
3170Sstevel@tonic-gate 	MI_OP miop = &wdp->mi_wd_miodata;
3180Sstevel@tonic-gate 	int status;
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	/* Always false in the first iteration */
3210Sstevel@tonic-gate 	if ((wsp->walk_addr == (uintptr_t)NULL) ||
3220Sstevel@tonic-gate 	    (wsp->walk_addr == wdp->mi_wd_miofirst)) {
3230Sstevel@tonic-gate 		return (WALK_DONE);
3240Sstevel@tonic-gate 	}
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	if (mdb_vread(miop, sizeof (MI_O), wsp->walk_addr) == -1) {
3270Sstevel@tonic-gate 		mdb_warn("failed to read MI object at %p", wsp->walk_addr);
3280Sstevel@tonic-gate 		return (WALK_ERR);
3290Sstevel@tonic-gate 	}
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 	/* Only true in the first iteration */
3323448Sdh155122 	if (wdp->mi_wd_miofirst == NULL) {
3330Sstevel@tonic-gate 		wdp->mi_wd_miofirst = wsp->walk_addr;
3343448Sdh155122 		status = WALK_NEXT;
3353448Sdh155122 	} else {
3363448Sdh155122 		status = wsp->walk_callback(wsp->walk_addr + sizeof (MI_O),
3373448Sdh155122 		    &miop[1], wsp->walk_cbdata);
3383448Sdh155122 	}
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)miop->mi_o_next;
3410Sstevel@tonic-gate 	return (status);
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate void
3450Sstevel@tonic-gate mi_walk_fini(mdb_walk_state_t *wsp)
3460Sstevel@tonic-gate {
3470Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (struct mi_walk_data));
3480Sstevel@tonic-gate }
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate typedef struct mi_payload_walk_arg_s {
3513448Sdh155122 	const char *mi_pwa_walker;	/* Underlying walker */
3523448Sdh155122 	const off_t mi_pwa_head_off;	/* Offset for mi_o_head_t * in stack */
3530Sstevel@tonic-gate 	const size_t mi_pwa_size;	/* size of mi payload */
3540Sstevel@tonic-gate 	const uint_t mi_pwa_flags;	/* device and/or module */
3550Sstevel@tonic-gate } mi_payload_walk_arg_t;
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate #define	MI_PAYLOAD_DEVICE	0x1
3580Sstevel@tonic-gate #define	MI_PAYLOAD_MODULE	0x2
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate int
3610Sstevel@tonic-gate mi_payload_walk_init(mdb_walk_state_t *wsp)
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate 	const mi_payload_walk_arg_t *arg = wsp->walk_arg;
3640Sstevel@tonic-gate 
3653448Sdh155122 	if (mdb_layered_walk(arg->mi_pwa_walker, wsp) == -1) {
3663448Sdh155122 		mdb_warn("can't walk '%s'", arg->mi_pwa_walker);
3670Sstevel@tonic-gate 		return (WALK_ERR);
3680Sstevel@tonic-gate 	}
3690Sstevel@tonic-gate 	return (WALK_NEXT);
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate int
3730Sstevel@tonic-gate mi_payload_walk_step(mdb_walk_state_t *wsp)
3740Sstevel@tonic-gate {
3750Sstevel@tonic-gate 	const mi_payload_walk_arg_t *arg = wsp->walk_arg;
3763448Sdh155122 	uintptr_t kaddr;
3770Sstevel@tonic-gate 
3783448Sdh155122 	kaddr = wsp->walk_addr + arg->mi_pwa_head_off;
3790Sstevel@tonic-gate 
3803448Sdh155122 	if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) {
3813448Sdh155122 		mdb_warn("can't read address of mi head at %p for %s",
3823448Sdh155122 		    kaddr, arg->mi_pwa_walker);
3830Sstevel@tonic-gate 		return (WALK_ERR);
3840Sstevel@tonic-gate 	}
3850Sstevel@tonic-gate 
3863448Sdh155122 	if (kaddr == 0) {
3873448Sdh155122 		/* Empty list */
3883448Sdh155122 		return (WALK_DONE);
3893448Sdh155122 	}
3900Sstevel@tonic-gate 
3913448Sdh155122 	if (mdb_pwalk("genunix`mi", wsp->walk_callback,
3923448Sdh155122 	    wsp->walk_cbdata, kaddr) == -1) {
3933448Sdh155122 		mdb_warn("failed to walk genunix`mi");
3943448Sdh155122 		return (WALK_ERR);
3953448Sdh155122 	}
3963448Sdh155122 	return (WALK_NEXT);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate const mi_payload_walk_arg_t mi_ar_arg = {
4003448Sdh155122 	"ar_stacks", OFFSETOF(arp_stack_t, as_head), sizeof (ar_t),
4010Sstevel@tonic-gate 	MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE
4020Sstevel@tonic-gate };
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate const mi_payload_walk_arg_t mi_icmp_arg = {
4053448Sdh155122 	"icmp_stacks", OFFSETOF(icmp_stack_t, is_head), sizeof (icmp_t),
4060Sstevel@tonic-gate 	MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE
4070Sstevel@tonic-gate };
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate int
4100Sstevel@tonic-gate sonode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4110Sstevel@tonic-gate {
4120Sstevel@tonic-gate 	const char *optf = NULL;
4130Sstevel@tonic-gate 	const char *optt = NULL;
4140Sstevel@tonic-gate 	const char *optp = NULL;
4150Sstevel@tonic-gate 	int family, type, proto;
4160Sstevel@tonic-gate 	int filter = 0;
4170Sstevel@tonic-gate 	struct sonode so;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
4200Sstevel@tonic-gate 		if (mdb_walk_dcmd("genunix`sonode", "genunix`sonode", argc,
4210Sstevel@tonic-gate 		    argv) == -1) {
4220Sstevel@tonic-gate 			mdb_warn("failed to walk sonode");
4230Sstevel@tonic-gate 			return (DCMD_ERR);
4240Sstevel@tonic-gate 		}
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 		return (DCMD_OK);
4270Sstevel@tonic-gate 	}
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
4300Sstevel@tonic-gate 	    'f', MDB_OPT_STR, &optf,
4310Sstevel@tonic-gate 	    't', MDB_OPT_STR, &optt,
4320Sstevel@tonic-gate 	    'p', MDB_OPT_STR, &optp,
4330Sstevel@tonic-gate 	    NULL) != argc)
4340Sstevel@tonic-gate 		return (DCMD_USAGE);
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	if (optf != NULL) {
4370Sstevel@tonic-gate 		if (strcmp("inet", optf) == 0)
4380Sstevel@tonic-gate 			family = AF_INET;
4390Sstevel@tonic-gate 		else if (strcmp("inet6", optf) == 0)
4400Sstevel@tonic-gate 			family = AF_INET6;
4410Sstevel@tonic-gate 		else if (strcmp("unix", optf) == 0)
4420Sstevel@tonic-gate 			family = AF_UNIX;
4430Sstevel@tonic-gate 		else
4440Sstevel@tonic-gate 			family = mdb_strtoull(optf);
4450Sstevel@tonic-gate 		filter = 1;
4460Sstevel@tonic-gate 	}
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	if (optt != NULL) {
4490Sstevel@tonic-gate 		if (strcmp("stream", optt) == 0)
4500Sstevel@tonic-gate 			type = SOCK_STREAM;
4510Sstevel@tonic-gate 		else if (strcmp("dgram", optt) == 0)
4520Sstevel@tonic-gate 			type = SOCK_DGRAM;
4530Sstevel@tonic-gate 		else if (strcmp("raw", optt) == 0)
4540Sstevel@tonic-gate 			type = SOCK_RAW;
4550Sstevel@tonic-gate 		else
4560Sstevel@tonic-gate 			type = mdb_strtoull(optt);
4570Sstevel@tonic-gate 		filter = 1;
4580Sstevel@tonic-gate 	}
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	if (optp != NULL) {
4610Sstevel@tonic-gate 		proto = mdb_strtoull(optp);
4620Sstevel@tonic-gate 		filter = 1;
4630Sstevel@tonic-gate 	}
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) && !filter) {
4660Sstevel@tonic-gate 		mdb_printf("%<u>%-?s Family Type Proto State Mode Flag "
4670Sstevel@tonic-gate 		    "AccessVP%</u>\n", "Sonode:");
4680Sstevel@tonic-gate 	}
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 	if (mdb_vread(&so, sizeof (so), addr) == -1) {
4710Sstevel@tonic-gate 		mdb_warn("failed to read sonode at %p", addr);
4720Sstevel@tonic-gate 		return (DCMD_ERR);
4730Sstevel@tonic-gate 	}
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	if ((optf != NULL) && (so.so_family != family))
4760Sstevel@tonic-gate 		return (DCMD_OK);
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	if ((optt != NULL) && (so.so_type != type))
4790Sstevel@tonic-gate 		return (DCMD_OK);
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	if ((optp != NULL) && (so.so_protocol != proto))
4820Sstevel@tonic-gate 		return (DCMD_OK);
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 	if (filter) {
4850Sstevel@tonic-gate 		mdb_printf("%0?p\n", addr);
4860Sstevel@tonic-gate 		return (DCMD_OK);
4870Sstevel@tonic-gate 	}
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 	mdb_printf("%0?p ", addr);
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	switch (so.so_family) {
4925563Snordmark 	case AF_UNIX:
4930Sstevel@tonic-gate 		mdb_printf("unix  ");
4940Sstevel@tonic-gate 		break;
4955563Snordmark 	case AF_INET:
4960Sstevel@tonic-gate 		mdb_printf("inet  ");
4970Sstevel@tonic-gate 		break;
4985563Snordmark 	case AF_INET6:
4990Sstevel@tonic-gate 		mdb_printf("inet6 ");
5000Sstevel@tonic-gate 		break;
5015563Snordmark 	default:
5020Sstevel@tonic-gate 		mdb_printf("%6hi", so.so_family);
5030Sstevel@tonic-gate 	}
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 	switch (so.so_type) {
5065563Snordmark 	case SOCK_STREAM:
5070Sstevel@tonic-gate 		mdb_printf(" strm");
5080Sstevel@tonic-gate 		break;
5095563Snordmark 	case SOCK_DGRAM:
5100Sstevel@tonic-gate 		mdb_printf(" dgrm");
5110Sstevel@tonic-gate 		break;
5125563Snordmark 	case SOCK_RAW:
5130Sstevel@tonic-gate 		mdb_printf(" raw ");
5140Sstevel@tonic-gate 		break;
5155563Snordmark 	default:
5160Sstevel@tonic-gate 		mdb_printf(" %4hi", so.so_type);
5170Sstevel@tonic-gate 	}
5180Sstevel@tonic-gate 
5198348SEric.Yu@Sun.COM 	mdb_printf(" %5hi %05x %04x %04hx\n",
5200Sstevel@tonic-gate 	    so.so_protocol, so.so_state, so.so_mode,
5218348SEric.Yu@Sun.COM 	    so.so_flag);
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 	return (DCMD_OK);
5240Sstevel@tonic-gate }
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate #define	MI_PAYLOAD	0x1
5270Sstevel@tonic-gate #define	MI_DEVICE	0x2
5280Sstevel@tonic-gate #define	MI_MODULE	0x4
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate int
5310Sstevel@tonic-gate mi(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5320Sstevel@tonic-gate {
5330Sstevel@tonic-gate 	uint_t opts = 0;
5340Sstevel@tonic-gate 	MI_O	mio;
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
5370Sstevel@tonic-gate 		return (DCMD_USAGE);
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
5400Sstevel@tonic-gate 	    'p', MDB_OPT_SETBITS, MI_PAYLOAD, &opts,
5410Sstevel@tonic-gate 	    'd', MDB_OPT_SETBITS, MI_DEVICE, &opts,
5420Sstevel@tonic-gate 	    'm', MDB_OPT_SETBITS, MI_MODULE, &opts,
5430Sstevel@tonic-gate 	    NULL) != argc)
5440Sstevel@tonic-gate 		return (DCMD_USAGE);
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 	if ((opts & (MI_DEVICE | MI_MODULE)) == (MI_DEVICE | MI_MODULE)) {
5470Sstevel@tonic-gate 		mdb_warn("at most one filter, d for devices or m "
5480Sstevel@tonic-gate 		    "for modules, may be specified\n");
5490Sstevel@tonic-gate 		return (DCMD_USAGE);
5500Sstevel@tonic-gate 	}
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 	if ((opts == 0) && (DCMD_HDRSPEC(flags))) {
5530Sstevel@tonic-gate 		mdb_printf("%<u>%-?s %-?s %-?s IsDev Dev%</u>\n",
5540Sstevel@tonic-gate 		    "MI_O", "Next", "Prev");
5550Sstevel@tonic-gate 	}
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate 	if (mdb_vread(&mio, sizeof (mio), addr) == -1) {
5580Sstevel@tonic-gate 		mdb_warn("failed to read mi object MI_O at %p", addr);
5590Sstevel@tonic-gate 		return (DCMD_ERR);
5600Sstevel@tonic-gate 	}
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 	if (opts != 0) {
5630Sstevel@tonic-gate 		if (mio.mi_o_isdev == B_FALSE) {
5640Sstevel@tonic-gate 			/* mio is a module */
5650Sstevel@tonic-gate 			if (!(opts & MI_MODULE) && (opts & MI_DEVICE))
5660Sstevel@tonic-gate 				return (DCMD_OK);
5670Sstevel@tonic-gate 		} else {
5680Sstevel@tonic-gate 			/* mio is a device */
5690Sstevel@tonic-gate 			if (!(opts & MI_DEVICE) && (opts & MI_MODULE))
5700Sstevel@tonic-gate 				return (DCMD_OK);
5710Sstevel@tonic-gate 		}
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 		if (opts & MI_PAYLOAD)
5740Sstevel@tonic-gate 			mdb_printf("%p\n", addr + sizeof (MI_O));
5750Sstevel@tonic-gate 		else
5760Sstevel@tonic-gate 			mdb_printf("%p\n", addr);
5770Sstevel@tonic-gate 		return (DCMD_OK);
5780Sstevel@tonic-gate 	}
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 	mdb_printf("%0?p %0?p %0?p ", addr, mio.mi_o_next, mio.mi_o_prev);
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	if (mio.mi_o_isdev == B_FALSE)
5830Sstevel@tonic-gate 		mdb_printf("FALSE");
5840Sstevel@tonic-gate 	else
5850Sstevel@tonic-gate 		mdb_printf("TRUE ");
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	mdb_printf(" %0?p\n", mio.mi_o_dev);
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate 	return (DCMD_OK);
5900Sstevel@tonic-gate }
5910Sstevel@tonic-gate 
5923448Sdh155122 static int
5933448Sdh155122 ns_to_stackid(uintptr_t kaddr)
5943448Sdh155122 {
5953448Sdh155122 	netstack_t nss;
5963448Sdh155122 
5973448Sdh155122 	if (mdb_vread(&nss, sizeof (nss), kaddr) == -1) {
5983448Sdh155122 		mdb_warn("failed to read netstack_t %p", kaddr);
5993448Sdh155122 		return (0);
6003448Sdh155122 	}
6013448Sdh155122 	return (nss.netstack_stackid);
6023448Sdh155122 }
6033448Sdh155122 
6043448Sdh155122 
6053448Sdh155122 
6060Sstevel@tonic-gate static void
6070Sstevel@tonic-gate netstat_tcp_verbose_pr(const tcp_t *tcp)
6080Sstevel@tonic-gate {
6090Sstevel@tonic-gate 	mdb_printf("       %5i %08x %08x %5i %08x %08x %5li %5i\n",
6100Sstevel@tonic-gate 	    tcp->tcp_swnd, tcp->tcp_snxt, tcp->tcp_suna, tcp->tcp_rwnd,
6110Sstevel@tonic-gate 	    tcp->tcp_rack, tcp->tcp_rnxt, tcp->tcp_rto, tcp->tcp_mss);
6120Sstevel@tonic-gate }
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate /*ARGSUSED*/
6150Sstevel@tonic-gate static int
616*9089SVasumathi.Sundaram@Sun.COM netstat_tcp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data)
6170Sstevel@tonic-gate {
618*9089SVasumathi.Sundaram@Sun.COM 	netstat_cb_data_t *ncb = cb_data;
619*9089SVasumathi.Sundaram@Sun.COM 	uint_t opts = ncb->opts;
620*9089SVasumathi.Sundaram@Sun.COM 	int af = ncb->af;
6210Sstevel@tonic-gate 	uintptr_t tcp_kaddr;
622*9089SVasumathi.Sundaram@Sun.COM 	conn_t *connp = &ncb->conn;
6235563Snordmark 	tcp_t tcps, *tcp;
6240Sstevel@tonic-gate 
625*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(connp, sizeof (conn_t), kaddr) == -1) {
6265563Snordmark 		mdb_warn("failed to read conn_t at %p", kaddr);
6275563Snordmark 		return (WALK_ERR);
6280Sstevel@tonic-gate 	}
6290Sstevel@tonic-gate 
6305563Snordmark 	tcp_kaddr = (uintptr_t)connp->conn_tcp;
6315563Snordmark 	if (mdb_vread(&tcps, sizeof (tcp_t), tcp_kaddr) == -1) {
6325563Snordmark 		mdb_warn("failed to read tcp_t at %p", kaddr);
6330Sstevel@tonic-gate 		return (WALK_ERR);
6340Sstevel@tonic-gate 	}
6350Sstevel@tonic-gate 
6365563Snordmark 	tcp = &tcps;
6370Sstevel@tonic-gate 	connp->conn_tcp = tcp;
6380Sstevel@tonic-gate 	tcp->tcp_connp = connp;
6390Sstevel@tonic-gate 
640741Smasputra 	if (!((opts & NETSTAT_ALL) || net_tcp_active(tcp)) ||
6410Sstevel@tonic-gate 	    (af == AF_INET && !net_tcp_ipv4(tcp)) ||
6420Sstevel@tonic-gate 	    (af == AF_INET6 && !net_tcp_ipv6(tcp))) {
6430Sstevel@tonic-gate 		return (WALK_NEXT);
6440Sstevel@tonic-gate 	}
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 	mdb_printf("%0?p %2i ", tcp_kaddr, tcp->tcp_state);
6470Sstevel@tonic-gate 	if (af == AF_INET) {
6480Sstevel@tonic-gate 		net_ipv4addrport_pr(&tcp->tcp_ip_src_v6, tcp->tcp_lport);
6490Sstevel@tonic-gate 		mdb_printf(" ");
6500Sstevel@tonic-gate 		net_ipv4addrport_pr(&tcp->tcp_remote_v6, tcp->tcp_fport);
6510Sstevel@tonic-gate 	} else if (af == AF_INET6) {
6520Sstevel@tonic-gate 		net_ipv6addrport_pr(&tcp->tcp_ip_src_v6, tcp->tcp_lport);
6530Sstevel@tonic-gate 		mdb_printf(" ");
6540Sstevel@tonic-gate 		net_ipv6addrport_pr(&tcp->tcp_remote_v6, tcp->tcp_fport);
6550Sstevel@tonic-gate 	}
656*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf(" %5i", ns_to_stackid((uintptr_t)connp->conn_netstack));
6570Sstevel@tonic-gate 	mdb_printf(" %4i\n", connp->conn_zoneid);
6580Sstevel@tonic-gate 	if (opts & NETSTAT_VERBOSE)
6590Sstevel@tonic-gate 		netstat_tcp_verbose_pr(tcp);
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 	return (WALK_NEXT);
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate 
664741Smasputra /*ARGSUSED*/
6650Sstevel@tonic-gate static int
666*9089SVasumathi.Sundaram@Sun.COM netstat_udp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data)
6670Sstevel@tonic-gate {
668*9089SVasumathi.Sundaram@Sun.COM 	netstat_cb_data_t *ncb = cb_data;
669*9089SVasumathi.Sundaram@Sun.COM 	uint_t opts = ncb->opts;
670*9089SVasumathi.Sundaram@Sun.COM 	int af = ncb->af;
671741Smasputra 	udp_t udp;
672*9089SVasumathi.Sundaram@Sun.COM 	conn_t *connp = &ncb->conn;
673*9089SVasumathi.Sundaram@Sun.COM 	char *state;
674741Smasputra 
675*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(connp, sizeof (conn_t), kaddr) == -1) {
6765563Snordmark 		mdb_warn("failed to read conn_t at %p", kaddr);
677741Smasputra 		return (WALK_ERR);
678741Smasputra 	}
6790Sstevel@tonic-gate 
6805563Snordmark 	if (mdb_vread(&udp, sizeof (udp_t),
681*9089SVasumathi.Sundaram@Sun.COM 	    (uintptr_t)connp->conn_udp) == -1) {
6825563Snordmark 		mdb_warn("failed to read conn_udp at %p",
683*9089SVasumathi.Sundaram@Sun.COM 		    (uintptr_t)connp->conn_udp);
684741Smasputra 		return (WALK_ERR);
685741Smasputra 	}
6860Sstevel@tonic-gate 
687741Smasputra 	if (!((opts & NETSTAT_ALL) || net_udp_active(&udp)) ||
688741Smasputra 	    (af == AF_INET && !net_udp_ipv4(&udp)) ||
689741Smasputra 	    (af == AF_INET6 && !net_udp_ipv6(&udp))) {
690741Smasputra 		return (WALK_NEXT);
691741Smasputra 	}
692741Smasputra 
693*9089SVasumathi.Sundaram@Sun.COM 	if (udp.udp_state == TS_UNBND)
694*9089SVasumathi.Sundaram@Sun.COM 		state = "UNBOUND";
695*9089SVasumathi.Sundaram@Sun.COM 	else if (udp.udp_state == TS_IDLE)
696*9089SVasumathi.Sundaram@Sun.COM 		state = "IDLE";
697*9089SVasumathi.Sundaram@Sun.COM 	else if (udp.udp_state == TS_DATA_XFER)
698*9089SVasumathi.Sundaram@Sun.COM 		state = "CONNECTED";
699*9089SVasumathi.Sundaram@Sun.COM 	else
700*9089SVasumathi.Sundaram@Sun.COM 		state = "UNKNOWN";
701*9089SVasumathi.Sundaram@Sun.COM 
702*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%0?p %10s ", (uintptr_t)connp->conn_udp, state);
703741Smasputra 	if (af == AF_INET) {
704741Smasputra 		net_ipv4addrport_pr(&udp.udp_v6src, udp.udp_port);
705741Smasputra 		mdb_printf(" ");
706741Smasputra 		net_ipv4addrport_pr(&udp.udp_v6dst, udp.udp_dstport);
707741Smasputra 	} else if (af == AF_INET6) {
708741Smasputra 		net_ipv6addrport_pr(&udp.udp_v6src, udp.udp_port);
709741Smasputra 		mdb_printf(" ");
710741Smasputra 		net_ipv6addrport_pr(&udp.udp_v6dst, udp.udp_dstport);
711741Smasputra 	}
712*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf(" %5i", ns_to_stackid((uintptr_t)connp->conn_netstack));
713*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf(" %4i\n", connp->conn_zoneid);
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 	return (WALK_NEXT);
7160Sstevel@tonic-gate }
7170Sstevel@tonic-gate 
718*9089SVasumathi.Sundaram@Sun.COM /*ARGSUSED*/
7190Sstevel@tonic-gate static int
720*9089SVasumathi.Sundaram@Sun.COM netstat_icmp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data)
721741Smasputra {
722*9089SVasumathi.Sundaram@Sun.COM 	netstat_cb_data_t *ncb = cb_data;
723*9089SVasumathi.Sundaram@Sun.COM 	int af = ncb->af;
724*9089SVasumathi.Sundaram@Sun.COM 	icmp_t icmp;
725*9089SVasumathi.Sundaram@Sun.COM 	conn_t *connp = &ncb->conn;
726*9089SVasumathi.Sundaram@Sun.COM 	char *state;
727*9089SVasumathi.Sundaram@Sun.COM 
728*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(connp, sizeof (conn_t), kaddr) == -1) {
729*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read conn_t at %p", kaddr);
730*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
731*9089SVasumathi.Sundaram@Sun.COM 	}
732*9089SVasumathi.Sundaram@Sun.COM 
733*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&icmp, sizeof (icmp_t),
734*9089SVasumathi.Sundaram@Sun.COM 	    (uintptr_t)connp->conn_icmp) == -1) {
735*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read conn_icmp at %p",
736*9089SVasumathi.Sundaram@Sun.COM 		    (uintptr_t)connp->conn_icmp);
737*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
738*9089SVasumathi.Sundaram@Sun.COM 	}
739*9089SVasumathi.Sundaram@Sun.COM 
740*9089SVasumathi.Sundaram@Sun.COM 	if ((af == AF_INET && icmp.icmp_ipversion != IPV4_VERSION) ||
741*9089SVasumathi.Sundaram@Sun.COM 	    (af == AF_INET6 && icmp.icmp_ipversion != IPV6_VERSION)) {
742*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
743*9089SVasumathi.Sundaram@Sun.COM 	}
744741Smasputra 
745*9089SVasumathi.Sundaram@Sun.COM 	if (icmp.icmp_state == TS_UNBND)
746*9089SVasumathi.Sundaram@Sun.COM 		state = "UNBOUND";
747*9089SVasumathi.Sundaram@Sun.COM 	else if (icmp.icmp_state == TS_IDLE)
748*9089SVasumathi.Sundaram@Sun.COM 		state = "IDLE";
749*9089SVasumathi.Sundaram@Sun.COM 	else if (icmp.icmp_state == TS_DATA_XFER)
750*9089SVasumathi.Sundaram@Sun.COM 		state = "CONNECTED";
751*9089SVasumathi.Sundaram@Sun.COM 	else
752*9089SVasumathi.Sundaram@Sun.COM 		state = "UNKNOWN";
753*9089SVasumathi.Sundaram@Sun.COM 
754*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%0?p %10s ", (uintptr_t)connp->conn_icmp, state);
755*9089SVasumathi.Sundaram@Sun.COM 	if (af == AF_INET) {
756*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*I ", ADDR_V4_WIDTH,
757*9089SVasumathi.Sundaram@Sun.COM 		    V4_PART_OF_V6((icmp.icmp_v6src)));
758*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*I ", ADDR_V4_WIDTH,
759*9089SVasumathi.Sundaram@Sun.COM 		    V4_PART_OF_V6((icmp.icmp_v6dst.sin6_addr)));
760*9089SVasumathi.Sundaram@Sun.COM 	} else if (af == AF_INET6) {
761*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*N ", ADDR_V6_WIDTH, &icmp.icmp_v6src);
762*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*N ", ADDR_V6_WIDTH, &icmp.icmp_v6dst);
763*9089SVasumathi.Sundaram@Sun.COM 	}
764*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf(" %5i", ns_to_stackid((uintptr_t)connp->conn_netstack));
765*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf(" %4i\n", icmp.icmp_zoneid);
766*9089SVasumathi.Sundaram@Sun.COM 
767*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate /*
7710Sstevel@tonic-gate  * print the address of a unix domain socket
7720Sstevel@tonic-gate  *
7730Sstevel@tonic-gate  * so is the address of a AF_UNIX struct sonode in mdb's address space
7740Sstevel@tonic-gate  * soa is the address of the struct soaddr to print
7750Sstevel@tonic-gate  *
7760Sstevel@tonic-gate  * returns 0 on success, -1 otherwise
7770Sstevel@tonic-gate  */
7780Sstevel@tonic-gate static int
7798348SEric.Yu@Sun.COM netstat_unix_name_pr(const struct sotpi_sonode *st, const struct soaddr *soa)
7800Sstevel@tonic-gate {
7818348SEric.Yu@Sun.COM 	const struct sonode *so = &st->st_sonode;
7820Sstevel@tonic-gate 	const char none[] = " (none)";
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 	if ((so->so_state & SS_ISBOUND) && (soa->soa_len != 0)) {
7858348SEric.Yu@Sun.COM 		if (st->st_info.sti_faddr_noxlate) {
7860Sstevel@tonic-gate 			mdb_printf("%-14s ", " (socketpair)");
7870Sstevel@tonic-gate 		} else {
7880Sstevel@tonic-gate 			if (soa->soa_len > sizeof (sa_family_t)) {
7890Sstevel@tonic-gate 				char addr[MAXPATHLEN + 1];
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 				if (mdb_readstr(addr, sizeof (addr),
7920Sstevel@tonic-gate 				    (uintptr_t)&soa->soa_sa->sa_data) == -1) {
7930Sstevel@tonic-gate 					mdb_warn("failed to read unix address "
7940Sstevel@tonic-gate 					    "at %p", &soa->soa_sa->sa_data);
7950Sstevel@tonic-gate 					return (-1);
7960Sstevel@tonic-gate 				}
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate 				mdb_printf("%-14s ", addr);
7990Sstevel@tonic-gate 			} else {
8000Sstevel@tonic-gate 				mdb_printf("%-14s ", none);
8010Sstevel@tonic-gate 			}
8020Sstevel@tonic-gate 		}
8030Sstevel@tonic-gate 	} else {
8040Sstevel@tonic-gate 		mdb_printf("%-14s ", none);
8050Sstevel@tonic-gate 	}
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 	return (0);
8080Sstevel@tonic-gate }
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate /* based on sockfs_snapshot */
8110Sstevel@tonic-gate /*ARGSUSED*/
8120Sstevel@tonic-gate static int
8130Sstevel@tonic-gate netstat_unix_cb(uintptr_t kaddr, const void *walk_data, void *cb_data)
8140Sstevel@tonic-gate {
8158348SEric.Yu@Sun.COM 	const struct sotpi_sonode *st = walk_data;
8168348SEric.Yu@Sun.COM 	const struct sonode *so = &st->st_sonode;
8178348SEric.Yu@Sun.COM 	const struct sotpi_info *sti = &st->st_info;
8180Sstevel@tonic-gate 
8198348SEric.Yu@Sun.COM 	if (so->so_count == 0)
8200Sstevel@tonic-gate 		return (WALK_NEXT);
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate 	if (so->so_family != AF_UNIX) {
8230Sstevel@tonic-gate 		mdb_warn("sonode of family %hi at %p\n", so->so_family, kaddr);
8240Sstevel@tonic-gate 		return (WALK_ERR);
8250Sstevel@tonic-gate 	}
8260Sstevel@tonic-gate 
8270Sstevel@tonic-gate 	mdb_printf("%-?p ", kaddr);
8280Sstevel@tonic-gate 
8298348SEric.Yu@Sun.COM 	switch (sti->sti_serv_type) {
8305563Snordmark 	case T_CLTS:
8310Sstevel@tonic-gate 		mdb_printf("%-10s ", "dgram");
8320Sstevel@tonic-gate 		break;
8335563Snordmark 	case T_COTS:
8340Sstevel@tonic-gate 		mdb_printf("%-10s ", "stream");
8350Sstevel@tonic-gate 		break;
8365563Snordmark 	case T_COTS_ORD:
8370Sstevel@tonic-gate 		mdb_printf("%-10s ", "stream-ord");
8380Sstevel@tonic-gate 		break;
8395563Snordmark 	default:
8408348SEric.Yu@Sun.COM 		mdb_printf("%-10i ", sti->sti_serv_type);
8410Sstevel@tonic-gate 	}
8420Sstevel@tonic-gate 
8430Sstevel@tonic-gate 	if ((so->so_state & SS_ISBOUND) &&
8448348SEric.Yu@Sun.COM 	    (sti->sti_ux_laddr.soua_magic == SOU_MAGIC_EXPLICIT)) {
8458348SEric.Yu@Sun.COM 		mdb_printf("%0?p ", sti->sti_ux_laddr.soua_vp);
8460Sstevel@tonic-gate 	} else {
8470Sstevel@tonic-gate 		mdb_printf("%0?p ", NULL);
8480Sstevel@tonic-gate 	}
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 	if ((so->so_state & SS_ISCONNECTED) &&
8518348SEric.Yu@Sun.COM 	    (sti->sti_ux_faddr.soua_magic == SOU_MAGIC_EXPLICIT)) {
8528348SEric.Yu@Sun.COM 		mdb_printf("%0?p ", sti->sti_ux_faddr.soua_vp);
8530Sstevel@tonic-gate 	} else {
8540Sstevel@tonic-gate 		mdb_printf("%0?p ", NULL);
8550Sstevel@tonic-gate 	}
8560Sstevel@tonic-gate 
8578348SEric.Yu@Sun.COM 	if (netstat_unix_name_pr(st, &sti->sti_laddr) == -1)
8580Sstevel@tonic-gate 		return (WALK_ERR);
8590Sstevel@tonic-gate 
8608348SEric.Yu@Sun.COM 	if (netstat_unix_name_pr(st, &sti->sti_faddr) == -1)
8610Sstevel@tonic-gate 		return (WALK_ERR);
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate 	mdb_printf("%4i\n", so->so_zoneid);
8640Sstevel@tonic-gate 
8650Sstevel@tonic-gate 	return (WALK_NEXT);
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate static void
8690Sstevel@tonic-gate netstat_tcp_verbose_header_pr(void)
8700Sstevel@tonic-gate {
8710Sstevel@tonic-gate 	mdb_printf("       %<u>%-5s %-8s %-8s %-5s %-8s %-8s %5s %5s%</u>\n",
8720Sstevel@tonic-gate 	    "Swind", "Snext", "Suna", "Rwind", "Rack", "Rnext", "Rto", "Mss");
8730Sstevel@tonic-gate }
8740Sstevel@tonic-gate 
8751676Sjpk static void
8761676Sjpk get_ifname(const ire_t *ire, char *intf)
8771676Sjpk {
8781676Sjpk 	ill_t ill;
8791676Sjpk 
8801676Sjpk 	*intf = '\0';
8811676Sjpk 	if (ire->ire_type == IRE_CACHE) {
8821676Sjpk 		queue_t stq;
8831676Sjpk 
8841676Sjpk 		if (mdb_vread(&stq, sizeof (stq), (uintptr_t)ire->ire_stq) ==
8851676Sjpk 		    -1)
8861676Sjpk 			return;
8871676Sjpk 		if (mdb_vread(&ill, sizeof (ill), (uintptr_t)stq.q_ptr) == -1)
8881676Sjpk 			return;
8891676Sjpk 		(void) mdb_readstr(intf, MIN(LIFNAMSIZ, ill.ill_name_length),
8901676Sjpk 		    (uintptr_t)ill.ill_name);
8911676Sjpk 	} else if (ire->ire_ipif != NULL) {
8921676Sjpk 		ipif_t ipif;
8931676Sjpk 		char *cp;
8941676Sjpk 
8951676Sjpk 		if (mdb_vread(&ipif, sizeof (ipif),
8961676Sjpk 		    (uintptr_t)ire->ire_ipif) == -1)
8971676Sjpk 			return;
8981676Sjpk 		if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ipif.ipif_ill) ==
8991676Sjpk 		    -1)
9001676Sjpk 			return;
9011676Sjpk 		(void) mdb_readstr(intf, MIN(LIFNAMSIZ, ill.ill_name_length),
9021676Sjpk 		    (uintptr_t)ill.ill_name);
9031676Sjpk 		if (ipif.ipif_id != 0) {
9041676Sjpk 			cp = intf + strlen(intf);
9051676Sjpk 			(void) mdb_snprintf(cp, LIFNAMSIZ + 1 - (cp - intf),
9061676Sjpk 			    ":%u", ipif.ipif_id);
9071676Sjpk 		}
9081676Sjpk 	}
9091676Sjpk }
9101676Sjpk 
9111676Sjpk static void
9121676Sjpk get_v4flags(const ire_t *ire, char *flags)
9131676Sjpk {
9141676Sjpk 	(void) strcpy(flags, "U");
9151676Sjpk 	if (ire->ire_type == IRE_DEFAULT || ire->ire_type == IRE_PREFIX ||
9161676Sjpk 	    ire->ire_type == IRE_HOST || ire->ire_type == IRE_HOST_REDIRECT)
9171676Sjpk 		(void) strcat(flags, "G");
9181676Sjpk 	if (ire->ire_mask == IP_HOST_MASK)
9191676Sjpk 		(void) strcat(flags, "H");
9201676Sjpk 	if (ire->ire_type == IRE_HOST_REDIRECT)
9211676Sjpk 		(void) strcat(flags, "D");
9221676Sjpk 	if (ire->ire_type == IRE_CACHE)
9231676Sjpk 		(void) strcat(flags, "A");
9241676Sjpk 	if (ire->ire_type == IRE_BROADCAST)
9251676Sjpk 		(void) strcat(flags, "B");
9261676Sjpk 	if (ire->ire_type == IRE_LOCAL)
9271676Sjpk 		(void) strcat(flags, "L");
9281676Sjpk 	if (ire->ire_flags & RTF_MULTIRT)
9291676Sjpk 		(void) strcat(flags, "M");
9301676Sjpk 	if (ire->ire_flags & RTF_SETSRC)
9311676Sjpk 		(void) strcat(flags, "S");
9321676Sjpk }
9331676Sjpk 
9341676Sjpk static int
9351676Sjpk netstat_irev4_cb(uintptr_t kaddr, const void *walk_data, void *cb_data)
9361676Sjpk {
9371676Sjpk 	const ire_t *ire = walk_data;
9381676Sjpk 	uint_t *opts = cb_data;
9391676Sjpk 	ipaddr_t gate;
9401676Sjpk 	char flags[10], intf[LIFNAMSIZ + 1];
9411676Sjpk 
9424823Sseb 	if (ire->ire_ipversion != IPV4_VERSION)
9431676Sjpk 		return (WALK_NEXT);
9441676Sjpk 
9451676Sjpk 	if (!(*opts & NETSTAT_ALL) && (ire->ire_type == IRE_CACHE ||
9461676Sjpk 	    ire->ire_type == IRE_BROADCAST || ire->ire_type == IRE_LOCAL))
9471676Sjpk 		return (WALK_NEXT);
9481676Sjpk 
9491676Sjpk 	if (*opts & NETSTAT_FIRST) {
9501676Sjpk 		*opts &= ~NETSTAT_FIRST;
9511676Sjpk 		mdb_printf("%<u>%s Table: IPv4%</u>\n",
9521676Sjpk 		    (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing");
9531676Sjpk 		if (*opts & NETSTAT_VERBOSE) {
9541676Sjpk 			mdb_printf("%<u>%-?s %-*s %-*s %-*s Device Mxfrg Rtt  "
9551676Sjpk 			    " Ref Flg Out   In/Fwd%</u>\n",
9561676Sjpk 			    "Address", ADDR_V4_WIDTH, "Destination",
9571676Sjpk 			    ADDR_V4_WIDTH, "Mask", ADDR_V4_WIDTH, "Gateway");
9581676Sjpk 		} else {
9591676Sjpk 			mdb_printf("%<u>%-?s %-*s %-*s Flags Ref  Use   "
9601676Sjpk 			    "Interface%</u>\n",
9611676Sjpk 			    "Address", ADDR_V4_WIDTH, "Destination",
9621676Sjpk 			    ADDR_V4_WIDTH, "Gateway");
9631676Sjpk 		}
9641676Sjpk 	}
9651676Sjpk 
9661676Sjpk 	gate = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK|IRE_BROADCAST)) ?
9671676Sjpk 	    ire->ire_src_addr : ire->ire_gateway_addr;
9681676Sjpk 
9691676Sjpk 	get_v4flags(ire, flags);
9701676Sjpk 
9711676Sjpk 	get_ifname(ire, intf);
9721676Sjpk 
9731676Sjpk 	if (*opts & NETSTAT_VERBOSE) {
9741676Sjpk 		mdb_printf("%?p %-*I %-*I %-*I %-6s %5u%c %4u %3u %-3s %5u "
9751676Sjpk 		    "%u\n", kaddr, ADDR_V4_WIDTH, ire->ire_addr, ADDR_V4_WIDTH,
9761676Sjpk 		    ire->ire_mask, ADDR_V4_WIDTH, gate, intf,
9771676Sjpk 		    ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ',
9781676Sjpk 		    ire->ire_uinfo.iulp_rtt, ire->ire_refcnt, flags,
9791676Sjpk 		    ire->ire_ob_pkt_count, ire->ire_ib_pkt_count);
9801676Sjpk 	} else {
9811676Sjpk 		mdb_printf("%?p %-*I %-*I %-5s %4u %5u %s\n", kaddr,
9821676Sjpk 		    ADDR_V4_WIDTH, ire->ire_addr, ADDR_V4_WIDTH, gate, flags,
9831676Sjpk 		    ire->ire_refcnt,
9841676Sjpk 		    ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf);
9851676Sjpk 	}
9861676Sjpk 
9871676Sjpk 	return (WALK_NEXT);
9881676Sjpk }
9891676Sjpk 
9901676Sjpk int
9911676Sjpk ip_mask_to_plen_v6(const in6_addr_t *v6mask)
9921676Sjpk {
9931676Sjpk 	int plen;
9941676Sjpk 	int i;
9951676Sjpk 	uint32_t val;
9961676Sjpk 
9971676Sjpk 	for (i = 3; i >= 0; i--)
9981676Sjpk 		if (v6mask->s6_addr32[i] != 0)
9991676Sjpk 			break;
10001676Sjpk 	if (i < 0)
10011676Sjpk 		return (0);
10021676Sjpk 	plen = 32 + 32 * i;
10031676Sjpk 	val = v6mask->s6_addr32[i];
10041676Sjpk 	while (!(val & 1)) {
10051676Sjpk 		val >>= 1;
10061676Sjpk 		plen--;
10071676Sjpk 	}
10081676Sjpk 
10091676Sjpk 	return (plen);
10101676Sjpk }
10111676Sjpk 
10121676Sjpk static int
10131676Sjpk netstat_irev6_cb(uintptr_t kaddr, const void *walk_data, void *cb_data)
10141676Sjpk {
10151676Sjpk 	const ire_t *ire = walk_data;
10161676Sjpk 	uint_t *opts = cb_data;
10171676Sjpk 	const in6_addr_t *gatep;
10181676Sjpk 	char deststr[ADDR_V6_WIDTH + 5];
10191676Sjpk 	char flags[10], intf[LIFNAMSIZ + 1];
10201676Sjpk 	int masklen;
10211676Sjpk 
10221676Sjpk 	if (ire->ire_ipversion != IPV6_VERSION)
10231676Sjpk 		return (WALK_NEXT);
10241676Sjpk 
10251676Sjpk 	if (!(*opts & NETSTAT_ALL) && ire->ire_type == IRE_CACHE)
10261676Sjpk 		return (WALK_NEXT);
10271676Sjpk 
10281676Sjpk 	if (*opts & NETSTAT_FIRST) {
10291676Sjpk 		*opts &= ~NETSTAT_FIRST;
10301676Sjpk 		mdb_printf("\n%<u>%s Table: IPv6%</u>\n",
10311676Sjpk 		    (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing");
10321676Sjpk 		if (*opts & NETSTAT_VERBOSE) {
10331676Sjpk 			mdb_printf("%<u>%-?s %-*s %-*s If    PMTU   Rtt   Ref "
10341676Sjpk 			    "Flags Out    In/Fwd%</u>\n",
10351676Sjpk 			    "Address", ADDR_V6_WIDTH+4, "Destination/Mask",
10361676Sjpk 			    ADDR_V6_WIDTH, "Gateway");
10371676Sjpk 		} else {
10381676Sjpk 			mdb_printf("%<u>%-?s %-*s %-*s Flags Ref Use    If"
10391676Sjpk 			    "%</u>\n",
10401676Sjpk 			    "Address", ADDR_V6_WIDTH+4, "Destination/Mask",
10411676Sjpk 			    ADDR_V6_WIDTH, "Gateway");
10421676Sjpk 		}
10431676Sjpk 	}
10441676Sjpk 
10451676Sjpk 	gatep = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK)) ?
10461676Sjpk 	    &ire->ire_src_addr_v6 : &ire->ire_gateway_addr_v6;
10471676Sjpk 
10481676Sjpk 	masklen = ip_mask_to_plen_v6(&ire->ire_mask_v6);
10491676Sjpk 	(void) mdb_snprintf(deststr, sizeof (deststr), "%N/%d",
10501676Sjpk 	    &ire->ire_addr_v6, masklen);
10511676Sjpk 
10521676Sjpk 	(void) strcpy(flags, "U");
10531676Sjpk 	if (ire->ire_type == IRE_DEFAULT || ire->ire_type == IRE_PREFIX ||
10541676Sjpk 	    ire->ire_type == IRE_HOST || ire->ire_type == IRE_HOST_REDIRECT)
10551676Sjpk 		(void) strcat(flags, "G");
10561676Sjpk 	if (masklen == IPV6_ABITS)
10571676Sjpk 		(void) strcat(flags, "H");
10581676Sjpk 	if (ire->ire_type == IRE_HOST_REDIRECT)
10591676Sjpk 		(void) strcat(flags, "D");
10601676Sjpk 	if (ire->ire_type == IRE_CACHE)
10611676Sjpk 		(void) strcat(flags, "A");
10621676Sjpk 	if (ire->ire_type == IRE_LOCAL)
10631676Sjpk 		(void) strcat(flags, "L");
10641676Sjpk 	if (ire->ire_flags & RTF_MULTIRT)
10651676Sjpk 		(void) strcat(flags, "M");
10661676Sjpk 	if (ire->ire_flags & RTF_SETSRC)
10671676Sjpk 		(void) strcat(flags, "S");
10681676Sjpk 
10691676Sjpk 	get_ifname(ire, intf);
10701676Sjpk 
10711676Sjpk 	if (*opts & NETSTAT_VERBOSE) {
10721676Sjpk 		mdb_printf("%?p %-*s %-*N %-5s %5u%c %5u %3u %-5s %6u %u\n",
10731676Sjpk 		    kaddr, ADDR_V6_WIDTH+4, deststr, ADDR_V6_WIDTH, gatep,
10741676Sjpk 		    intf, ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ',
10751676Sjpk 		    ire->ire_uinfo.iulp_rtt, ire->ire_refcnt,
10761676Sjpk 		    flags, ire->ire_ob_pkt_count, ire->ire_ib_pkt_count);
10771676Sjpk 	} else {
10781676Sjpk 		mdb_printf("%?p %-*s %-*N %-5s %3u %6u %s\n", kaddr,
10791676Sjpk 		    ADDR_V6_WIDTH+4, deststr, ADDR_V6_WIDTH, gatep, flags,
10801676Sjpk 		    ire->ire_refcnt,
10811676Sjpk 		    ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf);
10821676Sjpk 	}
10831676Sjpk 
10841676Sjpk 	return (WALK_NEXT);
10851676Sjpk }
10861676Sjpk 
1087*9089SVasumathi.Sundaram@Sun.COM static void
1088*9089SVasumathi.Sundaram@Sun.COM netstat_header_v4(int proto)
1089*9089SVasumathi.Sundaram@Sun.COM {
1090*9089SVasumathi.Sundaram@Sun.COM 	if (proto == IPPROTO_TCP)
1091*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%<u>%-?s ", "TCPv4");
1092*9089SVasumathi.Sundaram@Sun.COM 	else if (proto == IPPROTO_UDP)
1093*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%<u>%-?s ", "UDPv4");
1094*9089SVasumathi.Sundaram@Sun.COM 	else if (proto == IPPROTO_ICMP)
1095*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%<u>%-?s ", "ICMPv4");
1096*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("State %6s%*s %6s%*s %-5s %-4s%</u>\n",
1097*9089SVasumathi.Sundaram@Sun.COM 	    "", ADDR_V4_WIDTH, "Local Address",
1098*9089SVasumathi.Sundaram@Sun.COM 	    "", ADDR_V4_WIDTH, "Remote Address", "Stack", "Zone");
1099*9089SVasumathi.Sundaram@Sun.COM }
1100*9089SVasumathi.Sundaram@Sun.COM 
1101*9089SVasumathi.Sundaram@Sun.COM static void
1102*9089SVasumathi.Sundaram@Sun.COM netstat_header_v6(int proto)
1103*9089SVasumathi.Sundaram@Sun.COM {
1104*9089SVasumathi.Sundaram@Sun.COM 	if (proto == IPPROTO_TCP)
1105*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%<u>%-?s ", "TCPv6");
1106*9089SVasumathi.Sundaram@Sun.COM 	else if (proto == IPPROTO_UDP)
1107*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%<u>%-?s ", "UDPv6");
1108*9089SVasumathi.Sundaram@Sun.COM 	else if (proto == IPPROTO_ICMP)
1109*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%<u>%-?s ", "ICMPv6");
1110*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("State %6s%*s %6s%*s %-5s %-4s%</u>\n",
1111*9089SVasumathi.Sundaram@Sun.COM 	    "", ADDR_V6_WIDTH, "Local Address",
1112*9089SVasumathi.Sundaram@Sun.COM 	    "", ADDR_V6_WIDTH, "Remote Address", "Stack", "Zone");
1113*9089SVasumathi.Sundaram@Sun.COM }
1114*9089SVasumathi.Sundaram@Sun.COM 
1115*9089SVasumathi.Sundaram@Sun.COM static int
1116*9089SVasumathi.Sundaram@Sun.COM netstat_print_conn(const char *cache, int proto, mdb_walk_cb_t cbfunc,
1117*9089SVasumathi.Sundaram@Sun.COM     void *cbdata)
1118*9089SVasumathi.Sundaram@Sun.COM {
1119*9089SVasumathi.Sundaram@Sun.COM 	netstat_cb_data_t *ncb = cbdata;
1120*9089SVasumathi.Sundaram@Sun.COM 
1121*9089SVasumathi.Sundaram@Sun.COM 	if ((ncb->opts & NETSTAT_VERBOSE) && proto == IPPROTO_TCP)
1122*9089SVasumathi.Sundaram@Sun.COM 		netstat_tcp_verbose_header_pr();
1123*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_walk(cache, cbfunc, cbdata) == -1) {
1124*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to walk %s", cache);
1125*9089SVasumathi.Sundaram@Sun.COM 		return (DCMD_ERR);
1126*9089SVasumathi.Sundaram@Sun.COM 	}
1127*9089SVasumathi.Sundaram@Sun.COM 	return (DCMD_OK);
1128*9089SVasumathi.Sundaram@Sun.COM }
1129*9089SVasumathi.Sundaram@Sun.COM 
1130*9089SVasumathi.Sundaram@Sun.COM static int
1131*9089SVasumathi.Sundaram@Sun.COM netstat_print_common(const char *cache, int proto, mdb_walk_cb_t cbfunc,
1132*9089SVasumathi.Sundaram@Sun.COM     void *cbdata)
1133*9089SVasumathi.Sundaram@Sun.COM {
1134*9089SVasumathi.Sundaram@Sun.COM 	netstat_cb_data_t *ncb = cbdata;
1135*9089SVasumathi.Sundaram@Sun.COM 	int af = ncb->af;
1136*9089SVasumathi.Sundaram@Sun.COM 	int status = DCMD_OK;
1137*9089SVasumathi.Sundaram@Sun.COM 
1138*9089SVasumathi.Sundaram@Sun.COM 	if (af != AF_INET6) {
1139*9089SVasumathi.Sundaram@Sun.COM 		ncb->af = AF_INET;
1140*9089SVasumathi.Sundaram@Sun.COM 		netstat_header_v4(proto);
1141*9089SVasumathi.Sundaram@Sun.COM 		status = netstat_print_conn(cache, proto, cbfunc, cbdata);
1142*9089SVasumathi.Sundaram@Sun.COM 	}
1143*9089SVasumathi.Sundaram@Sun.COM 	if (status == DCMD_OK && af != AF_INET) {
1144*9089SVasumathi.Sundaram@Sun.COM 		ncb->af = AF_INET6;
1145*9089SVasumathi.Sundaram@Sun.COM 		netstat_header_v6(proto);
1146*9089SVasumathi.Sundaram@Sun.COM 		status = netstat_print_conn(cache, proto, cbfunc, cbdata);
1147*9089SVasumathi.Sundaram@Sun.COM 	}
1148*9089SVasumathi.Sundaram@Sun.COM 	ncb->af = af;
1149*9089SVasumathi.Sundaram@Sun.COM 	return (status);
1150*9089SVasumathi.Sundaram@Sun.COM }
1151*9089SVasumathi.Sundaram@Sun.COM 
11520Sstevel@tonic-gate /*ARGSUSED*/
11530Sstevel@tonic-gate int
11540Sstevel@tonic-gate netstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11550Sstevel@tonic-gate {
11560Sstevel@tonic-gate 	uint_t opts = 0;
11570Sstevel@tonic-gate 	const char *optf = NULL;
11580Sstevel@tonic-gate 	const char *optP = NULL;
1159*9089SVasumathi.Sundaram@Sun.COM 	netstat_cb_data_t *cbdata;
1160*9089SVasumathi.Sundaram@Sun.COM 	int status;
1161*9089SVasumathi.Sundaram@Sun.COM 	int af = 0;
11620Sstevel@tonic-gate 
11630Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
11640Sstevel@tonic-gate 	    'a', MDB_OPT_SETBITS, NETSTAT_ALL, &opts,
11650Sstevel@tonic-gate 	    'f', MDB_OPT_STR, &optf,
11660Sstevel@tonic-gate 	    'P', MDB_OPT_STR, &optP,
11671676Sjpk 	    'r', MDB_OPT_SETBITS, NETSTAT_ROUTE, &opts,
11681676Sjpk 	    'v', MDB_OPT_SETBITS, NETSTAT_VERBOSE, &opts,
11690Sstevel@tonic-gate 	    NULL) != argc)
11700Sstevel@tonic-gate 		return (DCMD_USAGE);
11710Sstevel@tonic-gate 
11720Sstevel@tonic-gate 	if (optP != NULL) {
1173*9089SVasumathi.Sundaram@Sun.COM 		if ((strcmp("tcp", optP) != 0) && (strcmp("udp", optP) != 0) &&
1174*9089SVasumathi.Sundaram@Sun.COM 		    (strcmp("icmp", optP) != 0))
11750Sstevel@tonic-gate 			return (DCMD_USAGE);
11761676Sjpk 		if (opts & NETSTAT_ROUTE)
11771676Sjpk 			return (DCMD_USAGE);
11780Sstevel@tonic-gate 	}
11790Sstevel@tonic-gate 
11801676Sjpk 	if (optf == NULL)
11811676Sjpk 		opts |= NETSTAT_V4 | NETSTAT_V6 | NETSTAT_UNIX;
11821676Sjpk 	else if (strcmp("inet", optf) == 0)
11831676Sjpk 		opts |= NETSTAT_V4;
11841676Sjpk 	else if (strcmp("inet6", optf) == 0)
11851676Sjpk 		opts |= NETSTAT_V6;
11861676Sjpk 	else if (strcmp("unix", optf) == 0)
11871676Sjpk 		opts |= NETSTAT_UNIX;
11881676Sjpk 	else
11891676Sjpk 		return (DCMD_USAGE);
11901676Sjpk 
11911676Sjpk 	if (opts & NETSTAT_ROUTE) {
11921676Sjpk 		if (!(opts & (NETSTAT_V4|NETSTAT_V6)))
11930Sstevel@tonic-gate 			return (DCMD_USAGE);
11941676Sjpk 		if (opts & NETSTAT_V4) {
11951676Sjpk 			opts |= NETSTAT_FIRST;
11961676Sjpk 			if (mdb_walk("ip`ire", netstat_irev4_cb, &opts) == -1) {
11971676Sjpk 				mdb_warn("failed to walk ip`ire");
11981676Sjpk 				return (DCMD_ERR);
11991676Sjpk 			}
12001676Sjpk 		}
12011676Sjpk 		if (opts & NETSTAT_V6) {
12021676Sjpk 			opts |= NETSTAT_FIRST;
12031676Sjpk 			if (mdb_walk("ip`ire", netstat_irev6_cb, &opts) == -1) {
12041676Sjpk 				mdb_warn("failed to walk ip`ire");
12051676Sjpk 				return (DCMD_ERR);
12061676Sjpk 			}
12071676Sjpk 		}
12081676Sjpk 		return (DCMD_OK);
12090Sstevel@tonic-gate 	}
12100Sstevel@tonic-gate 
1211*9089SVasumathi.Sundaram@Sun.COM 	if ((opts & NETSTAT_UNIX) && (optP == NULL)) {
12120Sstevel@tonic-gate 		/* Print Unix Domain Sockets */
12130Sstevel@tonic-gate 		mdb_printf("%<u>%-?s %-10s %-?s %-?s %-14s %-14s %s%</u>\n",
12140Sstevel@tonic-gate 		    "AF_UNIX", "Type", "Vnode", "Conn", "Local Addr",
12150Sstevel@tonic-gate 		    "Remote Addr", "Zone");
12160Sstevel@tonic-gate 
12170Sstevel@tonic-gate 		if (mdb_walk("genunix`sonode", netstat_unix_cb, NULL) == -1) {
12180Sstevel@tonic-gate 			mdb_warn("failed to walk genunix`sonode");
12190Sstevel@tonic-gate 			return (DCMD_ERR);
12200Sstevel@tonic-gate 		}
1221*9089SVasumathi.Sundaram@Sun.COM 		if (!(opts & (NETSTAT_V4 | NETSTAT_V6)))
1222*9089SVasumathi.Sundaram@Sun.COM 			return (DCMD_OK);
12230Sstevel@tonic-gate 	}
12240Sstevel@tonic-gate 
1225*9089SVasumathi.Sundaram@Sun.COM 	cbdata = mdb_alloc(sizeof (netstat_cb_data_t), UM_SLEEP);
1226*9089SVasumathi.Sundaram@Sun.COM 	cbdata->opts = opts;
1227*9089SVasumathi.Sundaram@Sun.COM 	if ((optf != NULL) && (opts & NETSTAT_V4))
1228*9089SVasumathi.Sundaram@Sun.COM 		af = AF_INET;
1229*9089SVasumathi.Sundaram@Sun.COM 	else if ((optf != NULL) && (opts & NETSTAT_V6))
1230*9089SVasumathi.Sundaram@Sun.COM 		af = AF_INET6;
1231*9089SVasumathi.Sundaram@Sun.COM 
1232*9089SVasumathi.Sundaram@Sun.COM 	cbdata->af = af;
1233*9089SVasumathi.Sundaram@Sun.COM 	if ((optP == NULL) || (strcmp("tcp", optP) == 0)) {
1234*9089SVasumathi.Sundaram@Sun.COM 		status = netstat_print_common("tcp_conn_cache", IPPROTO_TCP,
1235*9089SVasumathi.Sundaram@Sun.COM 		    netstat_tcp_cb, cbdata);
1236*9089SVasumathi.Sundaram@Sun.COM 		if (status != DCMD_OK)
1237*9089SVasumathi.Sundaram@Sun.COM 			goto out;
1238*9089SVasumathi.Sundaram@Sun.COM 	}
1239*9089SVasumathi.Sundaram@Sun.COM 
1240*9089SVasumathi.Sundaram@Sun.COM 	if ((optP == NULL) || (strcmp("udp", optP) == 0)) {
1241*9089SVasumathi.Sundaram@Sun.COM 		status = netstat_print_common("udp_conn_cache", IPPROTO_UDP,
1242*9089SVasumathi.Sundaram@Sun.COM 		    netstat_udp_cb, cbdata);
1243*9089SVasumathi.Sundaram@Sun.COM 		if (status != DCMD_OK)
1244*9089SVasumathi.Sundaram@Sun.COM 			goto out;
1245*9089SVasumathi.Sundaram@Sun.COM 	}
1246*9089SVasumathi.Sundaram@Sun.COM 
1247*9089SVasumathi.Sundaram@Sun.COM 	if ((optP == NULL) || (strcmp("icmp", optP) == 0)) {
1248*9089SVasumathi.Sundaram@Sun.COM 		status = netstat_print_common("rawip_conn_cache", IPPROTO_ICMP,
1249*9089SVasumathi.Sundaram@Sun.COM 		    netstat_icmp_cb, cbdata);
1250*9089SVasumathi.Sundaram@Sun.COM 		if (status != DCMD_OK)
1251*9089SVasumathi.Sundaram@Sun.COM 			goto out;
1252*9089SVasumathi.Sundaram@Sun.COM 	}
1253*9089SVasumathi.Sundaram@Sun.COM out:
1254*9089SVasumathi.Sundaram@Sun.COM 	mdb_free(cbdata, sizeof (netstat_cb_data_t));
1255*9089SVasumathi.Sundaram@Sun.COM 	return (status);
12560Sstevel@tonic-gate }
1257