xref: /onnv-gate/usr/src/cmd/mdb/common/modules/ip/ip.c (revision 11042:2d6e217af1b4)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52546Scarlsonj  * Common Development and Distribution License (the "License").
62546Scarlsonj  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
228485SPeter.Memishian@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/stropts.h>
280Sstevel@tonic-gate #include <sys/stream.h>
290Sstevel@tonic-gate #include <sys/socket.h>
300Sstevel@tonic-gate #include <sys/avl_impl.h>
319089SVasumathi.Sundaram@Sun.COM #include <net/if_types.h>
320Sstevel@tonic-gate #include <net/if.h>
330Sstevel@tonic-gate #include <net/route.h>
340Sstevel@tonic-gate #include <netinet/in.h>
350Sstevel@tonic-gate #include <netinet/ip6.h>
360Sstevel@tonic-gate #include <netinet/udp.h>
370Sstevel@tonic-gate #include <netinet/sctp.h>
380Sstevel@tonic-gate #include <inet/mib2.h>
390Sstevel@tonic-gate #include <inet/common.h>
400Sstevel@tonic-gate #include <inet/ip.h>
410Sstevel@tonic-gate #include <inet/ip_ire.h>
420Sstevel@tonic-gate #include <inet/ip6.h>
430Sstevel@tonic-gate #include <inet/ipclassifier.h>
440Sstevel@tonic-gate #include <inet/mi.h>
450Sstevel@tonic-gate #include <sys/squeue_impl.h>
465023Scarlsonj #include <sys/modhash_impl.h>
475940Ssowmini #include <inet/ip_ndp.h>
485940Ssowmini #include <inet/ip_if.h>
4910946SSangeeta.Misra@Sun.COM #include <ilb.h>
5010946SSangeeta.Misra@Sun.COM #include <ilb/ilb_impl.h>
5110946SSangeeta.Misra@Sun.COM #include <ilb/ilb_stack.h>
5210946SSangeeta.Misra@Sun.COM #include <ilb/ilb_nat.h>
5310946SSangeeta.Misra@Sun.COM #include <ilb/ilb_conn.h>
545940Ssowmini #include <sys/dlpi.h>
55*11042SErik.Nordmark@Sun.COM #include <sys/zone.h>
560Sstevel@tonic-gate 
570Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
580Sstevel@tonic-gate #include <mdb/mdb_ks.h>
590Sstevel@tonic-gate 
600Sstevel@tonic-gate #define	ADDR_WIDTH 11
615940Ssowmini #define	L2MAXADDRSTRLEN	255
625940Ssowmini #define	MAX_SAP_LEN	255
639089SVasumathi.Sundaram@Sun.COM #define	DEFCOLS		80
640Sstevel@tonic-gate 
650Sstevel@tonic-gate typedef struct {
660Sstevel@tonic-gate 	const char *bit_name;	/* name of bit */
670Sstevel@tonic-gate 	const char *bit_descr;	/* description of bit's purpose */
680Sstevel@tonic-gate } bitname_t;
690Sstevel@tonic-gate 
700Sstevel@tonic-gate static const bitname_t squeue_states[] = {
710Sstevel@tonic-gate 	{ "SQS_PROC",		"being processed" },
720Sstevel@tonic-gate 	{ "SQS_WORKER",		"... by a worker thread" },
730Sstevel@tonic-gate 	{ "SQS_ENTER",		"... by an squeue_enter() thread" },
740Sstevel@tonic-gate 	{ "SQS_FAST",		"... in fast-path mode" },
750Sstevel@tonic-gate 	{ "SQS_USER", 		"A non interrupt user" },
760Sstevel@tonic-gate 	{ "SQS_BOUND",		"worker thread bound to CPU" },
770Sstevel@tonic-gate 	{ "SQS_PROFILE",	"profiling enabled" },
780Sstevel@tonic-gate 	{ "SQS_REENTER",	"re-entered thred" },
790Sstevel@tonic-gate 	{ NULL }
800Sstevel@tonic-gate };
810Sstevel@tonic-gate 
820Sstevel@tonic-gate typedef struct illif_walk_data {
830Sstevel@tonic-gate 	ill_g_head_t ill_g_heads[MAX_G_HEADS];
840Sstevel@tonic-gate 	int ill_list;
850Sstevel@tonic-gate 	ill_if_t ill_if;
860Sstevel@tonic-gate } illif_walk_data_t;
870Sstevel@tonic-gate 
88*11042SErik.Nordmark@Sun.COM typedef struct ncec_walk_data_s {
89*11042SErik.Nordmark@Sun.COM 	struct ndp_g_s	ncec_ip_ndp;
90*11042SErik.Nordmark@Sun.COM 	int		ncec_hash_tbl_index;
91*11042SErik.Nordmark@Sun.COM 	ncec_t 		ncec;
92*11042SErik.Nordmark@Sun.COM } ncec_walk_data_t;
93*11042SErik.Nordmark@Sun.COM 
94*11042SErik.Nordmark@Sun.COM typedef struct ncec_cbdata_s {
95*11042SErik.Nordmark@Sun.COM 	uintptr_t ncec_addr;
96*11042SErik.Nordmark@Sun.COM 	int	  ncec_ipversion;
97*11042SErik.Nordmark@Sun.COM } ncec_cbdata_t;
985940Ssowmini 
995940Ssowmini typedef struct nce_cbdata_s {
100*11042SErik.Nordmark@Sun.COM 	int		nce_ipversion;
101*11042SErik.Nordmark@Sun.COM 	char		nce_ill_name[LIFNAMSIZ];
1025940Ssowmini } nce_cbdata_t;
1035940Ssowmini 
1045940Ssowmini typedef struct ire_cbdata_s {
1055940Ssowmini 	int		ire_ipversion;
1065940Ssowmini 	boolean_t	verbose;
1075940Ssowmini } ire_cbdata_t;
1085940Ssowmini 
109*11042SErik.Nordmark@Sun.COM typedef struct zi_cbdata_s {
110*11042SErik.Nordmark@Sun.COM 	const char	*zone_name;
111*11042SErik.Nordmark@Sun.COM 	ip_stack_t	*ipst;
112*11042SErik.Nordmark@Sun.COM 	boolean_t	shared_ip_zone;
113*11042SErik.Nordmark@Sun.COM } zi_cbdata_t;
114*11042SErik.Nordmark@Sun.COM 
1155023Scarlsonj typedef struct th_walk_data {
1165023Scarlsonj 	uint_t		thw_non_zero_only;
1175023Scarlsonj 	boolean_t	thw_match;
1185023Scarlsonj 	uintptr_t	thw_matchkey;
1195023Scarlsonj 	uintptr_t	thw_ipst;
1205023Scarlsonj 	clock_t		thw_lbolt;
1215023Scarlsonj } th_walk_data_t;
1225023Scarlsonj 
1239089SVasumathi.Sundaram@Sun.COM typedef struct ipcl_hash_walk_data_s {
1249089SVasumathi.Sundaram@Sun.COM 	conn_t		*conn;
1259089SVasumathi.Sundaram@Sun.COM 	int		connf_tbl_index;
1269089SVasumathi.Sundaram@Sun.COM 	uintptr_t	hash_tbl;
1279089SVasumathi.Sundaram@Sun.COM 	int		hash_tbl_size;
1289089SVasumathi.Sundaram@Sun.COM } ipcl_hash_walk_data_t;
1299089SVasumathi.Sundaram@Sun.COM 
1309089SVasumathi.Sundaram@Sun.COM typedef struct ill_walk_data_s {
1319089SVasumathi.Sundaram@Sun.COM 	ill_t 		ill;
1329089SVasumathi.Sundaram@Sun.COM } ill_walk_data_t;
1339089SVasumathi.Sundaram@Sun.COM 
1349089SVasumathi.Sundaram@Sun.COM typedef struct ill_cbdata_s {
1359089SVasumathi.Sundaram@Sun.COM 	uintptr_t ill_addr;
1369089SVasumathi.Sundaram@Sun.COM 	int	  ill_ipversion;
137*11042SErik.Nordmark@Sun.COM 	ip_stack_t *ill_ipst;
1389089SVasumathi.Sundaram@Sun.COM 	boolean_t verbose;
1399089SVasumathi.Sundaram@Sun.COM } ill_cbdata_t;
1409089SVasumathi.Sundaram@Sun.COM 
1419089SVasumathi.Sundaram@Sun.COM typedef struct ipif_walk_data_s {
1429089SVasumathi.Sundaram@Sun.COM 	ipif_t 		ipif;
1439089SVasumathi.Sundaram@Sun.COM } ipif_walk_data_t;
1449089SVasumathi.Sundaram@Sun.COM 
1459089SVasumathi.Sundaram@Sun.COM typedef struct ipif_cbdata_s {
1469089SVasumathi.Sundaram@Sun.COM 	ill_t		ill;
1479089SVasumathi.Sundaram@Sun.COM 	int		ipif_ipversion;
1489089SVasumathi.Sundaram@Sun.COM 	boolean_t 	verbose;
1499089SVasumathi.Sundaram@Sun.COM } ipif_cbdata_t;
1509089SVasumathi.Sundaram@Sun.COM 
1519089SVasumathi.Sundaram@Sun.COM typedef struct hash_walk_arg_s {
1529089SVasumathi.Sundaram@Sun.COM 	off_t	tbl_off;
1539089SVasumathi.Sundaram@Sun.COM 	off_t	size_off;
1549089SVasumathi.Sundaram@Sun.COM } hash_walk_arg_t;
1559089SVasumathi.Sundaram@Sun.COM 
1569089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t udp_hash_arg = {
1579089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_udp_fanout),
1589089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_udp_fanout_size)
1599089SVasumathi.Sundaram@Sun.COM };
1609089SVasumathi.Sundaram@Sun.COM 
1619089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t conn_hash_arg = {
1629089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_conn_fanout),
1639089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_conn_fanout_size)
1649089SVasumathi.Sundaram@Sun.COM };
1659089SVasumathi.Sundaram@Sun.COM 
1669089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t bind_hash_arg = {
1679089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_bind_fanout),
1689089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_bind_fanout_size)
1699089SVasumathi.Sundaram@Sun.COM };
1709089SVasumathi.Sundaram@Sun.COM 
1719089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t proto_hash_arg = {
172*11042SErik.Nordmark@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v4),
1739089SVasumathi.Sundaram@Sun.COM 	0
1749089SVasumathi.Sundaram@Sun.COM };
1759089SVasumathi.Sundaram@Sun.COM 
1769089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t proto_v6_hash_arg = {
1779089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v6),
1789089SVasumathi.Sundaram@Sun.COM 	0
1799089SVasumathi.Sundaram@Sun.COM };
1809089SVasumathi.Sundaram@Sun.COM 
1819089SVasumathi.Sundaram@Sun.COM typedef struct ip_list_walk_data_s {
1829089SVasumathi.Sundaram@Sun.COM 	off_t 	nextoff;
1839089SVasumathi.Sundaram@Sun.COM } ip_list_walk_data_t;
1849089SVasumathi.Sundaram@Sun.COM 
1859089SVasumathi.Sundaram@Sun.COM typedef struct ip_list_walk_arg_s {
1869089SVasumathi.Sundaram@Sun.COM 	off_t	off;
1879089SVasumathi.Sundaram@Sun.COM 	size_t	size;
1889089SVasumathi.Sundaram@Sun.COM 	off_t	nextp_off;
1899089SVasumathi.Sundaram@Sun.COM } ip_list_walk_arg_t;
1909089SVasumathi.Sundaram@Sun.COM 
1919089SVasumathi.Sundaram@Sun.COM static ip_list_walk_arg_t ipif_walk_arg = {
1929089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ill_t, ill_ipif),
1939089SVasumathi.Sundaram@Sun.COM 	sizeof (ipif_t),
1949089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ipif_t, ipif_next)
1959089SVasumathi.Sundaram@Sun.COM };
1969089SVasumathi.Sundaram@Sun.COM 
1979089SVasumathi.Sundaram@Sun.COM static ip_list_walk_arg_t srcid_walk_arg = {
1989089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_srcid_head),
1999089SVasumathi.Sundaram@Sun.COM 	sizeof (srcid_map_t),
2009089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(srcid_map_t, sm_next)
2019089SVasumathi.Sundaram@Sun.COM };
2029089SVasumathi.Sundaram@Sun.COM 
2030Sstevel@tonic-gate static int iphdr(uintptr_t, uint_t, int, const mdb_arg_t *);
2040Sstevel@tonic-gate static int ip6hdr(uintptr_t, uint_t, int, const mdb_arg_t *);
2050Sstevel@tonic-gate 
2069089SVasumathi.Sundaram@Sun.COM static int ill(uintptr_t, uint_t, int, const mdb_arg_t *);
2079089SVasumathi.Sundaram@Sun.COM static void ill_help(void);
2089089SVasumathi.Sundaram@Sun.COM static int ill_walk_init(mdb_walk_state_t *);
2099089SVasumathi.Sundaram@Sun.COM static int ill_walk_step(mdb_walk_state_t *);
2109089SVasumathi.Sundaram@Sun.COM static int ill_format(uintptr_t, const void *, void *);
2119089SVasumathi.Sundaram@Sun.COM static void ill_header(boolean_t);
2129089SVasumathi.Sundaram@Sun.COM 
2139089SVasumathi.Sundaram@Sun.COM static int ipif(uintptr_t, uint_t, int, const mdb_arg_t *);
2149089SVasumathi.Sundaram@Sun.COM static void ipif_help(void);
2159089SVasumathi.Sundaram@Sun.COM static int ipif_walk_init(mdb_walk_state_t *);
2169089SVasumathi.Sundaram@Sun.COM static int ipif_walk_step(mdb_walk_state_t *);
2179089SVasumathi.Sundaram@Sun.COM static int ipif_format(uintptr_t, const void *, void *);
2189089SVasumathi.Sundaram@Sun.COM static void ipif_header(boolean_t);
2199089SVasumathi.Sundaram@Sun.COM 
2209089SVasumathi.Sundaram@Sun.COM static int ip_list_walk_init(mdb_walk_state_t *);
2219089SVasumathi.Sundaram@Sun.COM static int ip_list_walk_step(mdb_walk_state_t *);
2229089SVasumathi.Sundaram@Sun.COM static void ip_list_walk_fini(mdb_walk_state_t *);
2239089SVasumathi.Sundaram@Sun.COM static int srcid_walk_step(mdb_walk_state_t *);
2249089SVasumathi.Sundaram@Sun.COM 
2255940Ssowmini static int ire_format(uintptr_t addr, const void *, void *);
226*11042SErik.Nordmark@Sun.COM static int ncec_format(uintptr_t addr, const ncec_t *ncec, int ipversion);
227*11042SErik.Nordmark@Sun.COM static int ncec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv);
228*11042SErik.Nordmark@Sun.COM static int ncec_walk_step(mdb_walk_state_t *wsp);
229*11042SErik.Nordmark@Sun.COM static int ncec_stack_walk_init(mdb_walk_state_t *wsp);
230*11042SErik.Nordmark@Sun.COM static int ncec_stack_walk_step(mdb_walk_state_t *wsp);
231*11042SErik.Nordmark@Sun.COM static void ncec_stack_walk_fini(mdb_walk_state_t *wsp);
232*11042SErik.Nordmark@Sun.COM static int ncec_cb(uintptr_t addr, const ncec_walk_data_t *iw,
233*11042SErik.Nordmark@Sun.COM     ncec_cbdata_t *id);
234*11042SErik.Nordmark@Sun.COM static char *nce_l2_addr(const nce_t *, const ill_t *);
2353448Sdh155122 
2369089SVasumathi.Sundaram@Sun.COM static int ipcl_hash_walk_init(mdb_walk_state_t *);
2379089SVasumathi.Sundaram@Sun.COM static int ipcl_hash_walk_step(mdb_walk_state_t *);
2389089SVasumathi.Sundaram@Sun.COM static void ipcl_hash_walk_fini(mdb_walk_state_t *);
2399089SVasumathi.Sundaram@Sun.COM 
2409089SVasumathi.Sundaram@Sun.COM static int conn_status_walk_step(mdb_walk_state_t *);
2419089SVasumathi.Sundaram@Sun.COM static int conn_status(uintptr_t, uint_t, int, const mdb_arg_t *);
2429089SVasumathi.Sundaram@Sun.COM static void conn_status_help(void);
2439089SVasumathi.Sundaram@Sun.COM 
2449089SVasumathi.Sundaram@Sun.COM static int srcid_status(uintptr_t, uint_t, int, const mdb_arg_t *);
2459089SVasumathi.Sundaram@Sun.COM 
24610946SSangeeta.Misra@Sun.COM static int ilb_stacks_walk_step(mdb_walk_state_t *);
24710946SSangeeta.Misra@Sun.COM static int ilb_rules_walk_init(mdb_walk_state_t *);
24810946SSangeeta.Misra@Sun.COM static int ilb_rules_walk_step(mdb_walk_state_t *);
24910946SSangeeta.Misra@Sun.COM static int ilb_servers_walk_init(mdb_walk_state_t *);
25010946SSangeeta.Misra@Sun.COM static int ilb_servers_walk_step(mdb_walk_state_t *);
25110946SSangeeta.Misra@Sun.COM static int ilb_nat_src_walk_init(mdb_walk_state_t *);
25210946SSangeeta.Misra@Sun.COM static int ilb_nat_src_walk_step(mdb_walk_state_t *);
25310946SSangeeta.Misra@Sun.COM static int ilb_conn_walk_init(mdb_walk_state_t *);
25410946SSangeeta.Misra@Sun.COM static int ilb_conn_walk_step(mdb_walk_state_t *);
25510946SSangeeta.Misra@Sun.COM static int ilb_sticky_walk_init(mdb_walk_state_t *);
25610946SSangeeta.Misra@Sun.COM static int ilb_sticky_walk_step(mdb_walk_state_t *);
25710946SSangeeta.Misra@Sun.COM static void ilb_common_walk_fini(mdb_walk_state_t *);
25810946SSangeeta.Misra@Sun.COM 
2593448Sdh155122 /*
2603448Sdh155122  * Given the kernel address of an ip_stack_t, return the stackid
2613448Sdh155122  */
2623448Sdh155122 static int
2633448Sdh155122 ips_to_stackid(uintptr_t kaddr)
2643448Sdh155122 {
2653448Sdh155122 	ip_stack_t ipss;
2663448Sdh155122 	netstack_t nss;
2673448Sdh155122 
2683448Sdh155122 	if (mdb_vread(&ipss, sizeof (ipss), kaddr) == -1) {
2693448Sdh155122 		mdb_warn("failed to read ip_stack_t %p", kaddr);
2703448Sdh155122 		return (0);
2713448Sdh155122 	}
2723448Sdh155122 	kaddr = (uintptr_t)ipss.ips_netstack;
2733448Sdh155122 	if (mdb_vread(&nss, sizeof (nss), kaddr) == -1) {
2743448Sdh155122 		mdb_warn("failed to read netstack_t %p", kaddr);
2753448Sdh155122 		return (0);
2763448Sdh155122 	}
2773448Sdh155122 	return (nss.netstack_stackid);
2783448Sdh155122 }
2793448Sdh155122 
280*11042SErik.Nordmark@Sun.COM /* ARGSUSED */
281*11042SErik.Nordmark@Sun.COM static int
282*11042SErik.Nordmark@Sun.COM zone_to_ips_cb(uintptr_t addr, const void *zi_arg, void *zi_cb_arg)
283*11042SErik.Nordmark@Sun.COM {
284*11042SErik.Nordmark@Sun.COM 	zi_cbdata_t *zi_cb = zi_cb_arg;
285*11042SErik.Nordmark@Sun.COM 	zone_t zone;
286*11042SErik.Nordmark@Sun.COM 	char zone_name[ZONENAME_MAX];
287*11042SErik.Nordmark@Sun.COM 	netstack_t ns;
288*11042SErik.Nordmark@Sun.COM 
289*11042SErik.Nordmark@Sun.COM 	if (mdb_vread(&zone, sizeof (zone_t), addr) == -1) {
290*11042SErik.Nordmark@Sun.COM 		mdb_warn("can't read zone at %p", addr);
291*11042SErik.Nordmark@Sun.COM 		return (WALK_ERR);
292*11042SErik.Nordmark@Sun.COM 	}
293*11042SErik.Nordmark@Sun.COM 
294*11042SErik.Nordmark@Sun.COM 	(void) mdb_readstr(zone_name, ZONENAME_MAX, (uintptr_t)zone.zone_name);
295*11042SErik.Nordmark@Sun.COM 
296*11042SErik.Nordmark@Sun.COM 	if (strcmp(zi_cb->zone_name, zone_name) != 0)
297*11042SErik.Nordmark@Sun.COM 		return (WALK_NEXT);
298*11042SErik.Nordmark@Sun.COM 
299*11042SErik.Nordmark@Sun.COM 	zi_cb->shared_ip_zone = (!(zone.zone_flags & ZF_NET_EXCL) &&
300*11042SErik.Nordmark@Sun.COM 	    (strcmp(zone_name, "global") != 0));
301*11042SErik.Nordmark@Sun.COM 
302*11042SErik.Nordmark@Sun.COM 	if (mdb_vread(&ns, sizeof (netstack_t), (uintptr_t)zone.zone_netstack)
303*11042SErik.Nordmark@Sun.COM 	    == -1) {
304*11042SErik.Nordmark@Sun.COM 		mdb_warn("can't read netstack at %p", zone.zone_netstack);
305*11042SErik.Nordmark@Sun.COM 		return (WALK_ERR);
306*11042SErik.Nordmark@Sun.COM 	}
307*11042SErik.Nordmark@Sun.COM 
308*11042SErik.Nordmark@Sun.COM 	zi_cb->ipst = ns.netstack_ip;
309*11042SErik.Nordmark@Sun.COM 	return (WALK_DONE);
310*11042SErik.Nordmark@Sun.COM }
311*11042SErik.Nordmark@Sun.COM 
312*11042SErik.Nordmark@Sun.COM static ip_stack_t *
313*11042SErik.Nordmark@Sun.COM zone_to_ips(const char *zone_name)
314*11042SErik.Nordmark@Sun.COM {
315*11042SErik.Nordmark@Sun.COM 	zi_cbdata_t zi_cb;
316*11042SErik.Nordmark@Sun.COM 
317*11042SErik.Nordmark@Sun.COM 	if (zone_name == NULL)
318*11042SErik.Nordmark@Sun.COM 		return (NULL);
319*11042SErik.Nordmark@Sun.COM 
320*11042SErik.Nordmark@Sun.COM 	zi_cb.zone_name = zone_name;
321*11042SErik.Nordmark@Sun.COM 	zi_cb.ipst = NULL;
322*11042SErik.Nordmark@Sun.COM 	zi_cb.shared_ip_zone = B_FALSE;
323*11042SErik.Nordmark@Sun.COM 
324*11042SErik.Nordmark@Sun.COM 	if (mdb_walk("zone", (mdb_walk_cb_t)zone_to_ips_cb, &zi_cb) == -1) {
325*11042SErik.Nordmark@Sun.COM 		mdb_warn("failed to walk zone");
326*11042SErik.Nordmark@Sun.COM 		return (NULL);
327*11042SErik.Nordmark@Sun.COM 	}
328*11042SErik.Nordmark@Sun.COM 
329*11042SErik.Nordmark@Sun.COM 	if (zi_cb.shared_ip_zone) {
330*11042SErik.Nordmark@Sun.COM 		mdb_warn("%s is a Shared-IP zone, try '-s global' instead\n",
331*11042SErik.Nordmark@Sun.COM 		    zone_name);
332*11042SErik.Nordmark@Sun.COM 		return (NULL);
333*11042SErik.Nordmark@Sun.COM 	}
334*11042SErik.Nordmark@Sun.COM 
335*11042SErik.Nordmark@Sun.COM 	if (zi_cb.ipst == NULL) {
336*11042SErik.Nordmark@Sun.COM 		mdb_warn("failed to find zone %s\n", zone_name);
337*11042SErik.Nordmark@Sun.COM 		return (NULL);
338*11042SErik.Nordmark@Sun.COM 	}
339*11042SErik.Nordmark@Sun.COM 
340*11042SErik.Nordmark@Sun.COM 	return (zi_cb.ipst);
341*11042SErik.Nordmark@Sun.COM }
342*11042SErik.Nordmark@Sun.COM 
3430Sstevel@tonic-gate int
3443448Sdh155122 ip_stacks_walk_init(mdb_walk_state_t *wsp)
3453448Sdh155122 {
3463448Sdh155122 	if (mdb_layered_walk("netstack", wsp) == -1) {
3473448Sdh155122 		mdb_warn("can't walk 'netstack'");
3483448Sdh155122 		return (WALK_ERR);
3493448Sdh155122 	}
3503448Sdh155122 	return (WALK_NEXT);
3513448Sdh155122 }
3523448Sdh155122 
3533448Sdh155122 int
3543448Sdh155122 ip_stacks_walk_step(mdb_walk_state_t *wsp)
3553448Sdh155122 {
3563448Sdh155122 	uintptr_t kaddr;
3573448Sdh155122 	netstack_t nss;
3583448Sdh155122 
3593448Sdh155122 	if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
3603448Sdh155122 		mdb_warn("can't read netstack at %p", wsp->walk_addr);
3613448Sdh155122 		return (WALK_ERR);
3623448Sdh155122 	}
3633448Sdh155122 	kaddr = (uintptr_t)nss.netstack_modules[NS_IP];
3643448Sdh155122 
3653448Sdh155122 	return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
3663448Sdh155122 }
3673448Sdh155122 
3685023Scarlsonj int
3695023Scarlsonj th_hash_walk_init(mdb_walk_state_t *wsp)
3705023Scarlsonj {
3715023Scarlsonj 	GElf_Sym sym;
3725023Scarlsonj 	list_node_t *next;
3735023Scarlsonj 
3745023Scarlsonj 	if (wsp->walk_addr == NULL) {
3755023Scarlsonj 		if (mdb_lookup_by_obj("ip", "ip_thread_list", &sym) == 0) {
3765023Scarlsonj 			wsp->walk_addr = sym.st_value;
3775023Scarlsonj 		} else {
3785023Scarlsonj 			mdb_warn("unable to locate ip_thread_list\n");
3795023Scarlsonj 			return (WALK_ERR);
3805023Scarlsonj 		}
3815023Scarlsonj 	}
3825023Scarlsonj 
3835023Scarlsonj 	if (mdb_vread(&next, sizeof (next),
3845023Scarlsonj 	    wsp->walk_addr + offsetof(list_t, list_head) +
3855023Scarlsonj 	    offsetof(list_node_t, list_next)) == -1 ||
3865023Scarlsonj 	    next == NULL) {
3875023Scarlsonj 		mdb_warn("non-DEBUG image; cannot walk th_hash list\n");
3885023Scarlsonj 		return (WALK_ERR);
3895023Scarlsonj 	}
3905023Scarlsonj 
3915023Scarlsonj 	if (mdb_layered_walk("list", wsp) == -1) {
3925023Scarlsonj 		mdb_warn("can't walk 'list'");
3935023Scarlsonj 		return (WALK_ERR);
3945023Scarlsonj 	} else {
3955023Scarlsonj 		return (WALK_NEXT);
3965023Scarlsonj 	}
3975023Scarlsonj }
3985023Scarlsonj 
3995023Scarlsonj int
4005023Scarlsonj th_hash_walk_step(mdb_walk_state_t *wsp)
4015023Scarlsonj {
4025023Scarlsonj 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
4035023Scarlsonj 	    wsp->walk_cbdata));
4045023Scarlsonj }
4055023Scarlsonj 
4063448Sdh155122 /*
4073448Sdh155122  * Called with walk_addr being the address of ips_ill_g_heads
4083448Sdh155122  */
4093448Sdh155122 int
4103448Sdh155122 illif_stack_walk_init(mdb_walk_state_t *wsp)
4110Sstevel@tonic-gate {
4120Sstevel@tonic-gate 	illif_walk_data_t *iw;
4130Sstevel@tonic-gate 
4143448Sdh155122 	if (wsp->walk_addr == NULL) {
4153448Sdh155122 		mdb_warn("illif_stack supports only local walks\n");
4160Sstevel@tonic-gate 		return (WALK_ERR);
4170Sstevel@tonic-gate 	}
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	iw = mdb_alloc(sizeof (illif_walk_data_t), UM_SLEEP);
4200Sstevel@tonic-gate 
4213448Sdh155122 	if (mdb_vread(iw->ill_g_heads, MAX_G_HEADS * sizeof (ill_g_head_t),
4223448Sdh155122 	    wsp->walk_addr) == -1) {
4233448Sdh155122 		mdb_warn("failed to read 'ips_ill_g_heads' at %p",
4243448Sdh155122 		    wsp->walk_addr);
4250Sstevel@tonic-gate 		mdb_free(iw, sizeof (illif_walk_data_t));
4260Sstevel@tonic-gate 		return (WALK_ERR);
4270Sstevel@tonic-gate 	}
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	iw->ill_list = 0;
4303448Sdh155122 	wsp->walk_addr = (uintptr_t)iw->ill_g_heads[0].ill_g_list_head;
4310Sstevel@tonic-gate 	wsp->walk_data = iw;
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	return (WALK_NEXT);
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate int
4373448Sdh155122 illif_stack_walk_step(mdb_walk_state_t *wsp)
4380Sstevel@tonic-gate {
4390Sstevel@tonic-gate 	uintptr_t addr = wsp->walk_addr;
4400Sstevel@tonic-gate 	illif_walk_data_t *iw = wsp->walk_data;
4410Sstevel@tonic-gate 	int list = iw->ill_list;
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 	if (mdb_vread(&iw->ill_if, sizeof (ill_if_t), addr) == -1) {
4440Sstevel@tonic-gate 		mdb_warn("failed to read ill_if_t at %p", addr);
4450Sstevel@tonic-gate 		return (WALK_ERR);
4460Sstevel@tonic-gate 	}
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)iw->ill_if.illif_next;
4490Sstevel@tonic-gate 
4503448Sdh155122 	if (wsp->walk_addr ==
4513448Sdh155122 	    (uintptr_t)iw->ill_g_heads[list].ill_g_list_head) {
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 		if (++list >= MAX_G_HEADS)
4540Sstevel@tonic-gate 			return (WALK_DONE);
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 		iw->ill_list = list;
4573448Sdh155122 		wsp->walk_addr =
4583448Sdh155122 		    (uintptr_t)iw->ill_g_heads[list].ill_g_list_head;
4590Sstevel@tonic-gate 		return (WALK_NEXT);
4600Sstevel@tonic-gate 	}
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	return (wsp->walk_callback(addr, iw, wsp->walk_cbdata));
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate void
4663448Sdh155122 illif_stack_walk_fini(mdb_walk_state_t *wsp)
4670Sstevel@tonic-gate {
4680Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (illif_walk_data_t));
4690Sstevel@tonic-gate }
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate typedef struct illif_cbdata {
4720Sstevel@tonic-gate 	uint_t ill_flags;
4730Sstevel@tonic-gate 	uintptr_t ill_addr;
4740Sstevel@tonic-gate 	int ill_printlist;	/* list to be printed (MAX_G_HEADS for all) */
4750Sstevel@tonic-gate 	boolean_t ill_printed;
4760Sstevel@tonic-gate } illif_cbdata_t;
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate static int
4790Sstevel@tonic-gate illif_cb(uintptr_t addr, const illif_walk_data_t *iw, illif_cbdata_t *id)
4800Sstevel@tonic-gate {
4810Sstevel@tonic-gate 	const char *version;
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate 	if (id->ill_printlist < MAX_G_HEADS &&
4840Sstevel@tonic-gate 	    id->ill_printlist != iw->ill_list)
4850Sstevel@tonic-gate 		return (WALK_NEXT);
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	if (id->ill_flags & DCMD_ADDRSPEC && id->ill_addr != addr)
4880Sstevel@tonic-gate 		return (WALK_NEXT);
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	if (id->ill_flags & DCMD_PIPE_OUT) {
4910Sstevel@tonic-gate 		mdb_printf("%p\n", addr);
4920Sstevel@tonic-gate 		return (WALK_NEXT);
4930Sstevel@tonic-gate 	}
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 	switch (iw->ill_list) {
4960Sstevel@tonic-gate 		case IP_V4_G_HEAD:	version = "v4";	break;
4970Sstevel@tonic-gate 		case IP_V6_G_HEAD:	version = "v6";	break;
4980Sstevel@tonic-gate 		default:		version = "??"; break;
4990Sstevel@tonic-gate 	}
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	mdb_printf("%?p %2s %?p %10d %?p %s\n",
5020Sstevel@tonic-gate 	    addr, version, addr + offsetof(ill_if_t, illif_avl_by_ppa),
5030Sstevel@tonic-gate 	    iw->ill_if.illif_avl_by_ppa.avl_numnodes,
5040Sstevel@tonic-gate 	    iw->ill_if.illif_ppa_arena, iw->ill_if.illif_name);
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 	id->ill_printed = TRUE;
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	return (WALK_NEXT);
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate int
5125940Ssowmini ip_stacks_common_walk_init(mdb_walk_state_t *wsp)
5133448Sdh155122 {
5143448Sdh155122 	if (mdb_layered_walk("ip_stacks", wsp) == -1) {
5153448Sdh155122 		mdb_warn("can't walk 'ip_stacks'");
5163448Sdh155122 		return (WALK_ERR);
5173448Sdh155122 	}
5183448Sdh155122 
5193448Sdh155122 	return (WALK_NEXT);
5203448Sdh155122 }
5213448Sdh155122 
5223448Sdh155122 int
5233448Sdh155122 illif_walk_step(mdb_walk_state_t *wsp)
5243448Sdh155122 {
5253448Sdh155122 	uintptr_t kaddr;
5263448Sdh155122 
5273448Sdh155122 	kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ill_g_heads);
5283448Sdh155122 
5293448Sdh155122 	if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) {
5303448Sdh155122 		mdb_warn("can't read ips_ip_cache_table at %p", kaddr);
5313448Sdh155122 		return (WALK_ERR);
5323448Sdh155122 	}
5333448Sdh155122 
5343448Sdh155122 	if (mdb_pwalk("illif_stack", wsp->walk_callback,
5355023Scarlsonj 	    wsp->walk_cbdata, kaddr) == -1) {
5363448Sdh155122 		mdb_warn("couldn't walk 'illif_stack' for ips_ill_g_heads %p",
5373448Sdh155122 		    kaddr);
5383448Sdh155122 		return (WALK_ERR);
5393448Sdh155122 	}
5403448Sdh155122 	return (WALK_NEXT);
5413448Sdh155122 }
5423448Sdh155122 
5433448Sdh155122 int
5440Sstevel@tonic-gate illif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5450Sstevel@tonic-gate {
5460Sstevel@tonic-gate 	illif_cbdata_t id;
5470Sstevel@tonic-gate 	ill_if_t ill_if;
5480Sstevel@tonic-gate 	const char *opt_P = NULL;
5490Sstevel@tonic-gate 	int printlist = MAX_G_HEADS;
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
5520Sstevel@tonic-gate 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
5530Sstevel@tonic-gate 		return (DCMD_USAGE);
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	if (opt_P != NULL) {
5560Sstevel@tonic-gate 		if (strcmp("v4", opt_P) == 0) {
5570Sstevel@tonic-gate 			printlist = IP_V4_G_HEAD;
5580Sstevel@tonic-gate 		} else if (strcmp("v6", opt_P) == 0) {
5590Sstevel@tonic-gate 			printlist = IP_V6_G_HEAD;
5600Sstevel@tonic-gate 		} else {
5610Sstevel@tonic-gate 			mdb_warn("invalid protocol '%s'\n", opt_P);
5620Sstevel@tonic-gate 			return (DCMD_USAGE);
5630Sstevel@tonic-gate 		}
5640Sstevel@tonic-gate 	}
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) {
5670Sstevel@tonic-gate 		mdb_printf("%<u>%?s %2s %?s %10s %?s %-10s%</u>\n",
5680Sstevel@tonic-gate 		    "ADDR", "IP", "AVLADDR", "NUMNODES", "ARENA", "NAME");
5690Sstevel@tonic-gate 	}
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 	id.ill_flags = flags;
5720Sstevel@tonic-gate 	id.ill_addr = addr;
5730Sstevel@tonic-gate 	id.ill_printlist = printlist;
5740Sstevel@tonic-gate 	id.ill_printed = FALSE;
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate 	if (mdb_walk("illif", (mdb_walk_cb_t)illif_cb, &id) == -1) {
5770Sstevel@tonic-gate 		mdb_warn("can't walk ill_if_t structures");
5780Sstevel@tonic-gate 		return (DCMD_ERR);
5790Sstevel@tonic-gate 	}
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC) || opt_P != NULL || id.ill_printed)
5820Sstevel@tonic-gate 		return (DCMD_OK);
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate 	/*
5850Sstevel@tonic-gate 	 * If an address is specified and the walk doesn't find it,
5860Sstevel@tonic-gate 	 * print it anyway.
5870Sstevel@tonic-gate 	 */
5880Sstevel@tonic-gate 	if (mdb_vread(&ill_if, sizeof (ill_if_t), addr) == -1) {
5890Sstevel@tonic-gate 		mdb_warn("failed to read ill_if_t at %p", addr);
5900Sstevel@tonic-gate 		return (DCMD_ERR);
5910Sstevel@tonic-gate 	}
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 	mdb_printf("%?p %2s %?p %10d %?p %s\n",
5940Sstevel@tonic-gate 	    addr, "??", addr + offsetof(ill_if_t, illif_avl_by_ppa),
5950Sstevel@tonic-gate 	    ill_if.illif_avl_by_ppa.avl_numnodes,
5960Sstevel@tonic-gate 	    ill_if.illif_ppa_arena, ill_if.illif_name);
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 	return (DCMD_OK);
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate static void
6020Sstevel@tonic-gate illif_help(void)
6030Sstevel@tonic-gate {
6040Sstevel@tonic-gate 	mdb_printf("Options:\n");
6050Sstevel@tonic-gate 	mdb_printf("\t-P v4 | v6"
6060Sstevel@tonic-gate 	    "\tfilter interface structures for the specified protocol\n");
6070Sstevel@tonic-gate }
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate int
610*11042SErik.Nordmark@Sun.COM nce_walk_init(mdb_walk_state_t *wsp)
611*11042SErik.Nordmark@Sun.COM {
612*11042SErik.Nordmark@Sun.COM 	if (mdb_layered_walk("nce_cache", wsp) == -1) {
613*11042SErik.Nordmark@Sun.COM 		mdb_warn("can't walk 'nce_cache'");
614*11042SErik.Nordmark@Sun.COM 		return (WALK_ERR);
615*11042SErik.Nordmark@Sun.COM 	}
616*11042SErik.Nordmark@Sun.COM 
617*11042SErik.Nordmark@Sun.COM 	return (WALK_NEXT);
618*11042SErik.Nordmark@Sun.COM }
619*11042SErik.Nordmark@Sun.COM 
620*11042SErik.Nordmark@Sun.COM int
621*11042SErik.Nordmark@Sun.COM nce_walk_step(mdb_walk_state_t *wsp)
622*11042SErik.Nordmark@Sun.COM {
623*11042SErik.Nordmark@Sun.COM 	nce_t nce;
624*11042SErik.Nordmark@Sun.COM 
625*11042SErik.Nordmark@Sun.COM 	if (mdb_vread(&nce, sizeof (nce), wsp->walk_addr) == -1) {
626*11042SErik.Nordmark@Sun.COM 		mdb_warn("can't read nce at %p", wsp->walk_addr);
627*11042SErik.Nordmark@Sun.COM 		return (WALK_ERR);
628*11042SErik.Nordmark@Sun.COM 	}
629*11042SErik.Nordmark@Sun.COM 
630*11042SErik.Nordmark@Sun.COM 	return (wsp->walk_callback(wsp->walk_addr, &nce, wsp->walk_cbdata));
631*11042SErik.Nordmark@Sun.COM }
632*11042SErik.Nordmark@Sun.COM 
633*11042SErik.Nordmark@Sun.COM static int
634*11042SErik.Nordmark@Sun.COM nce_format(uintptr_t addr, const nce_t *ncep, void *nce_cb_arg)
635*11042SErik.Nordmark@Sun.COM {
636*11042SErik.Nordmark@Sun.COM 	nce_cbdata_t *nce_cb = nce_cb_arg;
637*11042SErik.Nordmark@Sun.COM 	ill_t ill;
638*11042SErik.Nordmark@Sun.COM 	char ill_name[LIFNAMSIZ];
639*11042SErik.Nordmark@Sun.COM 	ncec_t ncec;
640*11042SErik.Nordmark@Sun.COM 
641*11042SErik.Nordmark@Sun.COM 	if (mdb_vread(&ncec, sizeof (ncec),
642*11042SErik.Nordmark@Sun.COM 	    (uintptr_t)ncep->nce_common) == -1) {
643*11042SErik.Nordmark@Sun.COM 		mdb_warn("can't read ncec at %p", ncep->nce_common);
644*11042SErik.Nordmark@Sun.COM 		return (WALK_NEXT);
645*11042SErik.Nordmark@Sun.COM 	}
646*11042SErik.Nordmark@Sun.COM 	if (nce_cb->nce_ipversion != 0 &&
647*11042SErik.Nordmark@Sun.COM 	    ncec.ncec_ipversion != nce_cb->nce_ipversion)
648*11042SErik.Nordmark@Sun.COM 		return (WALK_NEXT);
649*11042SErik.Nordmark@Sun.COM 
650*11042SErik.Nordmark@Sun.COM 	if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ncep->nce_ill) == -1) {
651*11042SErik.Nordmark@Sun.COM 		mdb_snprintf(ill_name, sizeof (ill_name), "--");
652*11042SErik.Nordmark@Sun.COM 	} else {
653*11042SErik.Nordmark@Sun.COM 		(void) mdb_readstr(ill_name,
654*11042SErik.Nordmark@Sun.COM 		    MIN(LIFNAMSIZ, ill.ill_name_length),
655*11042SErik.Nordmark@Sun.COM 		    (uintptr_t)ill.ill_name);
656*11042SErik.Nordmark@Sun.COM 	}
657*11042SErik.Nordmark@Sun.COM 
658*11042SErik.Nordmark@Sun.COM 	if (nce_cb->nce_ill_name[0] != '\0' &&
659*11042SErik.Nordmark@Sun.COM 	    strncmp(nce_cb->nce_ill_name, ill_name, LIFNAMSIZ) != 0)
660*11042SErik.Nordmark@Sun.COM 		return (WALK_NEXT);
661*11042SErik.Nordmark@Sun.COM 
662*11042SErik.Nordmark@Sun.COM 	if (ncec.ncec_ipversion == IPV6_VERSION) {
663*11042SErik.Nordmark@Sun.COM 
664*11042SErik.Nordmark@Sun.COM 		mdb_printf("%?p %5s %-18s %?p %6d %N\n",
665*11042SErik.Nordmark@Sun.COM 		    addr, ill_name,
666*11042SErik.Nordmark@Sun.COM 		    nce_l2_addr(ncep, &ill),
667*11042SErik.Nordmark@Sun.COM 		    ncep->nce_fp_mp,
668*11042SErik.Nordmark@Sun.COM 		    ncep->nce_refcnt,
669*11042SErik.Nordmark@Sun.COM 		    &ncep->nce_addr);
670*11042SErik.Nordmark@Sun.COM 
671*11042SErik.Nordmark@Sun.COM 	} else {
672*11042SErik.Nordmark@Sun.COM 		struct in_addr nceaddr;
673*11042SErik.Nordmark@Sun.COM 
674*11042SErik.Nordmark@Sun.COM 		IN6_V4MAPPED_TO_INADDR(&ncep->nce_addr, &nceaddr);
675*11042SErik.Nordmark@Sun.COM 		mdb_printf("%?p %5s %-18s %?p %6d %I\n",
676*11042SErik.Nordmark@Sun.COM 		    addr, ill_name,
677*11042SErik.Nordmark@Sun.COM 		    nce_l2_addr(ncep, &ill),
678*11042SErik.Nordmark@Sun.COM 		    ncep->nce_fp_mp,
679*11042SErik.Nordmark@Sun.COM 		    ncep->nce_refcnt,
680*11042SErik.Nordmark@Sun.COM 		    nceaddr.s_addr);
681*11042SErik.Nordmark@Sun.COM 	}
682*11042SErik.Nordmark@Sun.COM 
683*11042SErik.Nordmark@Sun.COM 	return (WALK_NEXT);
684*11042SErik.Nordmark@Sun.COM }
685*11042SErik.Nordmark@Sun.COM 
686*11042SErik.Nordmark@Sun.COM int
687*11042SErik.Nordmark@Sun.COM dce_walk_init(mdb_walk_state_t *wsp)
688*11042SErik.Nordmark@Sun.COM {
689*11042SErik.Nordmark@Sun.COM 	wsp->walk_data = (void *)wsp->walk_addr;
690*11042SErik.Nordmark@Sun.COM 
691*11042SErik.Nordmark@Sun.COM 	if (mdb_layered_walk("dce_cache", wsp) == -1) {
692*11042SErik.Nordmark@Sun.COM 		mdb_warn("can't walk 'dce_cache'");
693*11042SErik.Nordmark@Sun.COM 		return (WALK_ERR);
694*11042SErik.Nordmark@Sun.COM 	}
695*11042SErik.Nordmark@Sun.COM 
696*11042SErik.Nordmark@Sun.COM 	return (WALK_NEXT);
697*11042SErik.Nordmark@Sun.COM }
698*11042SErik.Nordmark@Sun.COM 
699*11042SErik.Nordmark@Sun.COM int
700*11042SErik.Nordmark@Sun.COM dce_walk_step(mdb_walk_state_t *wsp)
701*11042SErik.Nordmark@Sun.COM {
702*11042SErik.Nordmark@Sun.COM 	dce_t dce;
703*11042SErik.Nordmark@Sun.COM 
704*11042SErik.Nordmark@Sun.COM 	if (mdb_vread(&dce, sizeof (dce), wsp->walk_addr) == -1) {
705*11042SErik.Nordmark@Sun.COM 		mdb_warn("can't read dce at %p", wsp->walk_addr);
706*11042SErik.Nordmark@Sun.COM 		return (WALK_ERR);
707*11042SErik.Nordmark@Sun.COM 	}
708*11042SErik.Nordmark@Sun.COM 
709*11042SErik.Nordmark@Sun.COM 	/* If ip_stack_t is specified, skip DCEs that don't belong to it. */
710*11042SErik.Nordmark@Sun.COM 	if ((wsp->walk_data != NULL) && (wsp->walk_data != dce.dce_ipst))
711*11042SErik.Nordmark@Sun.COM 		return (WALK_NEXT);
712*11042SErik.Nordmark@Sun.COM 
713*11042SErik.Nordmark@Sun.COM 	return (wsp->walk_callback(wsp->walk_addr, &dce, wsp->walk_cbdata));
714*11042SErik.Nordmark@Sun.COM }
715*11042SErik.Nordmark@Sun.COM 
716*11042SErik.Nordmark@Sun.COM int
7170Sstevel@tonic-gate ire_walk_init(mdb_walk_state_t *wsp)
7180Sstevel@tonic-gate {
719*11042SErik.Nordmark@Sun.COM 	wsp->walk_data = (void *)wsp->walk_addr;
720*11042SErik.Nordmark@Sun.COM 
7210Sstevel@tonic-gate 	if (mdb_layered_walk("ire_cache", wsp) == -1) {
7220Sstevel@tonic-gate 		mdb_warn("can't walk 'ire_cache'");
7230Sstevel@tonic-gate 		return (WALK_ERR);
7240Sstevel@tonic-gate 	}
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 	return (WALK_NEXT);
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate int
7300Sstevel@tonic-gate ire_walk_step(mdb_walk_state_t *wsp)
7310Sstevel@tonic-gate {
7320Sstevel@tonic-gate 	ire_t ire;
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 	if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) {
7350Sstevel@tonic-gate 		mdb_warn("can't read ire at %p", wsp->walk_addr);
7360Sstevel@tonic-gate 		return (WALK_ERR);
7370Sstevel@tonic-gate 	}
7380Sstevel@tonic-gate 
739*11042SErik.Nordmark@Sun.COM 	/* If ip_stack_t is specified, skip IREs that don't belong to it. */
740*11042SErik.Nordmark@Sun.COM 	if ((wsp->walk_data != NULL) && (wsp->walk_data != ire.ire_ipst))
741*11042SErik.Nordmark@Sun.COM 		return (WALK_NEXT);
742*11042SErik.Nordmark@Sun.COM 
7430Sstevel@tonic-gate 	return (wsp->walk_callback(wsp->walk_addr, &ire, wsp->walk_cbdata));
7440Sstevel@tonic-gate }
7450Sstevel@tonic-gate 
7463448Sdh155122 /* ARGSUSED */
7473448Sdh155122 int
7483448Sdh155122 ire_next_walk_init(mdb_walk_state_t *wsp)
7493448Sdh155122 {
7503448Sdh155122 	return (WALK_NEXT);
7513448Sdh155122 }
7523448Sdh155122 
7533448Sdh155122 int
7543448Sdh155122 ire_next_walk_step(mdb_walk_state_t *wsp)
7553448Sdh155122 {
7563448Sdh155122 	ire_t ire;
7573448Sdh155122 	int status;
7583448Sdh155122 
7593448Sdh155122 
7603448Sdh155122 	if (wsp->walk_addr == NULL)
7613448Sdh155122 		return (WALK_DONE);
7623448Sdh155122 
7633448Sdh155122 	if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) {
7643448Sdh155122 		mdb_warn("can't read ire at %p", wsp->walk_addr);
7653448Sdh155122 		return (WALK_ERR);
7663448Sdh155122 	}
7673448Sdh155122 	status = wsp->walk_callback(wsp->walk_addr, &ire,
7683448Sdh155122 	    wsp->walk_cbdata);
7693448Sdh155122 
7703448Sdh155122 	if (status != WALK_NEXT)
7713448Sdh155122 		return (status);
7723448Sdh155122 
7733448Sdh155122 	wsp->walk_addr = (uintptr_t)ire.ire_next;
7743448Sdh155122 	return (status);
7753448Sdh155122 }
7763448Sdh155122 
7770Sstevel@tonic-gate static int
7785940Ssowmini ire_format(uintptr_t addr, const void *ire_arg, void *ire_cb_arg)
7790Sstevel@tonic-gate {
7805940Ssowmini 	const ire_t *irep = ire_arg;
7815940Ssowmini 	ire_cbdata_t *ire_cb = ire_cb_arg;
7825940Ssowmini 	boolean_t verbose = ire_cb->verbose;
783*11042SErik.Nordmark@Sun.COM 	ill_t ill;
784*11042SErik.Nordmark@Sun.COM 	char ill_name[LIFNAMSIZ];
785*11042SErik.Nordmark@Sun.COM 	boolean_t condemned = irep->ire_generation == IRE_GENERATION_CONDEMNED;
7865940Ssowmini 
7870Sstevel@tonic-gate 	static const mdb_bitmask_t tmasks[] = {
7880Sstevel@tonic-gate 		{ "BROADCAST",	IRE_BROADCAST,		IRE_BROADCAST	},
7890Sstevel@tonic-gate 		{ "DEFAULT",	IRE_DEFAULT,		IRE_DEFAULT	},
7900Sstevel@tonic-gate 		{ "LOCAL",	IRE_LOCAL,		IRE_LOCAL	},
7910Sstevel@tonic-gate 		{ "LOOPBACK",	IRE_LOOPBACK,		IRE_LOOPBACK	},
7920Sstevel@tonic-gate 		{ "PREFIX",	IRE_PREFIX,		IRE_PREFIX	},
793*11042SErik.Nordmark@Sun.COM 		{ "MULTICAST",	IRE_MULTICAST,		IRE_MULTICAST	},
794*11042SErik.Nordmark@Sun.COM 		{ "NOROUTE",	IRE_NOROUTE,		IRE_NOROUTE	},
7950Sstevel@tonic-gate 		{ "IF_NORESOLVER", IRE_IF_NORESOLVER,	IRE_IF_NORESOLVER },
7960Sstevel@tonic-gate 		{ "IF_RESOLVER", IRE_IF_RESOLVER,	IRE_IF_RESOLVER	},
797*11042SErik.Nordmark@Sun.COM 		{ "IF_CLONE",	IRE_IF_CLONE,		IRE_IF_CLONE	},
7980Sstevel@tonic-gate 		{ "HOST",	IRE_HOST,		IRE_HOST	},
7990Sstevel@tonic-gate 		{ NULL,		0,			0		}
8000Sstevel@tonic-gate 	};
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 	static const mdb_bitmask_t fmasks[] = {
8030Sstevel@tonic-gate 		{ "UP",		RTF_UP,			RTF_UP		},
8040Sstevel@tonic-gate 		{ "GATEWAY",	RTF_GATEWAY,		RTF_GATEWAY	},
8050Sstevel@tonic-gate 		{ "HOST",	RTF_HOST,		RTF_HOST	},
8060Sstevel@tonic-gate 		{ "REJECT",	RTF_REJECT,		RTF_REJECT	},
8070Sstevel@tonic-gate 		{ "DYNAMIC",	RTF_DYNAMIC,		RTF_DYNAMIC	},
8080Sstevel@tonic-gate 		{ "MODIFIED",	RTF_MODIFIED,		RTF_MODIFIED	},
8090Sstevel@tonic-gate 		{ "DONE",	RTF_DONE,		RTF_DONE	},
8100Sstevel@tonic-gate 		{ "MASK",	RTF_MASK,		RTF_MASK	},
8110Sstevel@tonic-gate 		{ "CLONING",	RTF_CLONING,		RTF_CLONING	},
8120Sstevel@tonic-gate 		{ "XRESOLVE",	RTF_XRESOLVE,		RTF_XRESOLVE	},
8130Sstevel@tonic-gate 		{ "LLINFO",	RTF_LLINFO,		RTF_LLINFO	},
8140Sstevel@tonic-gate 		{ "STATIC",	RTF_STATIC,		RTF_STATIC	},
8150Sstevel@tonic-gate 		{ "BLACKHOLE",	RTF_BLACKHOLE,		RTF_BLACKHOLE	},
8160Sstevel@tonic-gate 		{ "PRIVATE",	RTF_PRIVATE,		RTF_PRIVATE	},
8170Sstevel@tonic-gate 		{ "PROTO2",	RTF_PROTO2,		RTF_PROTO2	},
8180Sstevel@tonic-gate 		{ "PROTO1",	RTF_PROTO1,		RTF_PROTO1	},
8190Sstevel@tonic-gate 		{ "MULTIRT",	RTF_MULTIRT,		RTF_MULTIRT	},
8200Sstevel@tonic-gate 		{ "SETSRC",	RTF_SETSRC,		RTF_SETSRC	},
821*11042SErik.Nordmark@Sun.COM 		{ "INDIRECT",	RTF_INDIRECT,		RTF_INDIRECT	},
8220Sstevel@tonic-gate 		{ NULL,		0,			0		}
8230Sstevel@tonic-gate 	};
8240Sstevel@tonic-gate 
8255940Ssowmini 	if (ire_cb->ire_ipversion != 0 &&
8265940Ssowmini 	    irep->ire_ipversion != ire_cb->ire_ipversion)
8275940Ssowmini 		return (WALK_NEXT);
8285940Ssowmini 
829*11042SErik.Nordmark@Sun.COM 	if (mdb_vread(&ill, sizeof (ill), (uintptr_t)irep->ire_ill) == -1) {
830*11042SErik.Nordmark@Sun.COM 		mdb_snprintf(ill_name, sizeof (ill_name), "--");
831*11042SErik.Nordmark@Sun.COM 	} else {
832*11042SErik.Nordmark@Sun.COM 		(void) mdb_readstr(ill_name,
833*11042SErik.Nordmark@Sun.COM 		    MIN(LIFNAMSIZ, ill.ill_name_length),
834*11042SErik.Nordmark@Sun.COM 		    (uintptr_t)ill.ill_name);
835*11042SErik.Nordmark@Sun.COM 	}
836*11042SErik.Nordmark@Sun.COM 
8375940Ssowmini 	if (irep->ire_ipversion == IPV6_VERSION && verbose) {
8380Sstevel@tonic-gate 
839*11042SErik.Nordmark@Sun.COM 		mdb_printf("%<b>%?p%</b>%3s %40N <%hb%s>\n"
840*11042SErik.Nordmark@Sun.COM 		    "%?s %40N\n"
841*11042SErik.Nordmark@Sun.COM 		    "%?s %40d %4d <%hb> %s\n",
842*11042SErik.Nordmark@Sun.COM 		    addr, condemned ? "(C)" : "", &irep->ire_setsrc_addr_v6,
843*11042SErik.Nordmark@Sun.COM 		    irep->ire_type, tmasks,
844*11042SErik.Nordmark@Sun.COM 		    (irep->ire_testhidden ? ", HIDDEN" : ""),
845*11042SErik.Nordmark@Sun.COM 		    "", &irep->ire_addr_v6,
8463448Sdh155122 		    "", ips_to_stackid((uintptr_t)irep->ire_ipst),
8473448Sdh155122 		    irep->ire_zoneid,
848*11042SErik.Nordmark@Sun.COM 		    irep->ire_flags, fmasks, ill_name);
8490Sstevel@tonic-gate 
8505940Ssowmini 	} else if (irep->ire_ipversion == IPV6_VERSION) {
8510Sstevel@tonic-gate 
852*11042SErik.Nordmark@Sun.COM 		mdb_printf("%?p%3s %30N %30N %5d %4d %s\n",
853*11042SErik.Nordmark@Sun.COM 		    addr, condemned ? "(C)" : "", &irep->ire_setsrc_addr_v6,
8543448Sdh155122 		    &irep->ire_addr_v6,
8553448Sdh155122 		    ips_to_stackid((uintptr_t)irep->ire_ipst),
856*11042SErik.Nordmark@Sun.COM 		    irep->ire_zoneid, ill_name);
8570Sstevel@tonic-gate 
8585940Ssowmini 	} else if (verbose) {
8590Sstevel@tonic-gate 
860*11042SErik.Nordmark@Sun.COM 		mdb_printf("%<b>%?p%</b>%3s %40I <%hb%s>\n"
861*11042SErik.Nordmark@Sun.COM 		    "%?s %40I\n"
862*11042SErik.Nordmark@Sun.COM 		    "%?s %40d %4d <%hb> %s\n",
863*11042SErik.Nordmark@Sun.COM 		    addr, condemned ? "(C)" : "", irep->ire_setsrc_addr,
864*11042SErik.Nordmark@Sun.COM 		    irep->ire_type, tmasks,
865*11042SErik.Nordmark@Sun.COM 		    (irep->ire_testhidden ? ", HIDDEN" : ""),
866*11042SErik.Nordmark@Sun.COM 		    "", irep->ire_addr,
8673448Sdh155122 		    "", ips_to_stackid((uintptr_t)irep->ire_ipst),
868*11042SErik.Nordmark@Sun.COM 		    irep->ire_zoneid, irep->ire_flags, fmasks, ill_name);
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 	} else {
8710Sstevel@tonic-gate 
872*11042SErik.Nordmark@Sun.COM 		mdb_printf("%?p%3s %30I %30I %5d %4d %s\n", addr,
873*11042SErik.Nordmark@Sun.COM 		    condemned ? "(C)" : "", irep->ire_setsrc_addr,
8743448Sdh155122 		    irep->ire_addr, ips_to_stackid((uintptr_t)irep->ire_ipst),
875*11042SErik.Nordmark@Sun.COM 		    irep->ire_zoneid, ill_name);
8760Sstevel@tonic-gate 	}
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 	return (WALK_NEXT);
8790Sstevel@tonic-gate }
8800Sstevel@tonic-gate 
8810Sstevel@tonic-gate /*
8820Sstevel@tonic-gate  * There are faster ways to do this.  Given the interactive nature of this
8830Sstevel@tonic-gate  * use I don't think its worth much effort.
8840Sstevel@tonic-gate  */
8850Sstevel@tonic-gate static unsigned short
8860Sstevel@tonic-gate ipcksum(void *p, int len)
8870Sstevel@tonic-gate {
8880Sstevel@tonic-gate 	int32_t	sum = 0;
8890Sstevel@tonic-gate 
8900Sstevel@tonic-gate 	while (len > 1) {
8910Sstevel@tonic-gate 		/* alignment */
8920Sstevel@tonic-gate 		sum += *(uint16_t *)p;
8930Sstevel@tonic-gate 		p = (char *)p + sizeof (uint16_t);
8940Sstevel@tonic-gate 		if (sum & 0x80000000)
8950Sstevel@tonic-gate 			sum = (sum & 0xFFFF) + (sum >> 16);
8960Sstevel@tonic-gate 		len -= 2;
8970Sstevel@tonic-gate 	}
8980Sstevel@tonic-gate 
8990Sstevel@tonic-gate 	if (len)
9000Sstevel@tonic-gate 		sum += (uint16_t)*(unsigned char *)p;
9010Sstevel@tonic-gate 
9020Sstevel@tonic-gate 	while (sum >> 16)
9030Sstevel@tonic-gate 		sum = (sum & 0xFFFF) + (sum >> 16);
9040Sstevel@tonic-gate 
9050Sstevel@tonic-gate 	return (~sum);
9060Sstevel@tonic-gate }
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate static const mdb_bitmask_t tcp_flags[] = {
9090Sstevel@tonic-gate 	{ "SYN",	TH_SYN,		TH_SYN	},
9100Sstevel@tonic-gate 	{ "ACK",	TH_ACK,		TH_ACK	},
9110Sstevel@tonic-gate 	{ "FIN",	TH_FIN,		TH_FIN	},
9120Sstevel@tonic-gate 	{ "RST",	TH_RST,		TH_RST	},
9130Sstevel@tonic-gate 	{ "PSH",	TH_PUSH,	TH_PUSH	},
9140Sstevel@tonic-gate 	{ "ECE",	TH_ECE,		TH_ECE	},
9150Sstevel@tonic-gate 	{ "CWR",	TH_CWR,		TH_CWR	},
9160Sstevel@tonic-gate 	{ NULL,		0,		0	}
9170Sstevel@tonic-gate };
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate static void
9200Sstevel@tonic-gate tcphdr_print(struct tcphdr *tcph)
9210Sstevel@tonic-gate {
9220Sstevel@tonic-gate 	in_port_t	sport, dport;
9230Sstevel@tonic-gate 	tcp_seq		seq, ack;
9240Sstevel@tonic-gate 	uint16_t	win, urp;
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 	mdb_printf("%<b>TCP header%</b>\n");
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 	mdb_nhconvert(&sport, &tcph->th_sport, sizeof (sport));
9290Sstevel@tonic-gate 	mdb_nhconvert(&dport, &tcph->th_dport, sizeof (dport));
9300Sstevel@tonic-gate 	mdb_nhconvert(&seq, &tcph->th_seq, sizeof (seq));
9310Sstevel@tonic-gate 	mdb_nhconvert(&ack, &tcph->th_ack, sizeof (ack));
9320Sstevel@tonic-gate 	mdb_nhconvert(&win, &tcph->th_win, sizeof (win));
9330Sstevel@tonic-gate 	mdb_nhconvert(&urp, &tcph->th_urp, sizeof (urp));
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	mdb_printf("%<u>%6s %6s %10s %10s %4s %5s %5s %5s %-15s%</u>\n",
9360Sstevel@tonic-gate 	    "SPORT", "DPORT", "SEQ", "ACK", "HLEN", "WIN", "CSUM", "URP",
9370Sstevel@tonic-gate 	    "FLAGS");
9380Sstevel@tonic-gate 	mdb_printf("%6hu %6hu %10u %10u %4d %5hu %5hu %5hu <%b>\n",
9390Sstevel@tonic-gate 	    sport, dport, seq, ack, tcph->th_off << 2, win,
9400Sstevel@tonic-gate 	    tcph->th_sum, urp, tcph->th_flags, tcp_flags);
9410Sstevel@tonic-gate 	mdb_printf("0x%04x 0x%04x 0x%08x 0x%08x\n\n",
9420Sstevel@tonic-gate 	    sport, dport, seq, ack);
9430Sstevel@tonic-gate }
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate /* ARGSUSED */
9460Sstevel@tonic-gate static int
9470Sstevel@tonic-gate tcphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av)
9480Sstevel@tonic-gate {
9490Sstevel@tonic-gate 	struct tcphdr	tcph;
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
9520Sstevel@tonic-gate 		return (DCMD_USAGE);
9530Sstevel@tonic-gate 
9540Sstevel@tonic-gate 	if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) {
9550Sstevel@tonic-gate 		mdb_warn("failed to read TCP header at %p", addr);
9560Sstevel@tonic-gate 		return (DCMD_ERR);
9570Sstevel@tonic-gate 	}
9580Sstevel@tonic-gate 	tcphdr_print(&tcph);
9590Sstevel@tonic-gate 	return (DCMD_OK);
9600Sstevel@tonic-gate }
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate static void
9630Sstevel@tonic-gate udphdr_print(struct udphdr *udph)
9640Sstevel@tonic-gate {
9650Sstevel@tonic-gate 	in_port_t	sport, dport;
9660Sstevel@tonic-gate 	uint16_t	hlen;
9670Sstevel@tonic-gate 
9680Sstevel@tonic-gate 	mdb_printf("%<b>UDP header%</b>\n");
9690Sstevel@tonic-gate 
9700Sstevel@tonic-gate 	mdb_nhconvert(&sport, &udph->uh_sport, sizeof (sport));
9710Sstevel@tonic-gate 	mdb_nhconvert(&dport, &udph->uh_dport, sizeof (dport));
9720Sstevel@tonic-gate 	mdb_nhconvert(&hlen, &udph->uh_ulen, sizeof (hlen));
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate 	mdb_printf("%<u>%14s %14s %5s %6s%</u>\n",
9750Sstevel@tonic-gate 	    "SPORT", "DPORT", "LEN", "CSUM");
9760Sstevel@tonic-gate 	mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %5hu 0x%04hx\n\n", sport, sport,
9770Sstevel@tonic-gate 	    dport, dport, hlen, udph->uh_sum);
9780Sstevel@tonic-gate }
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate /* ARGSUSED */
9810Sstevel@tonic-gate static int
9820Sstevel@tonic-gate udphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av)
9830Sstevel@tonic-gate {
9840Sstevel@tonic-gate 	struct udphdr	udph;
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
9870Sstevel@tonic-gate 		return (DCMD_USAGE);
9880Sstevel@tonic-gate 
9890Sstevel@tonic-gate 	if (mdb_vread(&udph, sizeof (udph), addr) == -1) {
9900Sstevel@tonic-gate 		mdb_warn("failed to read UDP header at %p", addr);
9910Sstevel@tonic-gate 		return (DCMD_ERR);
9920Sstevel@tonic-gate 	}
9930Sstevel@tonic-gate 	udphdr_print(&udph);
9940Sstevel@tonic-gate 	return (DCMD_OK);
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate static void
9980Sstevel@tonic-gate sctphdr_print(sctp_hdr_t *sctph)
9990Sstevel@tonic-gate {
10000Sstevel@tonic-gate 	in_port_t sport, dport;
10010Sstevel@tonic-gate 
10020Sstevel@tonic-gate 	mdb_printf("%<b>SCTP header%</b>\n");
10030Sstevel@tonic-gate 	mdb_nhconvert(&sport, &sctph->sh_sport, sizeof (sport));
10040Sstevel@tonic-gate 	mdb_nhconvert(&dport, &sctph->sh_dport, sizeof (dport));
10050Sstevel@tonic-gate 
10060Sstevel@tonic-gate 	mdb_printf("%<u>%14s %14s %10s %10s%</u>\n",
10070Sstevel@tonic-gate 	    "SPORT", "DPORT", "VTAG", "CHKSUM");
10080Sstevel@tonic-gate 	mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %10u 0x%08x\n\n", sport, sport,
10090Sstevel@tonic-gate 	    dport, dport, sctph->sh_verf, sctph->sh_chksum);
10100Sstevel@tonic-gate }
10110Sstevel@tonic-gate 
10120Sstevel@tonic-gate /* ARGSUSED */
10130Sstevel@tonic-gate static int
10140Sstevel@tonic-gate sctphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av)
10150Sstevel@tonic-gate {
10160Sstevel@tonic-gate 	sctp_hdr_t sctph;
10170Sstevel@tonic-gate 
10180Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
10190Sstevel@tonic-gate 		return (DCMD_USAGE);
10200Sstevel@tonic-gate 
10210Sstevel@tonic-gate 	if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) {
10220Sstevel@tonic-gate 		mdb_warn("failed to read SCTP header at %p", addr);
10230Sstevel@tonic-gate 		return (DCMD_ERR);
10240Sstevel@tonic-gate 	}
10250Sstevel@tonic-gate 
10260Sstevel@tonic-gate 	sctphdr_print(&sctph);
10270Sstevel@tonic-gate 	return (DCMD_OK);
10280Sstevel@tonic-gate }
10290Sstevel@tonic-gate 
10300Sstevel@tonic-gate static int
10310Sstevel@tonic-gate transport_hdr(int proto, uintptr_t addr)
10320Sstevel@tonic-gate {
10330Sstevel@tonic-gate 	mdb_printf("\n");
10340Sstevel@tonic-gate 	switch (proto) {
10350Sstevel@tonic-gate 	case IPPROTO_TCP: {
10360Sstevel@tonic-gate 		struct tcphdr tcph;
10370Sstevel@tonic-gate 
10380Sstevel@tonic-gate 		if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) {
10390Sstevel@tonic-gate 			mdb_warn("failed to read TCP header at %p", addr);
10400Sstevel@tonic-gate 			return (DCMD_ERR);
10410Sstevel@tonic-gate 		}
10420Sstevel@tonic-gate 		tcphdr_print(&tcph);
10430Sstevel@tonic-gate 		break;
10440Sstevel@tonic-gate 	}
10450Sstevel@tonic-gate 	case IPPROTO_UDP:  {
10460Sstevel@tonic-gate 		struct udphdr udph;
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate 		if (mdb_vread(&udph, sizeof (udph), addr) == -1) {
10490Sstevel@tonic-gate 			mdb_warn("failed to read UDP header at %p", addr);
10500Sstevel@tonic-gate 			return (DCMD_ERR);
10510Sstevel@tonic-gate 		}
10520Sstevel@tonic-gate 		udphdr_print(&udph);
10530Sstevel@tonic-gate 		break;
10540Sstevel@tonic-gate 	}
10550Sstevel@tonic-gate 	case IPPROTO_SCTP: {
10560Sstevel@tonic-gate 		sctp_hdr_t sctph;
10570Sstevel@tonic-gate 
10580Sstevel@tonic-gate 		if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) {
10590Sstevel@tonic-gate 			mdb_warn("failed to read SCTP header at %p", addr);
10600Sstevel@tonic-gate 			return (DCMD_ERR);
10610Sstevel@tonic-gate 		}
10620Sstevel@tonic-gate 		sctphdr_print(&sctph);
10630Sstevel@tonic-gate 		break;
10640Sstevel@tonic-gate 	}
10650Sstevel@tonic-gate 	default:
10660Sstevel@tonic-gate 		break;
10670Sstevel@tonic-gate 	}
10680Sstevel@tonic-gate 
10690Sstevel@tonic-gate 	return (DCMD_OK);
10700Sstevel@tonic-gate }
10710Sstevel@tonic-gate 
10720Sstevel@tonic-gate static const mdb_bitmask_t ip_flags[] = {
10730Sstevel@tonic-gate 	{ "DF",	IPH_DF, IPH_DF	},
10740Sstevel@tonic-gate 	{ "MF", IPH_MF,	IPH_MF	},
10750Sstevel@tonic-gate 	{ NULL, 0,	0	}
10760Sstevel@tonic-gate };
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate /* ARGSUSED */
10790Sstevel@tonic-gate static int
10800Sstevel@tonic-gate iphdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
10810Sstevel@tonic-gate {
10820Sstevel@tonic-gate 	uint_t		verbose = FALSE, force = FALSE;
10830Sstevel@tonic-gate 	ipha_t		iph[1];
10840Sstevel@tonic-gate 	uint16_t	ver, totlen, hdrlen, ipid, off, csum;
10850Sstevel@tonic-gate 	uintptr_t	nxt_proto;
10860Sstevel@tonic-gate 	char		exp_csum[8];
10870Sstevel@tonic-gate 
10880Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
10890Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
10900Sstevel@tonic-gate 	    'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc)
10910Sstevel@tonic-gate 		return (DCMD_USAGE);
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 	if (mdb_vread(iph, sizeof (*iph), addr) == -1) {
10940Sstevel@tonic-gate 		mdb_warn("failed to read IPv4 header at %p", addr);
10950Sstevel@tonic-gate 		return (DCMD_ERR);
10960Sstevel@tonic-gate 	}
10970Sstevel@tonic-gate 
10980Sstevel@tonic-gate 	ver = (iph->ipha_version_and_hdr_length & 0xf0) >> 4;
10990Sstevel@tonic-gate 	if (ver != IPV4_VERSION) {
11000Sstevel@tonic-gate 		if (ver == IPV6_VERSION) {
11010Sstevel@tonic-gate 			return (ip6hdr(addr, flags, argc, argv));
11020Sstevel@tonic-gate 		} else if (!force) {
11030Sstevel@tonic-gate 			mdb_warn("unknown IP version: %d\n", ver);
11040Sstevel@tonic-gate 			return (DCMD_ERR);
11050Sstevel@tonic-gate 		}
11060Sstevel@tonic-gate 	}
11070Sstevel@tonic-gate 
11080Sstevel@tonic-gate 	mdb_printf("%<b>IPv4 header%</b>\n");
11090Sstevel@tonic-gate 	mdb_printf("%-34s %-34s\n"
11100Sstevel@tonic-gate 	    "%<u>%-4s %-4s %-5s %-5s %-6s %-5s %-5s %-6s %-8s %-6s%</u>\n",
11110Sstevel@tonic-gate 	    "SRC", "DST",
11120Sstevel@tonic-gate 	    "HLEN", "TOS", "LEN", "ID", "OFFSET", "TTL", "PROTO", "CHKSUM",
11130Sstevel@tonic-gate 	    "EXP-CSUM", "FLGS");
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate 	hdrlen = (iph->ipha_version_and_hdr_length & 0x0f) << 2;
11160Sstevel@tonic-gate 	mdb_nhconvert(&totlen, &iph->ipha_length, sizeof (totlen));
11170Sstevel@tonic-gate 	mdb_nhconvert(&ipid, &iph->ipha_ident, sizeof (ipid));
11180Sstevel@tonic-gate 	mdb_nhconvert(&off, &iph->ipha_fragment_offset_and_flags, sizeof (off));
11190Sstevel@tonic-gate 	if (hdrlen == IP_SIMPLE_HDR_LENGTH) {
11200Sstevel@tonic-gate 		if ((csum = ipcksum(iph, sizeof (*iph))) != 0)
11210Sstevel@tonic-gate 			csum = ~(~csum + ~iph->ipha_hdr_checksum);
11220Sstevel@tonic-gate 		else
11230Sstevel@tonic-gate 			csum = iph->ipha_hdr_checksum;
11240Sstevel@tonic-gate 		mdb_snprintf(exp_csum, 8, "%u", csum);
11250Sstevel@tonic-gate 	} else {
11260Sstevel@tonic-gate 		mdb_snprintf(exp_csum, 8, "<n/a>");
11270Sstevel@tonic-gate 	}
11280Sstevel@tonic-gate 
11290Sstevel@tonic-gate 	mdb_printf("%-34I %-34I%\n"
11300Sstevel@tonic-gate 	    "%-4d %-4d %-5hu %-5hu %-6hu %-5hu %-5hu %-6u %-8s <%5hb>\n",
11310Sstevel@tonic-gate 	    iph->ipha_src, iph->ipha_dst,
11320Sstevel@tonic-gate 	    hdrlen, iph->ipha_type_of_service, totlen, ipid,
11330Sstevel@tonic-gate 	    (off << 3) & 0xffff, iph->ipha_ttl, iph->ipha_protocol,
11340Sstevel@tonic-gate 	    iph->ipha_hdr_checksum, exp_csum, off, ip_flags);
11350Sstevel@tonic-gate 
11360Sstevel@tonic-gate 	if (verbose) {
11370Sstevel@tonic-gate 		nxt_proto = addr + hdrlen;
11380Sstevel@tonic-gate 		return (transport_hdr(iph->ipha_protocol, nxt_proto));
11390Sstevel@tonic-gate 	} else {
11400Sstevel@tonic-gate 		return (DCMD_OK);
11410Sstevel@tonic-gate 	}
11420Sstevel@tonic-gate }
11430Sstevel@tonic-gate 
11440Sstevel@tonic-gate /* ARGSUSED */
11450Sstevel@tonic-gate static int
11460Sstevel@tonic-gate ip6hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11470Sstevel@tonic-gate {
11480Sstevel@tonic-gate 	uint_t		verbose = FALSE, force = FALSE;
11490Sstevel@tonic-gate 	ip6_t		iph[1];
11500Sstevel@tonic-gate 	int		ver, class, flow;
11510Sstevel@tonic-gate 	uint16_t	plen;
11520Sstevel@tonic-gate 	uintptr_t	nxt_proto;
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
11550Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
11560Sstevel@tonic-gate 	    'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc)
11570Sstevel@tonic-gate 		return (DCMD_USAGE);
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate 	if (mdb_vread(iph, sizeof (*iph), addr) == -1) {
11600Sstevel@tonic-gate 		mdb_warn("failed to read IPv6 header at %p", addr);
11610Sstevel@tonic-gate 		return (DCMD_ERR);
11620Sstevel@tonic-gate 	}
11630Sstevel@tonic-gate 
11640Sstevel@tonic-gate 	ver = (iph->ip6_vfc & 0xf0) >> 4;
11650Sstevel@tonic-gate 	if (ver != IPV6_VERSION) {
11660Sstevel@tonic-gate 		if (ver == IPV4_VERSION) {
11670Sstevel@tonic-gate 			return (iphdr(addr, flags, argc, argv));
11680Sstevel@tonic-gate 		} else if (!force) {
11690Sstevel@tonic-gate 			mdb_warn("unknown IP version: %d\n", ver);
11700Sstevel@tonic-gate 			return (DCMD_ERR);
11710Sstevel@tonic-gate 		}
11720Sstevel@tonic-gate 	}
11730Sstevel@tonic-gate 
11740Sstevel@tonic-gate 	mdb_printf("%<b>IPv6 header%</b>\n");
11750Sstevel@tonic-gate 	mdb_printf("%<u>%-26s %-26s %4s %7s %5s %3s %3s%</u>\n",
11760Sstevel@tonic-gate 	    "SRC", "DST", "TCLS", "FLOW-ID", "PLEN", "NXT", "HOP");
11770Sstevel@tonic-gate 
11780Sstevel@tonic-gate 	class = (iph->ip6_vcf & IPV6_FLOWINFO_TCLASS) >> 20;
11790Sstevel@tonic-gate 	mdb_nhconvert(&class, &class, sizeof (class));
11800Sstevel@tonic-gate 	flow = iph->ip6_vcf & IPV6_FLOWINFO_FLOWLABEL;
11810Sstevel@tonic-gate 	mdb_nhconvert(&flow, &flow, sizeof (flow));
11820Sstevel@tonic-gate 	mdb_nhconvert(&plen, &iph->ip6_plen, sizeof (plen));
11830Sstevel@tonic-gate 
11840Sstevel@tonic-gate 	mdb_printf("%-26N %-26N %4d %7d %5hu %3d %3d\n",
11850Sstevel@tonic-gate 	    &iph->ip6_src, &iph->ip6_dst,
11860Sstevel@tonic-gate 	    class, flow, plen, iph->ip6_nxt, iph->ip6_hlim);
11870Sstevel@tonic-gate 
11880Sstevel@tonic-gate 	if (verbose) {
11890Sstevel@tonic-gate 		nxt_proto = addr + sizeof (ip6_t);
11900Sstevel@tonic-gate 		return (transport_hdr(iph->ip6_nxt, nxt_proto));
11910Sstevel@tonic-gate 	} else {
11920Sstevel@tonic-gate 		return (DCMD_OK);
11930Sstevel@tonic-gate 	}
11940Sstevel@tonic-gate }
11950Sstevel@tonic-gate 
11960Sstevel@tonic-gate int
1197*11042SErik.Nordmark@Sun.COM nce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1198*11042SErik.Nordmark@Sun.COM {
1199*11042SErik.Nordmark@Sun.COM 	nce_t nce;
1200*11042SErik.Nordmark@Sun.COM 	nce_cbdata_t nce_cb;
1201*11042SErik.Nordmark@Sun.COM 	int ipversion = 0;
1202*11042SErik.Nordmark@Sun.COM 	const char *opt_P = NULL, *opt_ill;
1203*11042SErik.Nordmark@Sun.COM 
1204*11042SErik.Nordmark@Sun.COM 	if (mdb_getopts(argc, argv,
1205*11042SErik.Nordmark@Sun.COM 	    'i', MDB_OPT_STR, &opt_ill,
1206*11042SErik.Nordmark@Sun.COM 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
1207*11042SErik.Nordmark@Sun.COM 		return (DCMD_USAGE);
1208*11042SErik.Nordmark@Sun.COM 
1209*11042SErik.Nordmark@Sun.COM 	if (opt_P != NULL) {
1210*11042SErik.Nordmark@Sun.COM 		if (strcmp("v4", opt_P) == 0) {
1211*11042SErik.Nordmark@Sun.COM 			ipversion = IPV4_VERSION;
1212*11042SErik.Nordmark@Sun.COM 		} else if (strcmp("v6", opt_P) == 0) {
1213*11042SErik.Nordmark@Sun.COM 			ipversion = IPV6_VERSION;
1214*11042SErik.Nordmark@Sun.COM 		} else {
1215*11042SErik.Nordmark@Sun.COM 			mdb_warn("invalid protocol '%s'\n", opt_P);
1216*11042SErik.Nordmark@Sun.COM 			return (DCMD_USAGE);
1217*11042SErik.Nordmark@Sun.COM 		}
1218*11042SErik.Nordmark@Sun.COM 	}
1219*11042SErik.Nordmark@Sun.COM 
1220*11042SErik.Nordmark@Sun.COM 	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
1221*11042SErik.Nordmark@Sun.COM 		mdb_printf("%<u>%?s %5s %18s %?s %s %s %</u>\n",
1222*11042SErik.Nordmark@Sun.COM 		    "ADDR", "INTF", "LLADDR", "FP_MP", "REFCNT",
1223*11042SErik.Nordmark@Sun.COM 		    "NCE_ADDR");
1224*11042SErik.Nordmark@Sun.COM 	}
1225*11042SErik.Nordmark@Sun.COM 
1226*11042SErik.Nordmark@Sun.COM 	bzero(&nce_cb, sizeof (nce_cb));
1227*11042SErik.Nordmark@Sun.COM 	if (opt_ill != NULL) {
1228*11042SErik.Nordmark@Sun.COM 		strcpy(nce_cb.nce_ill_name, opt_ill);
1229*11042SErik.Nordmark@Sun.COM 	}
1230*11042SErik.Nordmark@Sun.COM 	nce_cb.nce_ipversion = ipversion;
1231*11042SErik.Nordmark@Sun.COM 
1232*11042SErik.Nordmark@Sun.COM 	if (flags & DCMD_ADDRSPEC) {
1233*11042SErik.Nordmark@Sun.COM 		(void) mdb_vread(&nce, sizeof (nce_t), addr);
1234*11042SErik.Nordmark@Sun.COM 		(void) nce_format(addr, &nce, &nce_cb);
1235*11042SErik.Nordmark@Sun.COM 	} else if (mdb_walk("nce", (mdb_walk_cb_t)nce_format, &nce_cb) == -1) {
1236*11042SErik.Nordmark@Sun.COM 		mdb_warn("failed to walk ire table");
1237*11042SErik.Nordmark@Sun.COM 		return (DCMD_ERR);
1238*11042SErik.Nordmark@Sun.COM 	}
1239*11042SErik.Nordmark@Sun.COM 
1240*11042SErik.Nordmark@Sun.COM 	return (DCMD_OK);
1241*11042SErik.Nordmark@Sun.COM }
1242*11042SErik.Nordmark@Sun.COM 
1243*11042SErik.Nordmark@Sun.COM /* ARGSUSED */
1244*11042SErik.Nordmark@Sun.COM static int
1245*11042SErik.Nordmark@Sun.COM dce_format(uintptr_t addr, const dce_t *dcep, void *dce_cb_arg)
1246*11042SErik.Nordmark@Sun.COM {
1247*11042SErik.Nordmark@Sun.COM 	static const mdb_bitmask_t dmasks[] = {
1248*11042SErik.Nordmark@Sun.COM 		{ "D",	DCEF_DEFAULT,		DCEF_DEFAULT },
1249*11042SErik.Nordmark@Sun.COM 		{ "P",	DCEF_PMTU,		DCEF_PMTU },
1250*11042SErik.Nordmark@Sun.COM 		{ "U",	DCEF_UINFO,		DCEF_UINFO },
1251*11042SErik.Nordmark@Sun.COM 		{ "S",	DCEF_TOO_SMALL_PMTU,	DCEF_TOO_SMALL_PMTU },
1252*11042SErik.Nordmark@Sun.COM 		{ NULL,	0,			0		}
1253*11042SErik.Nordmark@Sun.COM 	};
1254*11042SErik.Nordmark@Sun.COM 	char flagsbuf[2 * A_CNT(dmasks)];
1255*11042SErik.Nordmark@Sun.COM 	int ipversion = *(int *)dce_cb_arg;
1256*11042SErik.Nordmark@Sun.COM 	boolean_t condemned = dcep->dce_generation == DCE_GENERATION_CONDEMNED;
1257*11042SErik.Nordmark@Sun.COM 
1258*11042SErik.Nordmark@Sun.COM 	if (ipversion != 0 && ipversion != dcep->dce_ipversion)
1259*11042SErik.Nordmark@Sun.COM 		return (WALK_NEXT);
1260*11042SErik.Nordmark@Sun.COM 
1261*11042SErik.Nordmark@Sun.COM 	mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%b", dcep->dce_flags,
1262*11042SErik.Nordmark@Sun.COM 	    dmasks);
1263*11042SErik.Nordmark@Sun.COM 
1264*11042SErik.Nordmark@Sun.COM 	switch (dcep->dce_ipversion) {
1265*11042SErik.Nordmark@Sun.COM 	case IPV4_VERSION:
1266*11042SErik.Nordmark@Sun.COM 		mdb_printf("%<u>%?p%3s %8s %8d %30I %</u>\n", addr, condemned ?
1267*11042SErik.Nordmark@Sun.COM 		    "(C)" : "", flagsbuf, dcep->dce_pmtu, &dcep->dce_v4addr);
1268*11042SErik.Nordmark@Sun.COM 		break;
1269*11042SErik.Nordmark@Sun.COM 	case IPV6_VERSION:
1270*11042SErik.Nordmark@Sun.COM 		mdb_printf("%<u>%?p%3s %8s %8d %30N %</u>\n", addr, condemned ?
1271*11042SErik.Nordmark@Sun.COM 		    "(C)" : "", flagsbuf, dcep->dce_pmtu, &dcep->dce_v6addr);
1272*11042SErik.Nordmark@Sun.COM 		break;
1273*11042SErik.Nordmark@Sun.COM 	default:
1274*11042SErik.Nordmark@Sun.COM 		mdb_printf("%<u>%?p%3s %8s %8d %30s %</u>\n", addr, condemned ?
1275*11042SErik.Nordmark@Sun.COM 		    "(C)" : "", flagsbuf, dcep->dce_pmtu, "");
1276*11042SErik.Nordmark@Sun.COM 	}
1277*11042SErik.Nordmark@Sun.COM 
1278*11042SErik.Nordmark@Sun.COM 	return (WALK_NEXT);
1279*11042SErik.Nordmark@Sun.COM }
1280*11042SErik.Nordmark@Sun.COM 
1281*11042SErik.Nordmark@Sun.COM int
1282*11042SErik.Nordmark@Sun.COM dce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1283*11042SErik.Nordmark@Sun.COM {
1284*11042SErik.Nordmark@Sun.COM 	dce_t dce;
1285*11042SErik.Nordmark@Sun.COM 	const char *opt_P = NULL;
1286*11042SErik.Nordmark@Sun.COM 	const char *zone_name = NULL;
1287*11042SErik.Nordmark@Sun.COM 	ip_stack_t *ipst = NULL;
1288*11042SErik.Nordmark@Sun.COM 	int ipversion = 0;
1289*11042SErik.Nordmark@Sun.COM 
1290*11042SErik.Nordmark@Sun.COM 	if (mdb_getopts(argc, argv,
1291*11042SErik.Nordmark@Sun.COM 	    's', MDB_OPT_STR, &zone_name,
1292*11042SErik.Nordmark@Sun.COM 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
1293*11042SErik.Nordmark@Sun.COM 		return (DCMD_USAGE);
1294*11042SErik.Nordmark@Sun.COM 
1295*11042SErik.Nordmark@Sun.COM 	/* Follow the specified zone name to find a ip_stack_t*. */
1296*11042SErik.Nordmark@Sun.COM 	if (zone_name != NULL) {
1297*11042SErik.Nordmark@Sun.COM 		ipst = zone_to_ips(zone_name);
1298*11042SErik.Nordmark@Sun.COM 		if (ipst == NULL)
1299*11042SErik.Nordmark@Sun.COM 			return (DCMD_USAGE);
1300*11042SErik.Nordmark@Sun.COM 	}
1301*11042SErik.Nordmark@Sun.COM 
1302*11042SErik.Nordmark@Sun.COM 	if (opt_P != NULL) {
1303*11042SErik.Nordmark@Sun.COM 		if (strcmp("v4", opt_P) == 0) {
1304*11042SErik.Nordmark@Sun.COM 			ipversion = IPV4_VERSION;
1305*11042SErik.Nordmark@Sun.COM 		} else if (strcmp("v6", opt_P) == 0) {
1306*11042SErik.Nordmark@Sun.COM 			ipversion = IPV6_VERSION;
1307*11042SErik.Nordmark@Sun.COM 		} else {
1308*11042SErik.Nordmark@Sun.COM 			mdb_warn("invalid protocol '%s'\n", opt_P);
1309*11042SErik.Nordmark@Sun.COM 			return (DCMD_USAGE);
1310*11042SErik.Nordmark@Sun.COM 		}
1311*11042SErik.Nordmark@Sun.COM 	}
1312*11042SErik.Nordmark@Sun.COM 
1313*11042SErik.Nordmark@Sun.COM 	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
1314*11042SErik.Nordmark@Sun.COM 		mdb_printf("%<u>%?s%3s %8s %8s %30s %</u>\n",
1315*11042SErik.Nordmark@Sun.COM 		    "ADDR", "", "FLAGS", "PMTU", "DST_ADDR");
1316*11042SErik.Nordmark@Sun.COM 	}
1317*11042SErik.Nordmark@Sun.COM 
1318*11042SErik.Nordmark@Sun.COM 	if (flags & DCMD_ADDRSPEC) {
1319*11042SErik.Nordmark@Sun.COM 		(void) mdb_vread(&dce, sizeof (dce_t), addr);
1320*11042SErik.Nordmark@Sun.COM 		(void) dce_format(addr, &dce, &ipversion);
1321*11042SErik.Nordmark@Sun.COM 	} else if (mdb_pwalk("dce", (mdb_walk_cb_t)dce_format, &ipversion,
1322*11042SErik.Nordmark@Sun.COM 	    (uintptr_t)ipst) == -1) {
1323*11042SErik.Nordmark@Sun.COM 		mdb_warn("failed to walk dce cache");
1324*11042SErik.Nordmark@Sun.COM 		return (DCMD_ERR);
1325*11042SErik.Nordmark@Sun.COM 	}
1326*11042SErik.Nordmark@Sun.COM 
1327*11042SErik.Nordmark@Sun.COM 	return (DCMD_OK);
1328*11042SErik.Nordmark@Sun.COM }
1329*11042SErik.Nordmark@Sun.COM 
1330*11042SErik.Nordmark@Sun.COM int
13310Sstevel@tonic-gate ire(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
13320Sstevel@tonic-gate {
13330Sstevel@tonic-gate 	uint_t verbose = FALSE;
13340Sstevel@tonic-gate 	ire_t ire;
13355940Ssowmini 	ire_cbdata_t ire_cb;
13365940Ssowmini 	int ipversion = 0;
13375940Ssowmini 	const char *opt_P = NULL;
1338*11042SErik.Nordmark@Sun.COM 	const char *zone_name = NULL;
1339*11042SErik.Nordmark@Sun.COM 	ip_stack_t *ipst = NULL;
13400Sstevel@tonic-gate 
13410Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
13425940Ssowmini 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
1343*11042SErik.Nordmark@Sun.COM 	    's', MDB_OPT_STR, &zone_name,
13445940Ssowmini 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
13450Sstevel@tonic-gate 		return (DCMD_USAGE);
13460Sstevel@tonic-gate 
1347*11042SErik.Nordmark@Sun.COM 	/* Follow the specified zone name to find a ip_stack_t*. */
1348*11042SErik.Nordmark@Sun.COM 	if (zone_name != NULL) {
1349*11042SErik.Nordmark@Sun.COM 		ipst = zone_to_ips(zone_name);
1350*11042SErik.Nordmark@Sun.COM 		if (ipst == NULL)
1351*11042SErik.Nordmark@Sun.COM 			return (DCMD_USAGE);
1352*11042SErik.Nordmark@Sun.COM 	}
1353*11042SErik.Nordmark@Sun.COM 
13545940Ssowmini 	if (opt_P != NULL) {
13555940Ssowmini 		if (strcmp("v4", opt_P) == 0) {
13565940Ssowmini 			ipversion = IPV4_VERSION;
13575940Ssowmini 		} else if (strcmp("v6", opt_P) == 0) {
13585940Ssowmini 			ipversion = IPV6_VERSION;
13595940Ssowmini 		} else {
13605940Ssowmini 			mdb_warn("invalid protocol '%s'\n", opt_P);
13615940Ssowmini 			return (DCMD_USAGE);
13625940Ssowmini 		}
13635940Ssowmini 	}
13645940Ssowmini 
13650Sstevel@tonic-gate 	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
13660Sstevel@tonic-gate 
13670Sstevel@tonic-gate 		if (verbose) {
13680Sstevel@tonic-gate 			mdb_printf("%?s %40s %-20s%\n"
13690Sstevel@tonic-gate 			    "%?s %40s %-20s%\n"
1370*11042SErik.Nordmark@Sun.COM 			    "%<u>%?s %40s %4s %-20s %s%</u>\n",
13710Sstevel@tonic-gate 			    "ADDR", "SRC", "TYPE",
13720Sstevel@tonic-gate 			    "", "DST", "MARKS",
1373*11042SErik.Nordmark@Sun.COM 			    "", "STACK", "ZONE", "FLAGS", "INTF");
13740Sstevel@tonic-gate 		} else {
1375*11042SErik.Nordmark@Sun.COM 			mdb_printf("%<u>%?s %30s %30s %5s %4s %s%</u>\n",
1376*11042SErik.Nordmark@Sun.COM 			    "ADDR", "SRC", "DST", "STACK", "ZONE", "INTF");
13770Sstevel@tonic-gate 		}
13780Sstevel@tonic-gate 	}
13790Sstevel@tonic-gate 
13805940Ssowmini 	ire_cb.verbose = (verbose == TRUE);
13815940Ssowmini 	ire_cb.ire_ipversion = ipversion;
13825940Ssowmini 
13830Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC) {
13840Sstevel@tonic-gate 		(void) mdb_vread(&ire, sizeof (ire_t), addr);
13855940Ssowmini 		(void) ire_format(addr, &ire, &ire_cb);
1386*11042SErik.Nordmark@Sun.COM 	} else if (mdb_pwalk("ire", (mdb_walk_cb_t)ire_format, &ire_cb,
1387*11042SErik.Nordmark@Sun.COM 	    (uintptr_t)ipst) == -1) {
13880Sstevel@tonic-gate 		mdb_warn("failed to walk ire table");
13890Sstevel@tonic-gate 		return (DCMD_ERR);
13900Sstevel@tonic-gate 	}
13910Sstevel@tonic-gate 
13920Sstevel@tonic-gate 	return (DCMD_OK);
13930Sstevel@tonic-gate }
13940Sstevel@tonic-gate 
13950Sstevel@tonic-gate static size_t
13960Sstevel@tonic-gate mi_osize(const queue_t *q)
13970Sstevel@tonic-gate {
13980Sstevel@tonic-gate 	/*
13990Sstevel@tonic-gate 	 * The code in common/inet/mi.c allocates an extra word to store the
14000Sstevel@tonic-gate 	 * size of the allocation.  An mi_o_s is thus a size_t plus an mi_o_s.
14010Sstevel@tonic-gate 	 */
14020Sstevel@tonic-gate 	struct mi_block {
14030Sstevel@tonic-gate 		size_t mi_nbytes;
14040Sstevel@tonic-gate 		struct mi_o_s mi_o;
14050Sstevel@tonic-gate 	} m;
14060Sstevel@tonic-gate 
14070Sstevel@tonic-gate 	if (mdb_vread(&m, sizeof (m), (uintptr_t)q->q_ptr -
14080Sstevel@tonic-gate 	    sizeof (m)) == sizeof (m))
14090Sstevel@tonic-gate 		return (m.mi_nbytes - sizeof (m));
14100Sstevel@tonic-gate 
14110Sstevel@tonic-gate 	return (0);
14120Sstevel@tonic-gate }
14130Sstevel@tonic-gate 
14140Sstevel@tonic-gate static void
14150Sstevel@tonic-gate ip_ill_qinfo(const queue_t *q, char *buf, size_t nbytes)
14160Sstevel@tonic-gate {
14170Sstevel@tonic-gate 	char name[32];
14180Sstevel@tonic-gate 	ill_t ill;
14190Sstevel@tonic-gate 
14200Sstevel@tonic-gate 	if (mdb_vread(&ill, sizeof (ill),
14210Sstevel@tonic-gate 	    (uintptr_t)q->q_ptr) == sizeof (ill) &&
14220Sstevel@tonic-gate 	    mdb_readstr(name, sizeof (name), (uintptr_t)ill.ill_name) > 0)
14230Sstevel@tonic-gate 		(void) mdb_snprintf(buf, nbytes, "if: %s", name);
14240Sstevel@tonic-gate }
14250Sstevel@tonic-gate 
14260Sstevel@tonic-gate void
14270Sstevel@tonic-gate ip_qinfo(const queue_t *q, char *buf, size_t nbytes)
14280Sstevel@tonic-gate {
14290Sstevel@tonic-gate 	size_t size = mi_osize(q);
14300Sstevel@tonic-gate 
14310Sstevel@tonic-gate 	if (size == sizeof (ill_t))
14320Sstevel@tonic-gate 		ip_ill_qinfo(q, buf, nbytes);
14330Sstevel@tonic-gate }
14340Sstevel@tonic-gate 
14350Sstevel@tonic-gate uintptr_t
14360Sstevel@tonic-gate ip_rnext(const queue_t *q)
14370Sstevel@tonic-gate {
14380Sstevel@tonic-gate 	size_t size = mi_osize(q);
14390Sstevel@tonic-gate 	ill_t ill;
14400Sstevel@tonic-gate 
14410Sstevel@tonic-gate 	if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill),
14420Sstevel@tonic-gate 	    (uintptr_t)q->q_ptr) == sizeof (ill))
14430Sstevel@tonic-gate 		return ((uintptr_t)ill.ill_rq);
14440Sstevel@tonic-gate 
14450Sstevel@tonic-gate 	return (NULL);
14460Sstevel@tonic-gate }
14470Sstevel@tonic-gate 
14480Sstevel@tonic-gate uintptr_t
14490Sstevel@tonic-gate ip_wnext(const queue_t *q)
14500Sstevel@tonic-gate {
14510Sstevel@tonic-gate 	size_t size = mi_osize(q);
14520Sstevel@tonic-gate 	ill_t ill;
14530Sstevel@tonic-gate 
14540Sstevel@tonic-gate 	if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill),
14550Sstevel@tonic-gate 	    (uintptr_t)q->q_ptr) == sizeof (ill))
14560Sstevel@tonic-gate 		return ((uintptr_t)ill.ill_wq);
14570Sstevel@tonic-gate 
14580Sstevel@tonic-gate 	return (NULL);
14590Sstevel@tonic-gate }
14600Sstevel@tonic-gate 
14610Sstevel@tonic-gate /*
14620Sstevel@tonic-gate  * Print the core fields in an squeue_t.  With the "-v" argument,
14630Sstevel@tonic-gate  * provide more verbose output.
14640Sstevel@tonic-gate  */
14650Sstevel@tonic-gate static int
14660Sstevel@tonic-gate squeue(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14670Sstevel@tonic-gate {
14680Sstevel@tonic-gate 	unsigned int	i;
14690Sstevel@tonic-gate 	unsigned int	verbose = FALSE;
14700Sstevel@tonic-gate 	const int	SQUEUE_STATEDELT = (int)(sizeof (uintptr_t) + 9);
14710Sstevel@tonic-gate 	boolean_t	arm;
14720Sstevel@tonic-gate 	squeue_t	squeue;
14730Sstevel@tonic-gate 
14740Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
14750Sstevel@tonic-gate 		if (mdb_walk_dcmd("genunix`squeue_cache", "ip`squeue",
14760Sstevel@tonic-gate 		    argc, argv) == -1) {
14770Sstevel@tonic-gate 			mdb_warn("failed to walk squeue cache");
14780Sstevel@tonic-gate 			return (DCMD_ERR);
14790Sstevel@tonic-gate 		}
14800Sstevel@tonic-gate 		return (DCMD_OK);
14810Sstevel@tonic-gate 	}
14820Sstevel@tonic-gate 
14830Sstevel@tonic-gate 	if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL)
14840Sstevel@tonic-gate 	    != argc)
14850Sstevel@tonic-gate 		return (DCMD_USAGE);
14860Sstevel@tonic-gate 
14870Sstevel@tonic-gate 	if (!DCMD_HDRSPEC(flags) && verbose)
14880Sstevel@tonic-gate 		mdb_printf("\n\n");
14890Sstevel@tonic-gate 
14900Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) || verbose) {
14910Sstevel@tonic-gate 		mdb_printf("%?s %-5s %-3s %?s %?s %?s\n",
14920Sstevel@tonic-gate 		    "ADDR", "STATE", "CPU",
14930Sstevel@tonic-gate 		    "FIRST", "LAST", "WORKER");
14940Sstevel@tonic-gate 	}
14950Sstevel@tonic-gate 
14960Sstevel@tonic-gate 	if (mdb_vread(&squeue, sizeof (squeue_t), addr) == -1) {
14970Sstevel@tonic-gate 		mdb_warn("cannot read squeue_t at %p", addr);
14980Sstevel@tonic-gate 		return (DCMD_ERR);
14990Sstevel@tonic-gate 	}
15000Sstevel@tonic-gate 
15010Sstevel@tonic-gate 	mdb_printf("%0?p %05x %3d %0?p %0?p %0?p\n",
15020Sstevel@tonic-gate 	    addr, squeue.sq_state, squeue.sq_bind,
15030Sstevel@tonic-gate 	    squeue.sq_first, squeue.sq_last, squeue.sq_worker);
15040Sstevel@tonic-gate 
15050Sstevel@tonic-gate 	if (!verbose)
15060Sstevel@tonic-gate 		return (DCMD_OK);
15070Sstevel@tonic-gate 
15080Sstevel@tonic-gate 	arm = B_TRUE;
15090Sstevel@tonic-gate 	for (i = 0; squeue_states[i].bit_name != NULL; i++) {
15100Sstevel@tonic-gate 		if (((squeue.sq_state) & (1 << i)) == 0)
15110Sstevel@tonic-gate 			continue;
15120Sstevel@tonic-gate 
15130Sstevel@tonic-gate 		if (arm) {
15140Sstevel@tonic-gate 			mdb_printf("%*s|\n", SQUEUE_STATEDELT, "");
15150Sstevel@tonic-gate 			mdb_printf("%*s+-->  ", SQUEUE_STATEDELT, "");
15160Sstevel@tonic-gate 			arm = B_FALSE;
15170Sstevel@tonic-gate 		} else
15180Sstevel@tonic-gate 			mdb_printf("%*s      ", SQUEUE_STATEDELT, "");
15190Sstevel@tonic-gate 
15200Sstevel@tonic-gate 		mdb_printf("%-12s %s\n", squeue_states[i].bit_name,
15210Sstevel@tonic-gate 		    squeue_states[i].bit_descr);
15220Sstevel@tonic-gate 	}
15230Sstevel@tonic-gate 
15240Sstevel@tonic-gate 	return (DCMD_OK);
15250Sstevel@tonic-gate }
15260Sstevel@tonic-gate 
15270Sstevel@tonic-gate static void
15280Sstevel@tonic-gate ip_squeue_help(void)
15290Sstevel@tonic-gate {
15300Sstevel@tonic-gate 	mdb_printf("Print the core information for a given NCA squeue_t.\n\n");
15310Sstevel@tonic-gate 	mdb_printf("Options:\n");
15320Sstevel@tonic-gate 	mdb_printf("\t-v\tbe verbose (more descriptive)\n");
15330Sstevel@tonic-gate }
15340Sstevel@tonic-gate 
15355023Scarlsonj /*
15365023Scarlsonj  * This is called by ::th_trace (via a callback) when walking the th_hash
15375023Scarlsonj  * list.  It calls modent to find the entries.
15385023Scarlsonj  */
15395023Scarlsonj /* ARGSUSED */
15405023Scarlsonj static int
15415023Scarlsonj modent_summary(uintptr_t addr, const void *data, void *private)
15425023Scarlsonj {
15435023Scarlsonj 	th_walk_data_t *thw = private;
15445023Scarlsonj 	const struct mod_hash_entry *mhe = data;
15455023Scarlsonj 	th_trace_t th;
15465023Scarlsonj 
15475023Scarlsonj 	if (mdb_vread(&th, sizeof (th), (uintptr_t)mhe->mhe_val) == -1) {
15485023Scarlsonj 		mdb_warn("failed to read th_trace_t %p", mhe->mhe_val);
15495023Scarlsonj 		return (WALK_ERR);
15505023Scarlsonj 	}
15515023Scarlsonj 
15525023Scarlsonj 	if (th.th_refcnt == 0 && thw->thw_non_zero_only)
15535023Scarlsonj 		return (WALK_NEXT);
15545023Scarlsonj 
15555023Scarlsonj 	if (!thw->thw_match) {
15565023Scarlsonj 		mdb_printf("%?p %?p %?p %8d %?p\n", thw->thw_ipst, mhe->mhe_key,
15575023Scarlsonj 		    mhe->mhe_val, th.th_refcnt, th.th_id);
15585023Scarlsonj 	} else if (thw->thw_matchkey == (uintptr_t)mhe->mhe_key) {
15595023Scarlsonj 		int i, j, k;
15605023Scarlsonj 		tr_buf_t *tr;
15615023Scarlsonj 
15625023Scarlsonj 		mdb_printf("Object %p in IP stack %p:\n", mhe->mhe_key,
15635023Scarlsonj 		    thw->thw_ipst);
15645023Scarlsonj 		i = th.th_trace_lastref;
15655023Scarlsonj 		mdb_printf("\tThread %p refcnt %d:\n", th.th_id,
15665023Scarlsonj 		    th.th_refcnt);
15675023Scarlsonj 		for (j = TR_BUF_MAX; j > 0; j--) {
15685023Scarlsonj 			tr = th.th_trbuf + i;
15695023Scarlsonj 			if (tr->tr_depth == 0 || tr->tr_depth > TR_STACK_DEPTH)
15705023Scarlsonj 				break;
15715023Scarlsonj 			mdb_printf("\t  T%+ld:\n", tr->tr_time -
15725023Scarlsonj 			    thw->thw_lbolt);
15735023Scarlsonj 			for (k = 0; k < tr->tr_depth; k++)
15745023Scarlsonj 				mdb_printf("\t\t%a\n", tr->tr_stack[k]);
15755023Scarlsonj 			if (--i < 0)
15765023Scarlsonj 				i = TR_BUF_MAX - 1;
15775023Scarlsonj 		}
15785023Scarlsonj 	}
15795023Scarlsonj 	return (WALK_NEXT);
15805023Scarlsonj }
15815023Scarlsonj 
15825023Scarlsonj /*
15835023Scarlsonj  * This is called by ::th_trace (via a callback) when walking the th_hash
15845023Scarlsonj  * list.  It calls modent to find the entries.
15855023Scarlsonj  */
15865023Scarlsonj /* ARGSUSED */
15875023Scarlsonj static int
15885023Scarlsonj th_hash_summary(uintptr_t addr, const void *data, void *private)
15895023Scarlsonj {
15905023Scarlsonj 	const th_hash_t *thh = data;
15915023Scarlsonj 	th_walk_data_t *thw = private;
15925023Scarlsonj 
15935023Scarlsonj 	thw->thw_ipst = (uintptr_t)thh->thh_ipst;
15945023Scarlsonj 	return (mdb_pwalk("modent", modent_summary, private,
15955023Scarlsonj 	    (uintptr_t)thh->thh_hash));
15965023Scarlsonj }
15975023Scarlsonj 
15985023Scarlsonj /*
15995023Scarlsonj  * Print or summarize the th_trace_t structures.
16005023Scarlsonj  */
16015023Scarlsonj static int
16025023Scarlsonj th_trace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
16035023Scarlsonj {
16045023Scarlsonj 	th_walk_data_t thw;
16055023Scarlsonj 
16065023Scarlsonj 	(void) memset(&thw, 0, sizeof (thw));
16075023Scarlsonj 
16085023Scarlsonj 	if (mdb_getopts(argc, argv,
16095023Scarlsonj 	    'n', MDB_OPT_SETBITS, TRUE, &thw.thw_non_zero_only,
16105023Scarlsonj 	    NULL) != argc)
16115023Scarlsonj 		return (DCMD_USAGE);
16125023Scarlsonj 
16135023Scarlsonj 	if (!(flags & DCMD_ADDRSPEC)) {
16145023Scarlsonj 		/*
16155023Scarlsonj 		 * No address specified.  Walk all of the th_hash_t in the
16165023Scarlsonj 		 * system, and summarize the th_trace_t entries in each.
16175023Scarlsonj 		 */
16185023Scarlsonj 		mdb_printf("%?s %?s %?s %8s %?s\n",
16195023Scarlsonj 		    "IPSTACK", "OBJECT", "TRACE", "REFCNT", "THREAD");
16205023Scarlsonj 		thw.thw_match = B_FALSE;
16215023Scarlsonj 	} else {
16225023Scarlsonj 		thw.thw_match = B_TRUE;
16235023Scarlsonj 		thw.thw_matchkey = addr;
16245023Scarlsonj 		if (mdb_readvar(&thw.thw_lbolt,
16255023Scarlsonj 		    mdb_prop_postmortem ? "panic_lbolt" : "lbolt") == -1) {
16265023Scarlsonj 			mdb_warn("failed to read lbolt");
16275023Scarlsonj 			return (DCMD_ERR);
16285023Scarlsonj 		}
16295023Scarlsonj 	}
16305023Scarlsonj 	if (mdb_pwalk("th_hash", th_hash_summary, &thw, NULL) == -1) {
16315023Scarlsonj 		mdb_warn("can't walk th_hash entries");
16325023Scarlsonj 		return (DCMD_ERR);
16335023Scarlsonj 	}
16345023Scarlsonj 	return (DCMD_OK);
16355023Scarlsonj }
16365023Scarlsonj 
16375023Scarlsonj static void
16385023Scarlsonj th_trace_help(void)
16395023Scarlsonj {
1640*11042SErik.Nordmark@Sun.COM 	mdb_printf("If given an address of an ill_t, ipif_t, ire_t, or ncec_t, "
16415023Scarlsonj 	    "print the\n"
16425023Scarlsonj 	    "corresponding th_trace_t structure in detail.  Otherwise, if no "
16435023Scarlsonj 	    "address is\n"
16445023Scarlsonj 	    "given, then summarize all th_trace_t structures.\n\n");
16455023Scarlsonj 	mdb_printf("Options:\n"
16465023Scarlsonj 	    "\t-n\tdisplay only entries with non-zero th_refcnt\n");
16475023Scarlsonj }
16485023Scarlsonj 
16490Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = {
16509089SVasumathi.Sundaram@Sun.COM 	{ "conn_status", ":",
16519089SVasumathi.Sundaram@Sun.COM 	    "display connection structures from ipcl hash tables",
16529089SVasumathi.Sundaram@Sun.COM 	    conn_status, conn_status_help },
16539089SVasumathi.Sundaram@Sun.COM 	{ "srcid_status", ":",
16549089SVasumathi.Sundaram@Sun.COM 	    "display connection structures from ipcl hash tables",
16559089SVasumathi.Sundaram@Sun.COM 	    srcid_status },
1656*11042SErik.Nordmark@Sun.COM 	{ "ill", "?[-v] [-P v4 | v6] [-s exclusive-ip-zone-name]",
1657*11042SErik.Nordmark@Sun.COM 	    "display ill_t structures", ill, ill_help },
16580Sstevel@tonic-gate 	{ "illif", "?[-P v4 | v6]",
16590Sstevel@tonic-gate 	    "display or filter IP Lower Level InterFace structures", illif,
16600Sstevel@tonic-gate 	    illif_help },
16610Sstevel@tonic-gate 	{ "iphdr", ":[-vf]", "display an IPv4 header", iphdr },
16620Sstevel@tonic-gate 	{ "ip6hdr", ":[-vf]", "display an IPv6 header", ip6hdr },
16639089SVasumathi.Sundaram@Sun.COM 	{ "ipif", "?[-v] [-P v4 | v6]", "display ipif structures",
16649089SVasumathi.Sundaram@Sun.COM 	    ipif, ipif_help },
1665*11042SErik.Nordmark@Sun.COM 	{ "ire", "?[-v] [-P v4|v6] [-s exclusive-ip-zone-name]",
16665940Ssowmini 	    "display Internet Route Entry structures", ire },
1667*11042SErik.Nordmark@Sun.COM 	{ "nce", "?[-P v4|v6] [-i <interface>]",
1668*11042SErik.Nordmark@Sun.COM 	    "display interface-specific Neighbor Cache structures", nce },
1669*11042SErik.Nordmark@Sun.COM 	{ "ncec", "?[-P v4 | v6]", "display Neighbor Cache Entry structures",
1670*11042SErik.Nordmark@Sun.COM 	    ncec },
1671*11042SErik.Nordmark@Sun.COM 	{ "dce", "?[-P v4|v6] [-s exclusive-ip-zone-name]",
1672*11042SErik.Nordmark@Sun.COM 	    "display Destination Cache Entry structures", dce },
16730Sstevel@tonic-gate 	{ "squeue", ":[-v]", "print core squeue_t info", squeue,
16740Sstevel@tonic-gate 	    ip_squeue_help },
16750Sstevel@tonic-gate 	{ "tcphdr", ":", "display a TCP header", tcphdr },
16760Sstevel@tonic-gate 	{ "udphdr", ":", "display an UDP header", udphdr },
16770Sstevel@tonic-gate 	{ "sctphdr", ":", "display an SCTP header", sctphdr },
16785023Scarlsonj 	{ "th_trace", "?[-n]", "display th_trace_t structures", th_trace,
16795023Scarlsonj 	    th_trace_help },
16800Sstevel@tonic-gate 	{ NULL }
16810Sstevel@tonic-gate };
16820Sstevel@tonic-gate 
16830Sstevel@tonic-gate static const mdb_walker_t walkers[] = {
16849089SVasumathi.Sundaram@Sun.COM 	{ "conn_status", "walk list of conn_t structures",
16859089SVasumathi.Sundaram@Sun.COM 		ip_stacks_common_walk_init, conn_status_walk_step, NULL },
16863448Sdh155122 	{ "illif", "walk list of ill interface types for all stacks",
16875940Ssowmini 		ip_stacks_common_walk_init, illif_walk_step, NULL },
16883448Sdh155122 	{ "illif_stack", "walk list of ill interface types",
16893448Sdh155122 		illif_stack_walk_init, illif_stack_walk_step,
16903448Sdh155122 		illif_stack_walk_fini },
1691*11042SErik.Nordmark@Sun.COM 	{ "ill", "walk active ill_t structures for all stacks",
16929089SVasumathi.Sundaram@Sun.COM 		ill_walk_init, ill_walk_step, NULL },
16939089SVasumathi.Sundaram@Sun.COM 	{ "ipif", "walk list of ipif structures for all stacks",
16949089SVasumathi.Sundaram@Sun.COM 		ipif_walk_init, ipif_walk_step, NULL },
16959089SVasumathi.Sundaram@Sun.COM 	{ "ipif_list", "walk the linked list of ipif structures "
16969089SVasumathi.Sundaram@Sun.COM 		"for a given ill",
16979089SVasumathi.Sundaram@Sun.COM 		ip_list_walk_init, ip_list_walk_step,
16989089SVasumathi.Sundaram@Sun.COM 		ip_list_walk_fini, &ipif_walk_arg },
16999089SVasumathi.Sundaram@Sun.COM 	{ "srcid", "walk list of srcid_map structures for all stacks",
17009089SVasumathi.Sundaram@Sun.COM 		ip_stacks_common_walk_init, srcid_walk_step, NULL },
17019089SVasumathi.Sundaram@Sun.COM 	{ "srcid_list", "walk list of srcid_map structures for a stack",
17029089SVasumathi.Sundaram@Sun.COM 		ip_list_walk_init, ip_list_walk_step, ip_list_walk_fini,
17039089SVasumathi.Sundaram@Sun.COM 		&srcid_walk_arg },
17040Sstevel@tonic-gate 	{ "ire", "walk active ire_t structures",
17050Sstevel@tonic-gate 		ire_walk_init, ire_walk_step, NULL },
17063448Sdh155122 	{ "ire_next", "walk ire_t structures in the ctable",
17073448Sdh155122 		ire_next_walk_init, ire_next_walk_step, NULL },
1708*11042SErik.Nordmark@Sun.COM 	{ "nce", "walk active nce_t structures",
1709*11042SErik.Nordmark@Sun.COM 		nce_walk_init, nce_walk_step, NULL },
1710*11042SErik.Nordmark@Sun.COM 	{ "dce", "walk active dce_t structures",
1711*11042SErik.Nordmark@Sun.COM 		dce_walk_init, dce_walk_step, NULL },
17123448Sdh155122 	{ "ip_stacks", "walk all the ip_stack_t",
17133448Sdh155122 		ip_stacks_walk_init, ip_stacks_walk_step, NULL },
17145023Scarlsonj 	{ "th_hash", "walk all the th_hash_t entries",
17155023Scarlsonj 		th_hash_walk_init, th_hash_walk_step, NULL },
1716*11042SErik.Nordmark@Sun.COM 	{ "ncec", "walk list of ncec structures for all stacks",
1717*11042SErik.Nordmark@Sun.COM 		ip_stacks_common_walk_init, ncec_walk_step, NULL },
1718*11042SErik.Nordmark@Sun.COM 	{ "ncec_stack", "walk list of ncec structures",
1719*11042SErik.Nordmark@Sun.COM 		ncec_stack_walk_init, ncec_stack_walk_step,
1720*11042SErik.Nordmark@Sun.COM 		ncec_stack_walk_fini},
17219089SVasumathi.Sundaram@Sun.COM 	{ "udp_hash", "walk list of conn_t structures in ips_ipcl_udp_fanout",
17229089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_init, ipcl_hash_walk_step,
17239089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_fini, &udp_hash_arg},
17249089SVasumathi.Sundaram@Sun.COM 	{ "conn_hash", "walk list of conn_t structures in ips_ipcl_conn_fanout",
17259089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_init, ipcl_hash_walk_step,
17269089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_fini, &conn_hash_arg},
17279089SVasumathi.Sundaram@Sun.COM 	{ "bind_hash", "walk list of conn_t structures in ips_ipcl_bind_fanout",
17289089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_init, ipcl_hash_walk_step,
17299089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_fini, &bind_hash_arg},
17309089SVasumathi.Sundaram@Sun.COM 	{ "proto_hash", "walk list of conn_t structures in "
17319089SVasumathi.Sundaram@Sun.COM 	    "ips_ipcl_proto_fanout",
17329089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_init, ipcl_hash_walk_step,
17339089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_fini, &proto_hash_arg},
17349089SVasumathi.Sundaram@Sun.COM 	{ "proto_v6_hash", "walk list of conn_t structures in "
17359089SVasumathi.Sundaram@Sun.COM 	    "ips_ipcl_proto_fanout_v6",
17369089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_init, ipcl_hash_walk_step,
17379089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_fini, &proto_v6_hash_arg},
173810946SSangeeta.Misra@Sun.COM 	{ "ilb_stacks", "walk ilb_stack_t",
173910946SSangeeta.Misra@Sun.COM 		ip_stacks_walk_init, ilb_stacks_walk_step, NULL },
174010946SSangeeta.Misra@Sun.COM 	{ "ilb_rules", "walk ilb rules in a given ilb_stack_t",
174110946SSangeeta.Misra@Sun.COM 		ilb_rules_walk_init, ilb_rules_walk_step, NULL },
174210946SSangeeta.Misra@Sun.COM 	{ "ilb_servers", "walk server in a given ilb_rule_t",
174310946SSangeeta.Misra@Sun.COM 		ilb_servers_walk_init, ilb_servers_walk_step, NULL },
174410946SSangeeta.Misra@Sun.COM 	{ "ilb_nat_src", "walk NAT source table of a given ilb_stack_t",
174510946SSangeeta.Misra@Sun.COM 		ilb_nat_src_walk_init, ilb_nat_src_walk_step,
174610946SSangeeta.Misra@Sun.COM 		ilb_common_walk_fini },
174710946SSangeeta.Misra@Sun.COM 	{ "ilb_conns", "walk NAT table of a given ilb_stack_t",
174810946SSangeeta.Misra@Sun.COM 		ilb_conn_walk_init, ilb_conn_walk_step, ilb_common_walk_fini },
174910946SSangeeta.Misra@Sun.COM 	{ "ilb_stickys", "walk sticky table of a given ilb_stack_t",
175010946SSangeeta.Misra@Sun.COM 		ilb_sticky_walk_init, ilb_sticky_walk_step,
175110946SSangeeta.Misra@Sun.COM 		ilb_common_walk_fini },
17520Sstevel@tonic-gate 	{ NULL }
17530Sstevel@tonic-gate };
17540Sstevel@tonic-gate 
17550Sstevel@tonic-gate static const mdb_qops_t ip_qops = { ip_qinfo, ip_rnext, ip_wnext };
17560Sstevel@tonic-gate static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
17570Sstevel@tonic-gate 
17580Sstevel@tonic-gate const mdb_modinfo_t *
17590Sstevel@tonic-gate _mdb_init(void)
17600Sstevel@tonic-gate {
17610Sstevel@tonic-gate 	GElf_Sym sym;
17620Sstevel@tonic-gate 
17632546Scarlsonj 	if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0)
17640Sstevel@tonic-gate 		mdb_qops_install(&ip_qops, (uintptr_t)sym.st_value);
17650Sstevel@tonic-gate 
17660Sstevel@tonic-gate 	return (&modinfo);
17670Sstevel@tonic-gate }
17680Sstevel@tonic-gate 
17690Sstevel@tonic-gate void
17700Sstevel@tonic-gate _mdb_fini(void)
17710Sstevel@tonic-gate {
17720Sstevel@tonic-gate 	GElf_Sym sym;
17730Sstevel@tonic-gate 
17742546Scarlsonj 	if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0)
17750Sstevel@tonic-gate 		mdb_qops_remove(&ip_qops, (uintptr_t)sym.st_value);
17760Sstevel@tonic-gate }
17775940Ssowmini 
17785940Ssowmini static char *
1779*11042SErik.Nordmark@Sun.COM ncec_state(int ncec_state)
17805940Ssowmini {
1781*11042SErik.Nordmark@Sun.COM 	switch (ncec_state) {
17825940Ssowmini 	case ND_UNCHANGED:
17835940Ssowmini 		return ("unchanged");
17845940Ssowmini 	case ND_INCOMPLETE:
17855940Ssowmini 		return ("incomplete");
17865940Ssowmini 	case ND_REACHABLE:
17875940Ssowmini 		return ("reachable");
17885940Ssowmini 	case ND_STALE:
17895940Ssowmini 		return ("stale");
17905940Ssowmini 	case ND_DELAY:
17915940Ssowmini 		return ("delay");
17925940Ssowmini 	case ND_PROBE:
17935940Ssowmini 		return ("probe");
17945940Ssowmini 	case ND_UNREACHABLE:
17955940Ssowmini 		return ("unreach");
17965940Ssowmini 	case ND_INITIAL:
17975940Ssowmini 		return ("initial");
17985940Ssowmini 	default:
17995940Ssowmini 		return ("??");
18005940Ssowmini 	}
18015940Ssowmini }
18025940Ssowmini 
18035940Ssowmini static char *
1804*11042SErik.Nordmark@Sun.COM ncec_l2_addr(const ncec_t *ncec, const ill_t *ill)
1805*11042SErik.Nordmark@Sun.COM {
1806*11042SErik.Nordmark@Sun.COM 	uchar_t *h;
1807*11042SErik.Nordmark@Sun.COM 	static char addr_buf[L2MAXADDRSTRLEN];
1808*11042SErik.Nordmark@Sun.COM 
1809*11042SErik.Nordmark@Sun.COM 	if (ncec->ncec_lladdr == NULL) {
1810*11042SErik.Nordmark@Sun.COM 		return ("None");
1811*11042SErik.Nordmark@Sun.COM 	}
1812*11042SErik.Nordmark@Sun.COM 
1813*11042SErik.Nordmark@Sun.COM 	if (ill->ill_net_type == IRE_IF_RESOLVER) {
1814*11042SErik.Nordmark@Sun.COM 
1815*11042SErik.Nordmark@Sun.COM 		if (ill->ill_phys_addr_length == 0)
1816*11042SErik.Nordmark@Sun.COM 			return ("None");
1817*11042SErik.Nordmark@Sun.COM 		h = mdb_zalloc(ill->ill_phys_addr_length, UM_SLEEP);
1818*11042SErik.Nordmark@Sun.COM 		if (mdb_vread(h, ill->ill_phys_addr_length,
1819*11042SErik.Nordmark@Sun.COM 		    (uintptr_t)ncec->ncec_lladdr) == -1) {
1820*11042SErik.Nordmark@Sun.COM 			mdb_warn("failed to read hwaddr at %p",
1821*11042SErik.Nordmark@Sun.COM 			    ncec->ncec_lladdr);
1822*11042SErik.Nordmark@Sun.COM 			return ("Unknown");
1823*11042SErik.Nordmark@Sun.COM 		}
1824*11042SErik.Nordmark@Sun.COM 		mdb_mac_addr(h, ill->ill_phys_addr_length,
1825*11042SErik.Nordmark@Sun.COM 		    addr_buf, sizeof (addr_buf));
1826*11042SErik.Nordmark@Sun.COM 	} else {
1827*11042SErik.Nordmark@Sun.COM 		return ("None");
1828*11042SErik.Nordmark@Sun.COM 	}
1829*11042SErik.Nordmark@Sun.COM 	mdb_free(h, ill->ill_phys_addr_length);
1830*11042SErik.Nordmark@Sun.COM 	return (addr_buf);
1831*11042SErik.Nordmark@Sun.COM }
1832*11042SErik.Nordmark@Sun.COM 
1833*11042SErik.Nordmark@Sun.COM static char *
18345940Ssowmini nce_l2_addr(const nce_t *nce, const ill_t *ill)
18355940Ssowmini {
18365940Ssowmini 	uchar_t *h;
18375940Ssowmini 	static char addr_buf[L2MAXADDRSTRLEN];
18385940Ssowmini 	mblk_t mp;
18395940Ssowmini 	size_t mblen;
18405940Ssowmini 
1841*11042SErik.Nordmark@Sun.COM 	if (nce->nce_dlur_mp == NULL)
18425940Ssowmini 		return ("None");
18435940Ssowmini 
18445940Ssowmini 	if (ill->ill_net_type == IRE_IF_RESOLVER) {
18455940Ssowmini 		if (mdb_vread(&mp, sizeof (mblk_t),
1846*11042SErik.Nordmark@Sun.COM 		    (uintptr_t)nce->nce_dlur_mp) == -1) {
1847*11042SErik.Nordmark@Sun.COM 			mdb_warn("failed to read nce_dlur_mp at %p",
1848*11042SErik.Nordmark@Sun.COM 			    nce->nce_dlur_mp);
1849*11042SErik.Nordmark@Sun.COM 			return ("None");
18505940Ssowmini 		}
1851*11042SErik.Nordmark@Sun.COM 		if (ill->ill_phys_addr_length == 0)
18525940Ssowmini 			return ("None");
18535940Ssowmini 		mblen = mp.b_wptr - mp.b_rptr;
18545940Ssowmini 		if (mblen > (sizeof (dl_unitdata_req_t) + MAX_SAP_LEN) ||
1855*11042SErik.Nordmark@Sun.COM 		    ill->ill_phys_addr_length > MAX_SAP_LEN ||
1856*11042SErik.Nordmark@Sun.COM 		    (NCE_LL_ADDR_OFFSET(ill) +
1857*11042SErik.Nordmark@Sun.COM 		    ill->ill_phys_addr_length) > mblen) {
1858*11042SErik.Nordmark@Sun.COM 			return ("Unknown");
18595940Ssowmini 		}
18605940Ssowmini 		h = mdb_zalloc(mblen, UM_SLEEP);
18615940Ssowmini 		if (mdb_vread(h, mblen, (uintptr_t)(mp.b_rptr)) == -1) {
18625940Ssowmini 			mdb_warn("failed to read hwaddr at %p",
18635940Ssowmini 			    mp.b_rptr + NCE_LL_ADDR_OFFSET(ill));
18645940Ssowmini 			return ("Unknown");
18655940Ssowmini 		}
1866*11042SErik.Nordmark@Sun.COM 		mdb_mac_addr(h + NCE_LL_ADDR_OFFSET(ill),
1867*11042SErik.Nordmark@Sun.COM 		    ill->ill_phys_addr_length, addr_buf, sizeof (addr_buf));
18685940Ssowmini 	} else {
18695940Ssowmini 		return ("None");
18705940Ssowmini 	}
18715940Ssowmini 	mdb_free(h, mblen);
18725940Ssowmini 	return (addr_buf);
18735940Ssowmini }
18745940Ssowmini 
18755940Ssowmini static void
1876*11042SErik.Nordmark@Sun.COM ncec_header(uint_t flags)
18775940Ssowmini {
18785940Ssowmini 	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
18795940Ssowmini 
18805940Ssowmini 		mdb_printf("%<u>%?s %-20s %-10s %-8s %-5s %s%</u>\n",
18815940Ssowmini 		    "ADDR", "HW_ADDR", "STATE", "FLAGS", "ILL", "IP ADDR");
18825940Ssowmini 	}
18835940Ssowmini }
18845940Ssowmini 
18855940Ssowmini int
1886*11042SErik.Nordmark@Sun.COM ncec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
18875940Ssowmini {
1888*11042SErik.Nordmark@Sun.COM 	ncec_t ncec;
1889*11042SErik.Nordmark@Sun.COM 	ncec_cbdata_t id;
18905940Ssowmini 	int ipversion = 0;
18915940Ssowmini 	const char *opt_P = NULL;
18925940Ssowmini 
18935940Ssowmini 	if (mdb_getopts(argc, argv,
18945940Ssowmini 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
18955940Ssowmini 		return (DCMD_USAGE);
18965940Ssowmini 
18975940Ssowmini 	if (opt_P != NULL) {
18985940Ssowmini 		if (strcmp("v4", opt_P) == 0) {
18995940Ssowmini 			ipversion = IPV4_VERSION;
19005940Ssowmini 		} else if (strcmp("v6", opt_P) == 0) {
19015940Ssowmini 			ipversion = IPV6_VERSION;
19025940Ssowmini 		} else {
19035940Ssowmini 			mdb_warn("invalid protocol '%s'\n", opt_P);
19045940Ssowmini 			return (DCMD_USAGE);
19055940Ssowmini 		}
19065940Ssowmini 	}
19075940Ssowmini 
19085940Ssowmini 	if (flags & DCMD_ADDRSPEC) {
19095940Ssowmini 
1910*11042SErik.Nordmark@Sun.COM 		if (mdb_vread(&ncec, sizeof (ncec_t), addr) == -1) {
1911*11042SErik.Nordmark@Sun.COM 			mdb_warn("failed to read ncec at %p\n", addr);
19125940Ssowmini 			return (DCMD_ERR);
19135940Ssowmini 		}
1914*11042SErik.Nordmark@Sun.COM 		if (ipversion != 0 && ncec.ncec_ipversion != ipversion) {
19155940Ssowmini 			mdb_printf("IP Version mismatch\n");
19165940Ssowmini 			return (DCMD_ERR);
19175940Ssowmini 		}
1918*11042SErik.Nordmark@Sun.COM 		ncec_header(flags);
1919*11042SErik.Nordmark@Sun.COM 		return (ncec_format(addr, &ncec, ipversion));
19205940Ssowmini 
19215940Ssowmini 	} else {
1922*11042SErik.Nordmark@Sun.COM 		id.ncec_addr = addr;
1923*11042SErik.Nordmark@Sun.COM 		id.ncec_ipversion = ipversion;
1924*11042SErik.Nordmark@Sun.COM 		ncec_header(flags);
1925*11042SErik.Nordmark@Sun.COM 		if (mdb_walk("ncec", (mdb_walk_cb_t)ncec_cb, &id) == -1) {
1926*11042SErik.Nordmark@Sun.COM 			mdb_warn("failed to walk ncec table\n");
19275940Ssowmini 			return (DCMD_ERR);
19285940Ssowmini 		}
19295940Ssowmini 	}
19305940Ssowmini 	return (DCMD_OK);
19315940Ssowmini }
19325940Ssowmini 
19335940Ssowmini static int
1934*11042SErik.Nordmark@Sun.COM ncec_format(uintptr_t addr, const ncec_t *ncec, int ipversion)
19355940Ssowmini {
1936*11042SErik.Nordmark@Sun.COM 	static const mdb_bitmask_t ncec_flags[] = {
1937*11042SErik.Nordmark@Sun.COM 		{ "P",	NCE_F_NONUD,		NCE_F_NONUD },
19385940Ssowmini 		{ "R",	NCE_F_ISROUTER,		NCE_F_ISROUTER	},
19395940Ssowmini 		{ "N",	NCE_F_NONUD,		NCE_F_NONUD	},
19405940Ssowmini 		{ "A",	NCE_F_ANYCAST,		NCE_F_ANYCAST	},
19415940Ssowmini 		{ "C",	NCE_F_CONDEMNED,	NCE_F_CONDEMNED	},
19425940Ssowmini 		{ "U",	NCE_F_UNSOL_ADV,	NCE_F_UNSOL_ADV },
19435940Ssowmini 		{ "B",	NCE_F_BCAST,		NCE_F_BCAST	},
19445940Ssowmini 		{ NULL,	0,			0		}
19455940Ssowmini 	};
1946*11042SErik.Nordmark@Sun.COM #define	NCE_MAX_FLAGS	(sizeof (ncec_flags) / sizeof (mdb_bitmask_t))
19475940Ssowmini 	struct in_addr nceaddr;
19485940Ssowmini 	ill_t ill;
19495940Ssowmini 	char ill_name[LIFNAMSIZ];
19505940Ssowmini 	char flagsbuf[NCE_MAX_FLAGS];
19515940Ssowmini 
1952*11042SErik.Nordmark@Sun.COM 	if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ncec->ncec_ill) == -1) {
1953*11042SErik.Nordmark@Sun.COM 		mdb_warn("failed to read ncec_ill at %p",
1954*11042SErik.Nordmark@Sun.COM 		    ncec->ncec_ill);
19555940Ssowmini 		return (DCMD_ERR);
19565940Ssowmini 	}
19575940Ssowmini 
19585940Ssowmini 	(void) mdb_readstr(ill_name, MIN(LIFNAMSIZ, ill.ill_name_length),
19595940Ssowmini 	    (uintptr_t)ill.ill_name);
19605940Ssowmini 
19615940Ssowmini 	mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%hb",
1962*11042SErik.Nordmark@Sun.COM 	    ncec->ncec_flags, ncec_flags);
1963*11042SErik.Nordmark@Sun.COM 
1964*11042SErik.Nordmark@Sun.COM 	if (ipversion != 0 && ncec->ncec_ipversion != ipversion)
19655940Ssowmini 		return (DCMD_OK);
19665940Ssowmini 
1967*11042SErik.Nordmark@Sun.COM 	if (ncec->ncec_ipversion == IPV4_VERSION) {
1968*11042SErik.Nordmark@Sun.COM 		IN6_V4MAPPED_TO_INADDR(&ncec->ncec_addr, &nceaddr);
19695940Ssowmini 		mdb_printf("%?p %-20s %-10s "
19705940Ssowmini 		    "%-8s "
19715940Ssowmini 		    "%-5s %I\n",
1972*11042SErik.Nordmark@Sun.COM 		    addr, ncec_l2_addr(ncec, &ill),
1973*11042SErik.Nordmark@Sun.COM 		    ncec_state(ncec->ncec_state),
19745940Ssowmini 		    flagsbuf,
19755940Ssowmini 		    ill_name, nceaddr.s_addr);
19765940Ssowmini 	} else {
19775940Ssowmini 		mdb_printf("%?p %-20s %-10s %-8s %-5s %N\n",
1978*11042SErik.Nordmark@Sun.COM 		    addr,  ncec_l2_addr(ncec, &ill),
1979*11042SErik.Nordmark@Sun.COM 		    ncec_state(ncec->ncec_state),
19805940Ssowmini 		    flagsbuf,
1981*11042SErik.Nordmark@Sun.COM 		    ill_name, &ncec->ncec_addr);
19825940Ssowmini 	}
19835940Ssowmini 
19845940Ssowmini 	return (DCMD_OK);
19855940Ssowmini }
19865940Ssowmini 
19875940Ssowmini static uintptr_t
1988*11042SErik.Nordmark@Sun.COM ncec_get_next_hash_tbl(uintptr_t start, int *index, struct ndp_g_s ndp)
19895940Ssowmini {
19905940Ssowmini 	uintptr_t addr = start;
19915940Ssowmini 	int i = *index;
19925940Ssowmini 
19935940Ssowmini 	while (addr == NULL) {
19945940Ssowmini 
19955940Ssowmini 		if (++i >= NCE_TABLE_SIZE)
19965940Ssowmini 			break;
19975940Ssowmini 		addr = (uintptr_t)ndp.nce_hash_tbl[i];
19985940Ssowmini 	}
19995940Ssowmini 	*index = i;
20005940Ssowmini 	return (addr);
20015940Ssowmini }
20025940Ssowmini 
20035940Ssowmini static int
2004*11042SErik.Nordmark@Sun.COM ncec_walk_step(mdb_walk_state_t *wsp)
20055940Ssowmini {
20065940Ssowmini 	uintptr_t kaddr4, kaddr6;
20075940Ssowmini 
20085940Ssowmini 	kaddr4 = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ndp4);
20095940Ssowmini 	kaddr6 = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ndp6);
20105940Ssowmini 
20115940Ssowmini 	if (mdb_vread(&kaddr4, sizeof (kaddr4), kaddr4) == -1) {
20125940Ssowmini 		mdb_warn("can't read ips_ip_cache_table at %p", kaddr4);
20135940Ssowmini 		return (WALK_ERR);
20145940Ssowmini 	}
20155940Ssowmini 	if (mdb_vread(&kaddr6, sizeof (kaddr6), kaddr6) == -1) {
20165940Ssowmini 		mdb_warn("can't read ips_ip_cache_table at %p", kaddr6);
20175940Ssowmini 		return (WALK_ERR);
20185940Ssowmini 	}
2019*11042SErik.Nordmark@Sun.COM 	if (mdb_pwalk("ncec_stack", wsp->walk_callback, wsp->walk_cbdata,
20205940Ssowmini 	    kaddr4) == -1) {
2021*11042SErik.Nordmark@Sun.COM 		mdb_warn("couldn't walk 'ncec_stack' for ips_ndp4 %p",
20225940Ssowmini 		    kaddr4);
20235940Ssowmini 		return (WALK_ERR);
20245940Ssowmini 	}
2025*11042SErik.Nordmark@Sun.COM 	if (mdb_pwalk("ncec_stack", wsp->walk_callback,
20265940Ssowmini 	    wsp->walk_cbdata, kaddr6) == -1) {
2027*11042SErik.Nordmark@Sun.COM 		mdb_warn("couldn't walk 'ncec_stack' for ips_ndp6 %p",
20285940Ssowmini 		    kaddr6);
20295940Ssowmini 		return (WALK_ERR);
20305940Ssowmini 	}
20315940Ssowmini 	return (WALK_NEXT);
20325940Ssowmini }
20335940Ssowmini 
20349089SVasumathi.Sundaram@Sun.COM static uintptr_t
20359089SVasumathi.Sundaram@Sun.COM ipcl_hash_get_next_connf_tbl(ipcl_hash_walk_data_t *iw)
20369089SVasumathi.Sundaram@Sun.COM {
20379089SVasumathi.Sundaram@Sun.COM 	struct connf_s connf;
20389089SVasumathi.Sundaram@Sun.COM 	uintptr_t addr = NULL, next;
20399089SVasumathi.Sundaram@Sun.COM 	int index = iw->connf_tbl_index;
20409089SVasumathi.Sundaram@Sun.COM 
20419089SVasumathi.Sundaram@Sun.COM 	do {
20429089SVasumathi.Sundaram@Sun.COM 		next = iw->hash_tbl + index * sizeof (struct connf_s);
20439089SVasumathi.Sundaram@Sun.COM 		if (++index >= iw->hash_tbl_size) {
20449089SVasumathi.Sundaram@Sun.COM 			addr = NULL;
20459089SVasumathi.Sundaram@Sun.COM 			break;
20469089SVasumathi.Sundaram@Sun.COM 		}
20479089SVasumathi.Sundaram@Sun.COM 		if (mdb_vread(&connf, sizeof (struct connf_s), next) == -1)  {
20489089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to read conn_t at %p", next);
20499089SVasumathi.Sundaram@Sun.COM 			return (NULL);
20509089SVasumathi.Sundaram@Sun.COM 		}
20519089SVasumathi.Sundaram@Sun.COM 		addr = (uintptr_t)connf.connf_head;
20529089SVasumathi.Sundaram@Sun.COM 	} while (addr == NULL);
20539089SVasumathi.Sundaram@Sun.COM 	iw->connf_tbl_index = index;
20549089SVasumathi.Sundaram@Sun.COM 	return (addr);
20559089SVasumathi.Sundaram@Sun.COM }
20569089SVasumathi.Sundaram@Sun.COM 
20579089SVasumathi.Sundaram@Sun.COM static int
20589089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_init(mdb_walk_state_t *wsp)
20599089SVasumathi.Sundaram@Sun.COM {
20609089SVasumathi.Sundaram@Sun.COM 	const hash_walk_arg_t *arg = wsp->walk_arg;
20619089SVasumathi.Sundaram@Sun.COM 	ipcl_hash_walk_data_t *iw;
20629089SVasumathi.Sundaram@Sun.COM 	uintptr_t tbladdr;
20639089SVasumathi.Sundaram@Sun.COM 	uintptr_t sizeaddr;
20649089SVasumathi.Sundaram@Sun.COM 
20659089SVasumathi.Sundaram@Sun.COM 	iw = mdb_alloc(sizeof (ipcl_hash_walk_data_t), UM_SLEEP);
20669089SVasumathi.Sundaram@Sun.COM 	iw->conn = mdb_alloc(sizeof (conn_t), UM_SLEEP);
20679089SVasumathi.Sundaram@Sun.COM 	tbladdr = wsp->walk_addr + arg->tbl_off;
20689089SVasumathi.Sundaram@Sun.COM 	sizeaddr = wsp->walk_addr + arg->size_off;
20699089SVasumathi.Sundaram@Sun.COM 
20709089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&iw->hash_tbl, sizeof (uintptr_t), tbladdr) == -1) {
20719089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't read fanout table addr at %p", tbladdr);
20729089SVasumathi.Sundaram@Sun.COM 		mdb_free(iw->conn, sizeof (conn_t));
20739089SVasumathi.Sundaram@Sun.COM 		mdb_free(iw, sizeof (ipcl_hash_walk_data_t));
20749089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
20759089SVasumathi.Sundaram@Sun.COM 	}
2076*11042SErik.Nordmark@Sun.COM 	if (arg->tbl_off == OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v4) ||
20779089SVasumathi.Sundaram@Sun.COM 	    arg->tbl_off == OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v6)) {
20789089SVasumathi.Sundaram@Sun.COM 		iw->hash_tbl_size = IPPROTO_MAX;
20799089SVasumathi.Sundaram@Sun.COM 	} else {
20809089SVasumathi.Sundaram@Sun.COM 		if (mdb_vread(&iw->hash_tbl_size, sizeof (int),
20819089SVasumathi.Sundaram@Sun.COM 		    sizeaddr) == -1) {
20829089SVasumathi.Sundaram@Sun.COM 			mdb_warn("can't read fanout table size addr at %p",
20839089SVasumathi.Sundaram@Sun.COM 			    sizeaddr);
20849089SVasumathi.Sundaram@Sun.COM 			mdb_free(iw->conn, sizeof (conn_t));
20859089SVasumathi.Sundaram@Sun.COM 			mdb_free(iw, sizeof (ipcl_hash_walk_data_t));
20869089SVasumathi.Sundaram@Sun.COM 			return (WALK_ERR);
20879089SVasumathi.Sundaram@Sun.COM 		}
20889089SVasumathi.Sundaram@Sun.COM 	}
20899089SVasumathi.Sundaram@Sun.COM 	iw->connf_tbl_index = 0;
20909089SVasumathi.Sundaram@Sun.COM 	wsp->walk_addr = ipcl_hash_get_next_connf_tbl(iw);
20919089SVasumathi.Sundaram@Sun.COM 	wsp->walk_data = iw;
20929089SVasumathi.Sundaram@Sun.COM 
20939089SVasumathi.Sundaram@Sun.COM 	if (wsp->walk_addr != NULL)
20949089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
20959089SVasumathi.Sundaram@Sun.COM 	else
20969089SVasumathi.Sundaram@Sun.COM 		return (WALK_DONE);
20979089SVasumathi.Sundaram@Sun.COM }
20989089SVasumathi.Sundaram@Sun.COM 
20999089SVasumathi.Sundaram@Sun.COM static int
21009089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_step(mdb_walk_state_t *wsp)
21019089SVasumathi.Sundaram@Sun.COM {
21029089SVasumathi.Sundaram@Sun.COM 	uintptr_t addr = wsp->walk_addr;
21039089SVasumathi.Sundaram@Sun.COM 	ipcl_hash_walk_data_t *iw = wsp->walk_data;
21049089SVasumathi.Sundaram@Sun.COM 	conn_t *conn = iw->conn;
21059089SVasumathi.Sundaram@Sun.COM 	int ret = WALK_DONE;
21069089SVasumathi.Sundaram@Sun.COM 
21079089SVasumathi.Sundaram@Sun.COM 	while (addr != NULL) {
21089089SVasumathi.Sundaram@Sun.COM 		if (mdb_vread(conn, sizeof (conn_t), addr) == -1) {
21099089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to read conn_t at %p", addr);
21109089SVasumathi.Sundaram@Sun.COM 			return (WALK_ERR);
21119089SVasumathi.Sundaram@Sun.COM 		}
21129089SVasumathi.Sundaram@Sun.COM 		ret = wsp->walk_callback(addr, iw, wsp->walk_cbdata);
21139089SVasumathi.Sundaram@Sun.COM 		if (ret != WALK_NEXT)
21149089SVasumathi.Sundaram@Sun.COM 			break;
21159089SVasumathi.Sundaram@Sun.COM 		addr = (uintptr_t)conn->conn_next;
21169089SVasumathi.Sundaram@Sun.COM 	}
21179089SVasumathi.Sundaram@Sun.COM 	if (ret == WALK_NEXT) {
21189089SVasumathi.Sundaram@Sun.COM 		wsp->walk_addr = ipcl_hash_get_next_connf_tbl(iw);
21199089SVasumathi.Sundaram@Sun.COM 
21209089SVasumathi.Sundaram@Sun.COM 		if (wsp->walk_addr != NULL)
21219089SVasumathi.Sundaram@Sun.COM 			return (WALK_NEXT);
21229089SVasumathi.Sundaram@Sun.COM 		else
21239089SVasumathi.Sundaram@Sun.COM 			return (WALK_DONE);
21249089SVasumathi.Sundaram@Sun.COM 	}
21259089SVasumathi.Sundaram@Sun.COM 
21269089SVasumathi.Sundaram@Sun.COM 	return (ret);
21279089SVasumathi.Sundaram@Sun.COM }
21289089SVasumathi.Sundaram@Sun.COM 
21299089SVasumathi.Sundaram@Sun.COM static void
21309089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_fini(mdb_walk_state_t *wsp)
21319089SVasumathi.Sundaram@Sun.COM {
21329089SVasumathi.Sundaram@Sun.COM 	ipcl_hash_walk_data_t *iw = wsp->walk_data;
21339089SVasumathi.Sundaram@Sun.COM 
21349089SVasumathi.Sundaram@Sun.COM 	mdb_free(iw->conn, sizeof (conn_t));
21359089SVasumathi.Sundaram@Sun.COM 	mdb_free(iw, sizeof (ipcl_hash_walk_data_t));
21369089SVasumathi.Sundaram@Sun.COM }
21379089SVasumathi.Sundaram@Sun.COM 
21385940Ssowmini /*
21395940Ssowmini  * Called with walk_addr being the address of ips_ndp{4,6}
21405940Ssowmini  */
21415940Ssowmini static int
2142*11042SErik.Nordmark@Sun.COM ncec_stack_walk_init(mdb_walk_state_t *wsp)
21435940Ssowmini {
2144*11042SErik.Nordmark@Sun.COM 	ncec_walk_data_t *nw;
21455940Ssowmini 
21465940Ssowmini 	if (wsp->walk_addr == NULL) {
2147*11042SErik.Nordmark@Sun.COM 		mdb_warn("ncec_stack requires ndp_g_s address\n");
21485940Ssowmini 		return (WALK_ERR);
21495940Ssowmini 	}
21505940Ssowmini 
2151*11042SErik.Nordmark@Sun.COM 	nw = mdb_alloc(sizeof (ncec_walk_data_t), UM_SLEEP);
2152*11042SErik.Nordmark@Sun.COM 
2153*11042SErik.Nordmark@Sun.COM 	if (mdb_vread(&nw->ncec_ip_ndp, sizeof (struct ndp_g_s),
21545940Ssowmini 	    wsp->walk_addr) == -1) {
21555940Ssowmini 		mdb_warn("failed to read 'ip_ndp' at %p",
21565940Ssowmini 		    wsp->walk_addr);
2157*11042SErik.Nordmark@Sun.COM 		mdb_free(nw, sizeof (ncec_walk_data_t));
21585940Ssowmini 		return (WALK_ERR);
21595940Ssowmini 	}
21605940Ssowmini 
2161*11042SErik.Nordmark@Sun.COM 	/*
2162*11042SErik.Nordmark@Sun.COM 	 * ncec_get_next_hash_tbl() starts at ++i , so initialize index to -1
2163*11042SErik.Nordmark@Sun.COM 	 */
2164*11042SErik.Nordmark@Sun.COM 	nw->ncec_hash_tbl_index = -1;
2165*11042SErik.Nordmark@Sun.COM 	wsp->walk_addr = ncec_get_next_hash_tbl(NULL,
2166*11042SErik.Nordmark@Sun.COM 	    &nw->ncec_hash_tbl_index, nw->ncec_ip_ndp);
21675940Ssowmini 	wsp->walk_data = nw;
21685940Ssowmini 
21695940Ssowmini 	return (WALK_NEXT);
21705940Ssowmini }
21715940Ssowmini 
21725940Ssowmini static int
2173*11042SErik.Nordmark@Sun.COM ncec_stack_walk_step(mdb_walk_state_t *wsp)
21745940Ssowmini {
21755940Ssowmini 	uintptr_t addr = wsp->walk_addr;
2176*11042SErik.Nordmark@Sun.COM 	ncec_walk_data_t *nw = wsp->walk_data;
21775940Ssowmini 
21785940Ssowmini 	if (addr == NULL)
21795940Ssowmini 		return (WALK_DONE);
21805940Ssowmini 
2181*11042SErik.Nordmark@Sun.COM 	if (mdb_vread(&nw->ncec, sizeof (ncec_t), addr) == -1) {
2182*11042SErik.Nordmark@Sun.COM 		mdb_warn("failed to read ncec_t at %p", addr);
21835940Ssowmini 		return (WALK_ERR);
21845940Ssowmini 	}
21855940Ssowmini 
2186*11042SErik.Nordmark@Sun.COM 	wsp->walk_addr = (uintptr_t)nw->ncec.ncec_next;
2187*11042SErik.Nordmark@Sun.COM 
2188*11042SErik.Nordmark@Sun.COM 	wsp->walk_addr = ncec_get_next_hash_tbl(wsp->walk_addr,
2189*11042SErik.Nordmark@Sun.COM 	    &nw->ncec_hash_tbl_index, nw->ncec_ip_ndp);
21905940Ssowmini 
21915940Ssowmini 	return (wsp->walk_callback(addr, nw, wsp->walk_cbdata));
21925940Ssowmini }
21935940Ssowmini 
21945940Ssowmini static void
2195*11042SErik.Nordmark@Sun.COM ncec_stack_walk_fini(mdb_walk_state_t *wsp)
21965940Ssowmini {
2197*11042SErik.Nordmark@Sun.COM 	mdb_free(wsp->walk_data, sizeof (ncec_walk_data_t));
21985940Ssowmini }
21995940Ssowmini 
22005940Ssowmini /* ARGSUSED */
22015940Ssowmini static int
2202*11042SErik.Nordmark@Sun.COM ncec_cb(uintptr_t addr, const ncec_walk_data_t *iw, ncec_cbdata_t *id)
22035940Ssowmini {
2204*11042SErik.Nordmark@Sun.COM 	ncec_t ncec;
2205*11042SErik.Nordmark@Sun.COM 
2206*11042SErik.Nordmark@Sun.COM 	if (mdb_vread(&ncec, sizeof (ncec_t), addr) == -1) {
2207*11042SErik.Nordmark@Sun.COM 		mdb_warn("failed to read ncec at %p", addr);
22085940Ssowmini 		return (WALK_NEXT);
22095940Ssowmini 	}
2210*11042SErik.Nordmark@Sun.COM 	(void) ncec_format(addr, &ncec, id->ncec_ipversion);
22115940Ssowmini 	return (WALK_NEXT);
22125940Ssowmini }
22139089SVasumathi.Sundaram@Sun.COM 
22149089SVasumathi.Sundaram@Sun.COM static int
22159089SVasumathi.Sundaram@Sun.COM ill_walk_init(mdb_walk_state_t *wsp)
22169089SVasumathi.Sundaram@Sun.COM {
22179089SVasumathi.Sundaram@Sun.COM 	if (mdb_layered_walk("illif", wsp) == -1) {
22189089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't walk 'illif'");
22199089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
22209089SVasumathi.Sundaram@Sun.COM 	}
22219089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
22229089SVasumathi.Sundaram@Sun.COM }
22239089SVasumathi.Sundaram@Sun.COM 
22249089SVasumathi.Sundaram@Sun.COM static int
22259089SVasumathi.Sundaram@Sun.COM ill_walk_step(mdb_walk_state_t *wsp)
22269089SVasumathi.Sundaram@Sun.COM {
22279089SVasumathi.Sundaram@Sun.COM 	ill_if_t ill_if;
22289089SVasumathi.Sundaram@Sun.COM 
22299089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&ill_if, sizeof (ill_if_t), wsp->walk_addr) == -1) {
22309089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't read ill_if_t at %p", wsp->walk_addr);
22319089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
22329089SVasumathi.Sundaram@Sun.COM 	}
22339089SVasumathi.Sundaram@Sun.COM 	wsp->walk_addr = (uintptr_t)(wsp->walk_addr +
22349089SVasumathi.Sundaram@Sun.COM 	    offsetof(ill_if_t, illif_avl_by_ppa));
22359089SVasumathi.Sundaram@Sun.COM 	if (mdb_pwalk("avl", wsp->walk_callback, wsp->walk_cbdata,
22369089SVasumathi.Sundaram@Sun.COM 	    wsp->walk_addr) == -1) {
22379089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't walk 'avl'");
22389089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
22399089SVasumathi.Sundaram@Sun.COM 	}
22409089SVasumathi.Sundaram@Sun.COM 
22419089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
22429089SVasumathi.Sundaram@Sun.COM }
22439089SVasumathi.Sundaram@Sun.COM 
22449089SVasumathi.Sundaram@Sun.COM /* ARGSUSED */
22459089SVasumathi.Sundaram@Sun.COM static int
22469089SVasumathi.Sundaram@Sun.COM ill_cb(uintptr_t addr, const ill_walk_data_t *iw, ill_cbdata_t *id)
22479089SVasumathi.Sundaram@Sun.COM {
22489089SVasumathi.Sundaram@Sun.COM 	ill_t ill;
22499089SVasumathi.Sundaram@Sun.COM 
22509089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&ill, sizeof (ill_t), (uintptr_t)addr) == -1) {
22519089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read ill at %p", addr);
22529089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
22539089SVasumathi.Sundaram@Sun.COM 	}
2254*11042SErik.Nordmark@Sun.COM 
2255*11042SErik.Nordmark@Sun.COM 	/* If ip_stack_t is specified, skip ILLs that don't belong to it. */
2256*11042SErik.Nordmark@Sun.COM 	if (id->ill_ipst != NULL && ill.ill_ipst != id->ill_ipst)
2257*11042SErik.Nordmark@Sun.COM 		return (WALK_NEXT);
2258*11042SErik.Nordmark@Sun.COM 
22599089SVasumathi.Sundaram@Sun.COM 	return (ill_format((uintptr_t)addr, &ill, id));
22609089SVasumathi.Sundaram@Sun.COM }
22619089SVasumathi.Sundaram@Sun.COM 
22629089SVasumathi.Sundaram@Sun.COM static void
22639089SVasumathi.Sundaram@Sun.COM ill_header(boolean_t verbose)
22649089SVasumathi.Sundaram@Sun.COM {
22659089SVasumathi.Sundaram@Sun.COM 	if (verbose) {
22669089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?s %-8s %3s %-10s %-?s %-?s %-10s%</u>\n",
22679089SVasumathi.Sundaram@Sun.COM 		    "ADDR", "NAME", "VER", "TYPE", "WQ", "IPST", "FLAGS");
22689089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?s %4s%4s %-?s\n",
22699089SVasumathi.Sundaram@Sun.COM 		    "PHYINT", "CNT", "", "GROUP");
22709089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%<u>%80s%</u>\n", "");
22719089SVasumathi.Sundaram@Sun.COM 	} else {
22729089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%<u>%-?s %-8s %-3s %-10s %4s %-?s %-10s%</u>\n",
22739089SVasumathi.Sundaram@Sun.COM 		    "ADDR", "NAME", "VER", "TYPE", "CNT", "WQ", "FLAGS");
22749089SVasumathi.Sundaram@Sun.COM 	}
22759089SVasumathi.Sundaram@Sun.COM }
22769089SVasumathi.Sundaram@Sun.COM 
22779089SVasumathi.Sundaram@Sun.COM static int
22789089SVasumathi.Sundaram@Sun.COM ill_format(uintptr_t addr, const void *illptr, void *ill_cb_arg)
22799089SVasumathi.Sundaram@Sun.COM {
22809089SVasumathi.Sundaram@Sun.COM 	ill_t *ill = (ill_t *)illptr;
22819089SVasumathi.Sundaram@Sun.COM 	ill_cbdata_t *illcb = ill_cb_arg;
22829089SVasumathi.Sundaram@Sun.COM 	boolean_t verbose = illcb->verbose;
22839089SVasumathi.Sundaram@Sun.COM 	phyint_t phyi;
22849089SVasumathi.Sundaram@Sun.COM 	static const mdb_bitmask_t fmasks[] = {
22859089SVasumathi.Sundaram@Sun.COM 		{ "R",		PHYI_RUNNING,		PHYI_RUNNING	},
22869089SVasumathi.Sundaram@Sun.COM 		{ "P",		PHYI_PROMISC,		PHYI_PROMISC	},
22879089SVasumathi.Sundaram@Sun.COM 		{ "V",		PHYI_VIRTUAL,		PHYI_VIRTUAL	},
22889089SVasumathi.Sundaram@Sun.COM 		{ "I",		PHYI_IPMP,		PHYI_IPMP	},
22899089SVasumathi.Sundaram@Sun.COM 		{ "f",		PHYI_FAILED,		PHYI_FAILED	},
22909089SVasumathi.Sundaram@Sun.COM 		{ "S",		PHYI_STANDBY,		PHYI_STANDBY	},
22919089SVasumathi.Sundaram@Sun.COM 		{ "i",		PHYI_INACTIVE,		PHYI_INACTIVE	},
22929089SVasumathi.Sundaram@Sun.COM 		{ "O",		PHYI_OFFLINE,		PHYI_OFFLINE	},
22939089SVasumathi.Sundaram@Sun.COM 		{ "T", 		ILLF_NOTRAILERS,	ILLF_NOTRAILERS },
22949089SVasumathi.Sundaram@Sun.COM 		{ "A",		ILLF_NOARP,		ILLF_NOARP	},
22959089SVasumathi.Sundaram@Sun.COM 		{ "M",		ILLF_MULTICAST,		ILLF_MULTICAST	},
22969089SVasumathi.Sundaram@Sun.COM 		{ "F",		ILLF_ROUTER,		ILLF_ROUTER	},
22979089SVasumathi.Sundaram@Sun.COM 		{ "D",		ILLF_NONUD,		ILLF_NONUD	},
22989089SVasumathi.Sundaram@Sun.COM 		{ "X",		ILLF_NORTEXCH,		ILLF_NORTEXCH	},
22999089SVasumathi.Sundaram@Sun.COM 		{ NULL,		0,			0		}
23009089SVasumathi.Sundaram@Sun.COM 	};
23019089SVasumathi.Sundaram@Sun.COM 	static const mdb_bitmask_t v_fmasks[] = {
23029089SVasumathi.Sundaram@Sun.COM 		{ "RUNNING",	PHYI_RUNNING,		PHYI_RUNNING	},
23039089SVasumathi.Sundaram@Sun.COM 		{ "PROMISC",	PHYI_PROMISC,		PHYI_PROMISC	},
23049089SVasumathi.Sundaram@Sun.COM 		{ "VIRTUAL",	PHYI_VIRTUAL,		PHYI_VIRTUAL	},
23059089SVasumathi.Sundaram@Sun.COM 		{ "IPMP",	PHYI_IPMP,		PHYI_IPMP	},
23069089SVasumathi.Sundaram@Sun.COM 		{ "FAILED",	PHYI_FAILED,		PHYI_FAILED	},
23079089SVasumathi.Sundaram@Sun.COM 		{ "STANDBY",	PHYI_STANDBY,		PHYI_STANDBY	},
23089089SVasumathi.Sundaram@Sun.COM 		{ "INACTIVE",	PHYI_INACTIVE,		PHYI_INACTIVE	},
23099089SVasumathi.Sundaram@Sun.COM 		{ "OFFLINE",	PHYI_OFFLINE,		PHYI_OFFLINE	},
23109089SVasumathi.Sundaram@Sun.COM 		{ "NOTRAILER",	ILLF_NOTRAILERS,	ILLF_NOTRAILERS },
23119089SVasumathi.Sundaram@Sun.COM 		{ "NOARP",	ILLF_NOARP,		ILLF_NOARP	},
23129089SVasumathi.Sundaram@Sun.COM 		{ "MULTICAST",	ILLF_MULTICAST,		ILLF_MULTICAST	},
23139089SVasumathi.Sundaram@Sun.COM 		{ "ROUTER",	ILLF_ROUTER,		ILLF_ROUTER	},
23149089SVasumathi.Sundaram@Sun.COM 		{ "NONUD",	ILLF_NONUD,		ILLF_NONUD	},
23159089SVasumathi.Sundaram@Sun.COM 		{ "NORTEXCH",	ILLF_NORTEXCH,		ILLF_NORTEXCH	},
23169089SVasumathi.Sundaram@Sun.COM 		{ NULL,		0,			0		}
23179089SVasumathi.Sundaram@Sun.COM 	};
23189089SVasumathi.Sundaram@Sun.COM 	char ill_name[LIFNAMSIZ];
23199089SVasumathi.Sundaram@Sun.COM 	int cnt;
23209089SVasumathi.Sundaram@Sun.COM 	char *typebuf;
23219089SVasumathi.Sundaram@Sun.COM 	char sbuf[DEFCOLS];
23229089SVasumathi.Sundaram@Sun.COM 	int ipver = illcb->ill_ipversion;
23239089SVasumathi.Sundaram@Sun.COM 
23249089SVasumathi.Sundaram@Sun.COM 	if (ipver != 0) {
23259089SVasumathi.Sundaram@Sun.COM 		if ((ipver == IPV4_VERSION && ill->ill_isv6) ||
23269089SVasumathi.Sundaram@Sun.COM 		    (ipver == IPV6_VERSION && !ill->ill_isv6)) {
23279089SVasumathi.Sundaram@Sun.COM 			return (WALK_NEXT);
23289089SVasumathi.Sundaram@Sun.COM 		}
23299089SVasumathi.Sundaram@Sun.COM 	}
23309089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&phyi, sizeof (phyint_t),
23319089SVasumathi.Sundaram@Sun.COM 	    (uintptr_t)ill->ill_phyint) == -1) {
23329089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read ill_phyint at %p",
23339089SVasumathi.Sundaram@Sun.COM 		    (uintptr_t)ill->ill_phyint);
23349089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
23359089SVasumathi.Sundaram@Sun.COM 	}
23369089SVasumathi.Sundaram@Sun.COM 	(void) mdb_readstr(ill_name, MIN(LIFNAMSIZ, ill->ill_name_length),
23379089SVasumathi.Sundaram@Sun.COM 	    (uintptr_t)ill->ill_name);
23389089SVasumathi.Sundaram@Sun.COM 
23399089SVasumathi.Sundaram@Sun.COM 	switch (ill->ill_type) {
23409089SVasumathi.Sundaram@Sun.COM 	case 0:
23419089SVasumathi.Sundaram@Sun.COM 		typebuf = "LOOPBACK";
23429089SVasumathi.Sundaram@Sun.COM 		break;
23439089SVasumathi.Sundaram@Sun.COM 	case IFT_ETHER:
23449089SVasumathi.Sundaram@Sun.COM 		typebuf = "ETHER";
23459089SVasumathi.Sundaram@Sun.COM 		break;
23469089SVasumathi.Sundaram@Sun.COM 	case IFT_OTHER:
23479089SVasumathi.Sundaram@Sun.COM 		typebuf = "OTHER";
23489089SVasumathi.Sundaram@Sun.COM 		break;
23499089SVasumathi.Sundaram@Sun.COM 	default:
23509089SVasumathi.Sundaram@Sun.COM 		typebuf = NULL;
23519089SVasumathi.Sundaram@Sun.COM 		break;
23529089SVasumathi.Sundaram@Sun.COM 	}
23539089SVasumathi.Sundaram@Sun.COM 	cnt = ill->ill_refcnt + ill->ill_ire_cnt + ill->ill_nce_cnt +
2354*11042SErik.Nordmark@Sun.COM 	    ill->ill_ilm_cnt + ill->ill_ncec_cnt;
23559089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%-?p %-8s %-3s ",
23569089SVasumathi.Sundaram@Sun.COM 	    addr, ill_name, ill->ill_isv6 ? "v6" : "v4");
23579089SVasumathi.Sundaram@Sun.COM 	if (typebuf != NULL)
23589089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-10s ", typebuf);
23599089SVasumathi.Sundaram@Sun.COM 	else
23609089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-10x ", ill->ill_type);
23619089SVasumathi.Sundaram@Sun.COM 	if (verbose) {
23629089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?p %-?p %-llb\n",
23639089SVasumathi.Sundaram@Sun.COM 		    ill->ill_wq, ill->ill_ipst,
23649089SVasumathi.Sundaram@Sun.COM 		    ill->ill_flags | phyi.phyint_flags, v_fmasks);
23659089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?p %4d%4s %-?p\n",
23669089SVasumathi.Sundaram@Sun.COM 		    ill->ill_phyint, cnt, "", ill->ill_grp);
23679089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(sbuf, sizeof (sbuf), "%*s %3s",
23689089SVasumathi.Sundaram@Sun.COM 		    sizeof (uintptr_t) * 2, "", "");
23699089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%s|\n%s+--> %3d %-18s "
23709089SVasumathi.Sundaram@Sun.COM 		    "references from active threads\n",
23719089SVasumathi.Sundaram@Sun.COM 		    sbuf, sbuf, ill->ill_refcnt, "ill_refcnt");
23729089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*s %7d %-18s ires referencing this ill\n",
23739089SVasumathi.Sundaram@Sun.COM 		    strlen(sbuf), "", ill->ill_ire_cnt, "ill_ire_cnt");
23749089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*s %7d %-18s nces referencing this ill\n",
23759089SVasumathi.Sundaram@Sun.COM 		    strlen(sbuf), "", ill->ill_nce_cnt, "ill_nce_cnt");
2376*11042SErik.Nordmark@Sun.COM 		mdb_printf("%*s %7d %-18s ncecs referencing this ill\n",
2377*11042SErik.Nordmark@Sun.COM 		    strlen(sbuf), "", ill->ill_ncec_cnt, "ill_ncec_cnt");
23789089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*s %7d %-18s ilms referencing this ill\n",
23799089SVasumathi.Sundaram@Sun.COM 		    strlen(sbuf), "", ill->ill_ilm_cnt, "ill_ilm_cnt");
23809089SVasumathi.Sundaram@Sun.COM 	} else {
23819089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%4d %-?p %-llb\n",
23829089SVasumathi.Sundaram@Sun.COM 		    cnt, ill->ill_wq,
23839089SVasumathi.Sundaram@Sun.COM 		    ill->ill_flags | phyi.phyint_flags, fmasks);
23849089SVasumathi.Sundaram@Sun.COM 	}
23859089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
23869089SVasumathi.Sundaram@Sun.COM }
23879089SVasumathi.Sundaram@Sun.COM 
23889089SVasumathi.Sundaram@Sun.COM static int
23899089SVasumathi.Sundaram@Sun.COM ill(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
23909089SVasumathi.Sundaram@Sun.COM {
23919089SVasumathi.Sundaram@Sun.COM 	ill_t ill_data;
23929089SVasumathi.Sundaram@Sun.COM 	ill_cbdata_t id;
23939089SVasumathi.Sundaram@Sun.COM 	int ipversion = 0;
2394*11042SErik.Nordmark@Sun.COM 	const char *zone_name = NULL;
23959089SVasumathi.Sundaram@Sun.COM 	const char *opt_P = NULL;
23969089SVasumathi.Sundaram@Sun.COM 	uint_t verbose = FALSE;
2397*11042SErik.Nordmark@Sun.COM 	ip_stack_t *ipst = NULL;
23989089SVasumathi.Sundaram@Sun.COM 
23999089SVasumathi.Sundaram@Sun.COM 	if (mdb_getopts(argc, argv,
24009089SVasumathi.Sundaram@Sun.COM 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
2401*11042SErik.Nordmark@Sun.COM 	    's', MDB_OPT_STR, &zone_name,
24029089SVasumathi.Sundaram@Sun.COM 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
24039089SVasumathi.Sundaram@Sun.COM 		return (DCMD_USAGE);
24049089SVasumathi.Sundaram@Sun.COM 
2405*11042SErik.Nordmark@Sun.COM 	/* Follow the specified zone name to find a ip_stack_t*. */
2406*11042SErik.Nordmark@Sun.COM 	if (zone_name != NULL) {
2407*11042SErik.Nordmark@Sun.COM 		ipst = zone_to_ips(zone_name);
2408*11042SErik.Nordmark@Sun.COM 		if (ipst == NULL)
2409*11042SErik.Nordmark@Sun.COM 			return (DCMD_USAGE);
2410*11042SErik.Nordmark@Sun.COM 	}
2411*11042SErik.Nordmark@Sun.COM 
24129089SVasumathi.Sundaram@Sun.COM 	if (opt_P != NULL) {
24139089SVasumathi.Sundaram@Sun.COM 		if (strcmp("v4", opt_P) == 0) {
24149089SVasumathi.Sundaram@Sun.COM 			ipversion = IPV4_VERSION;
24159089SVasumathi.Sundaram@Sun.COM 		} else if (strcmp("v6", opt_P) == 0) {
24169089SVasumathi.Sundaram@Sun.COM 			ipversion = IPV6_VERSION;
24179089SVasumathi.Sundaram@Sun.COM 		} else {
24189089SVasumathi.Sundaram@Sun.COM 			mdb_warn("invalid protocol '%s'\n", opt_P);
24199089SVasumathi.Sundaram@Sun.COM 			return (DCMD_USAGE);
24209089SVasumathi.Sundaram@Sun.COM 		}
24219089SVasumathi.Sundaram@Sun.COM 	}
24229089SVasumathi.Sundaram@Sun.COM 
24239089SVasumathi.Sundaram@Sun.COM 	id.verbose = verbose;
24249089SVasumathi.Sundaram@Sun.COM 	id.ill_addr = addr;
24259089SVasumathi.Sundaram@Sun.COM 	id.ill_ipversion = ipversion;
2426*11042SErik.Nordmark@Sun.COM 	id.ill_ipst = ipst;
24279089SVasumathi.Sundaram@Sun.COM 
24289089SVasumathi.Sundaram@Sun.COM 	ill_header(verbose);
24299089SVasumathi.Sundaram@Sun.COM 	if (flags & DCMD_ADDRSPEC) {
24309089SVasumathi.Sundaram@Sun.COM 		if (mdb_vread(&ill_data, sizeof (ill_t), addr) == -1) {
24319089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to read ill at %p\n", addr);
24329089SVasumathi.Sundaram@Sun.COM 			return (DCMD_ERR);
24339089SVasumathi.Sundaram@Sun.COM 		}
24349089SVasumathi.Sundaram@Sun.COM 		(void) ill_format(addr, &ill_data, &id);
24359089SVasumathi.Sundaram@Sun.COM 	} else {
24369089SVasumathi.Sundaram@Sun.COM 		if (mdb_walk("ill", (mdb_walk_cb_t)ill_cb, &id) == -1) {
24379089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to walk ills\n");
24389089SVasumathi.Sundaram@Sun.COM 			return (DCMD_ERR);
24399089SVasumathi.Sundaram@Sun.COM 		}
24409089SVasumathi.Sundaram@Sun.COM 	}
24419089SVasumathi.Sundaram@Sun.COM 	return (DCMD_OK);
24429089SVasumathi.Sundaram@Sun.COM }
24439089SVasumathi.Sundaram@Sun.COM 
24449089SVasumathi.Sundaram@Sun.COM static void
24459089SVasumathi.Sundaram@Sun.COM ill_help(void)
24469089SVasumathi.Sundaram@Sun.COM {
24479089SVasumathi.Sundaram@Sun.COM 	mdb_printf("Prints the following fields: ill ptr, name, "
24489089SVasumathi.Sundaram@Sun.COM 	    "IP version, count, ill type and ill flags.\n"
24499089SVasumathi.Sundaram@Sun.COM 	    "The count field is a sum of individual refcnts and is expanded "
24509089SVasumathi.Sundaram@Sun.COM 	    "with the -v option.\n\n");
24519089SVasumathi.Sundaram@Sun.COM 	mdb_printf("Options:\n");
24529089SVasumathi.Sundaram@Sun.COM 	mdb_printf("\t-P v4 | v6"
24539089SVasumathi.Sundaram@Sun.COM 	    "\tfilter ill structures for the specified protocol\n");
24549089SVasumathi.Sundaram@Sun.COM }
24559089SVasumathi.Sundaram@Sun.COM 
24569089SVasumathi.Sundaram@Sun.COM static int
24579089SVasumathi.Sundaram@Sun.COM ip_list_walk_init(mdb_walk_state_t *wsp)
24589089SVasumathi.Sundaram@Sun.COM {
24599089SVasumathi.Sundaram@Sun.COM 	const ip_list_walk_arg_t *arg = wsp->walk_arg;
24609089SVasumathi.Sundaram@Sun.COM 	ip_list_walk_data_t *iw;
24619089SVasumathi.Sundaram@Sun.COM 	uintptr_t addr = (uintptr_t)(wsp->walk_addr + arg->off);
24629089SVasumathi.Sundaram@Sun.COM 
24639089SVasumathi.Sundaram@Sun.COM 	if (wsp->walk_addr == NULL) {
24649089SVasumathi.Sundaram@Sun.COM 		mdb_warn("only local walks supported\n");
24659089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
24669089SVasumathi.Sundaram@Sun.COM 	}
24679089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t),
24689089SVasumathi.Sundaram@Sun.COM 	    addr) == -1) {
24699089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read list head at %p", addr);
24709089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
24719089SVasumathi.Sundaram@Sun.COM 	}
24729089SVasumathi.Sundaram@Sun.COM 	iw = mdb_alloc(sizeof (ip_list_walk_data_t), UM_SLEEP);
24739089SVasumathi.Sundaram@Sun.COM 	iw->nextoff = arg->nextp_off;
24749089SVasumathi.Sundaram@Sun.COM 	wsp->walk_data = iw;
24759089SVasumathi.Sundaram@Sun.COM 
24769089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
24779089SVasumathi.Sundaram@Sun.COM }
24789089SVasumathi.Sundaram@Sun.COM 
24799089SVasumathi.Sundaram@Sun.COM static int
24809089SVasumathi.Sundaram@Sun.COM ip_list_walk_step(mdb_walk_state_t *wsp)
24819089SVasumathi.Sundaram@Sun.COM {
24829089SVasumathi.Sundaram@Sun.COM 	ip_list_walk_data_t *iw = wsp->walk_data;
24839089SVasumathi.Sundaram@Sun.COM 	uintptr_t addr = wsp->walk_addr;
24849089SVasumathi.Sundaram@Sun.COM 
24859089SVasumathi.Sundaram@Sun.COM 	if (addr == NULL)
24869089SVasumathi.Sundaram@Sun.COM 		return (WALK_DONE);
24879089SVasumathi.Sundaram@Sun.COM 	wsp->walk_addr = addr + iw->nextoff;
24889089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t),
24899089SVasumathi.Sundaram@Sun.COM 	    wsp->walk_addr) == -1) {
24909089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read list node at %p", addr);
24919089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
24929089SVasumathi.Sundaram@Sun.COM 	}
24939089SVasumathi.Sundaram@Sun.COM 	return (wsp->walk_callback(addr, iw, wsp->walk_cbdata));
24949089SVasumathi.Sundaram@Sun.COM }
24959089SVasumathi.Sundaram@Sun.COM 
24969089SVasumathi.Sundaram@Sun.COM static void
24979089SVasumathi.Sundaram@Sun.COM ip_list_walk_fini(mdb_walk_state_t *wsp)
24989089SVasumathi.Sundaram@Sun.COM {
24999089SVasumathi.Sundaram@Sun.COM 	mdb_free(wsp->walk_data, sizeof (ip_list_walk_data_t));
25009089SVasumathi.Sundaram@Sun.COM }
25019089SVasumathi.Sundaram@Sun.COM 
25029089SVasumathi.Sundaram@Sun.COM static int
25039089SVasumathi.Sundaram@Sun.COM ipif_walk_init(mdb_walk_state_t *wsp)
25049089SVasumathi.Sundaram@Sun.COM {
25059089SVasumathi.Sundaram@Sun.COM 	if (mdb_layered_walk("ill", wsp) == -1) {
25069089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't walk 'ills'");
25079089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
25089089SVasumathi.Sundaram@Sun.COM 	}
25099089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
25109089SVasumathi.Sundaram@Sun.COM }
25119089SVasumathi.Sundaram@Sun.COM 
25129089SVasumathi.Sundaram@Sun.COM static int
25139089SVasumathi.Sundaram@Sun.COM ipif_walk_step(mdb_walk_state_t *wsp)
25149089SVasumathi.Sundaram@Sun.COM {
25159089SVasumathi.Sundaram@Sun.COM 	if (mdb_pwalk("ipif_list", wsp->walk_callback, wsp->walk_cbdata,
25169089SVasumathi.Sundaram@Sun.COM 	    wsp->walk_addr) == -1) {
25179089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't walk 'ipif_list'");
25189089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
25199089SVasumathi.Sundaram@Sun.COM 	}
25209089SVasumathi.Sundaram@Sun.COM 
25219089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
25229089SVasumathi.Sundaram@Sun.COM }
25239089SVasumathi.Sundaram@Sun.COM 
25249089SVasumathi.Sundaram@Sun.COM /* ARGSUSED */
25259089SVasumathi.Sundaram@Sun.COM static int
25269089SVasumathi.Sundaram@Sun.COM ipif_cb(uintptr_t addr, const ipif_walk_data_t *iw, ipif_cbdata_t *id)
25279089SVasumathi.Sundaram@Sun.COM {
25289089SVasumathi.Sundaram@Sun.COM 	ipif_t ipif;
25299089SVasumathi.Sundaram@Sun.COM 
25309089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&ipif, sizeof (ipif_t), (uintptr_t)addr) == -1) {
25319089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read ipif at %p", addr);
25329089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
25339089SVasumathi.Sundaram@Sun.COM 	}
25349089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&id->ill, sizeof (ill_t),
25359089SVasumathi.Sundaram@Sun.COM 	    (uintptr_t)ipif.ipif_ill) == -1) {
25369089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read ill at %p", ipif.ipif_ill);
25379089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
25389089SVasumathi.Sundaram@Sun.COM 	}
25399089SVasumathi.Sundaram@Sun.COM 	(void) ipif_format((uintptr_t)addr, &ipif, id);
25409089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
25419089SVasumathi.Sundaram@Sun.COM }
25429089SVasumathi.Sundaram@Sun.COM 
25439089SVasumathi.Sundaram@Sun.COM static void
25449089SVasumathi.Sundaram@Sun.COM ipif_header(boolean_t verbose)
25459089SVasumathi.Sundaram@Sun.COM {
25469089SVasumathi.Sundaram@Sun.COM 	if (verbose) {
25479089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?s %-10s %-3s %-?s %-8s %-30s\n",
25489089SVasumathi.Sundaram@Sun.COM 		    "ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS");
25499089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%s\n%s\n",
25509089SVasumathi.Sundaram@Sun.COM 		    "LCLADDR", "BROADCAST");
25519089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%<u>%80s%</u>\n", "");
25529089SVasumathi.Sundaram@Sun.COM 	} else {
25539089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?s %-10s %6s %-?s %-8s %-30s\n",
25549089SVasumathi.Sundaram@Sun.COM 		    "ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS");
25559089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%s\n%<u>%80s%</u>\n", "LCLADDR", "");
25569089SVasumathi.Sundaram@Sun.COM 	}
25579089SVasumathi.Sundaram@Sun.COM }
25589089SVasumathi.Sundaram@Sun.COM 
25599089SVasumathi.Sundaram@Sun.COM #ifdef _BIG_ENDIAN
25609089SVasumathi.Sundaram@Sun.COM #define	ip_ntohl_32(x)	((x) & 0xffffffff)
25619089SVasumathi.Sundaram@Sun.COM #else
25629089SVasumathi.Sundaram@Sun.COM #define	ip_ntohl_32(x)	(((uint32_t)(x) << 24) | \
25639089SVasumathi.Sundaram@Sun.COM 			(((uint32_t)(x) << 8) & 0xff0000) | \
25649089SVasumathi.Sundaram@Sun.COM 			(((uint32_t)(x) >> 8) & 0xff00) | \
25659089SVasumathi.Sundaram@Sun.COM 			((uint32_t)(x)  >> 24))
25669089SVasumathi.Sundaram@Sun.COM #endif
25679089SVasumathi.Sundaram@Sun.COM 
25689089SVasumathi.Sundaram@Sun.COM int
25699089SVasumathi.Sundaram@Sun.COM mask_to_prefixlen(int af, const in6_addr_t *addr)
25709089SVasumathi.Sundaram@Sun.COM {
25719089SVasumathi.Sundaram@Sun.COM 	int len = 0;
25729089SVasumathi.Sundaram@Sun.COM 	int i;
25739089SVasumathi.Sundaram@Sun.COM 	uint_t mask = 0;
25749089SVasumathi.Sundaram@Sun.COM 
25759089SVasumathi.Sundaram@Sun.COM 	if (af == AF_INET6) {
25769089SVasumathi.Sundaram@Sun.COM 		for (i = 0; i < 4; i++) {
25779089SVasumathi.Sundaram@Sun.COM 			if (addr->s6_addr32[i] == 0xffffffff) {
25789089SVasumathi.Sundaram@Sun.COM 				len += 32;
25799089SVasumathi.Sundaram@Sun.COM 			} else {
25809089SVasumathi.Sundaram@Sun.COM 				mask = addr->s6_addr32[i];
25819089SVasumathi.Sundaram@Sun.COM 				break;
25829089SVasumathi.Sundaram@Sun.COM 			}
25839089SVasumathi.Sundaram@Sun.COM 		}
25849089SVasumathi.Sundaram@Sun.COM 	} else {
25859089SVasumathi.Sundaram@Sun.COM 		mask = V4_PART_OF_V6((*addr));
25869089SVasumathi.Sundaram@Sun.COM 	}
25879089SVasumathi.Sundaram@Sun.COM 	if (mask > 0)
25889089SVasumathi.Sundaram@Sun.COM 		len += (33 - mdb_ffs(ip_ntohl_32(mask)));
25899089SVasumathi.Sundaram@Sun.COM 	return (len);
25909089SVasumathi.Sundaram@Sun.COM }
25919089SVasumathi.Sundaram@Sun.COM 
25929089SVasumathi.Sundaram@Sun.COM static int
25939089SVasumathi.Sundaram@Sun.COM ipif_format(uintptr_t addr, const void *ipifptr, void *ipif_cb_arg)
25949089SVasumathi.Sundaram@Sun.COM {
25959089SVasumathi.Sundaram@Sun.COM 	const ipif_t *ipif = ipifptr;
25969089SVasumathi.Sundaram@Sun.COM 	ipif_cbdata_t *ipifcb = ipif_cb_arg;
25979089SVasumathi.Sundaram@Sun.COM 	boolean_t verbose = ipifcb->verbose;
25989089SVasumathi.Sundaram@Sun.COM 	char ill_name[LIFNAMSIZ];
25999089SVasumathi.Sundaram@Sun.COM 	char buf[LIFNAMSIZ];
26009089SVasumathi.Sundaram@Sun.COM 	int cnt;
26019089SVasumathi.Sundaram@Sun.COM 	static const mdb_bitmask_t sfmasks[] = {
26029089SVasumathi.Sundaram@Sun.COM 		{ "CO",		IPIF_CONDEMNED,		IPIF_CONDEMNED},
26039089SVasumathi.Sundaram@Sun.COM 		{ "CH",		IPIF_CHANGING,		IPIF_CHANGING},
26049089SVasumathi.Sundaram@Sun.COM 		{ "SL",		IPIF_SET_LINKLOCAL,	IPIF_SET_LINKLOCAL},
26059089SVasumathi.Sundaram@Sun.COM 		{ NULL,		0,			0		}
26069089SVasumathi.Sundaram@Sun.COM 	};
26079089SVasumathi.Sundaram@Sun.COM 	static const mdb_bitmask_t fmasks[] = {
26089089SVasumathi.Sundaram@Sun.COM 		{ "UP",		IPIF_UP,		IPIF_UP		},
26099089SVasumathi.Sundaram@Sun.COM 		{ "UNN",	IPIF_UNNUMBERED,	IPIF_UNNUMBERED},
26109089SVasumathi.Sundaram@Sun.COM 		{ "DHCP",	IPIF_DHCPRUNNING,	IPIF_DHCPRUNNING},
26119089SVasumathi.Sundaram@Sun.COM 		{ "PRIV",	IPIF_PRIVATE,		IPIF_PRIVATE},
26129089SVasumathi.Sundaram@Sun.COM 		{ "NOXMT",	IPIF_NOXMIT,		IPIF_NOXMIT},
26139089SVasumathi.Sundaram@Sun.COM 		{ "NOLCL",	IPIF_NOLOCAL,		IPIF_NOLOCAL},
26149089SVasumathi.Sundaram@Sun.COM 		{ "DEPR",	IPIF_DEPRECATED,	IPIF_DEPRECATED},
26159089SVasumathi.Sundaram@Sun.COM 		{ "PREF",	IPIF_PREFERRED,		IPIF_PREFERRED},
26169089SVasumathi.Sundaram@Sun.COM 		{ "TEMP",	IPIF_TEMPORARY,		IPIF_TEMPORARY},
26179089SVasumathi.Sundaram@Sun.COM 		{ "ACONF",	IPIF_ADDRCONF,		IPIF_ADDRCONF},
26189089SVasumathi.Sundaram@Sun.COM 		{ "ANY",	IPIF_ANYCAST,		IPIF_ANYCAST},
26199089SVasumathi.Sundaram@Sun.COM 		{ "NFAIL",	IPIF_NOFAILOVER,	IPIF_NOFAILOVER},
26209089SVasumathi.Sundaram@Sun.COM 		{ NULL,		0,			0		}
26219089SVasumathi.Sundaram@Sun.COM 	};
26229089SVasumathi.Sundaram@Sun.COM 	char flagsbuf[2 * A_CNT(fmasks)];
26239089SVasumathi.Sundaram@Sun.COM 	char bitfields[A_CNT(fmasks)];
26249089SVasumathi.Sundaram@Sun.COM 	char sflagsbuf[A_CNT(sfmasks)];
26259089SVasumathi.Sundaram@Sun.COM 	char sbuf[DEFCOLS], addrstr[INET6_ADDRSTRLEN];
26269089SVasumathi.Sundaram@Sun.COM 	int ipver = ipifcb->ipif_ipversion;
26279089SVasumathi.Sundaram@Sun.COM 	int af;
26289089SVasumathi.Sundaram@Sun.COM 
26299089SVasumathi.Sundaram@Sun.COM 	if (ipver != 0) {
26309089SVasumathi.Sundaram@Sun.COM 		if ((ipver == IPV4_VERSION && ipifcb->ill.ill_isv6) ||
26319089SVasumathi.Sundaram@Sun.COM 		    (ipver == IPV6_VERSION && !ipifcb->ill.ill_isv6)) {
26329089SVasumathi.Sundaram@Sun.COM 			return (WALK_NEXT);
26339089SVasumathi.Sundaram@Sun.COM 		}
26349089SVasumathi.Sundaram@Sun.COM 	}
26359089SVasumathi.Sundaram@Sun.COM 	if ((mdb_readstr(ill_name, MIN(LIFNAMSIZ,
26369089SVasumathi.Sundaram@Sun.COM 	    ipifcb->ill.ill_name_length),
26379089SVasumathi.Sundaram@Sun.COM 	    (uintptr_t)ipifcb->ill.ill_name)) == -1) {
26389089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read ill_name of ill %p\n", ipifcb->ill);
26399089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
26409089SVasumathi.Sundaram@Sun.COM 	}
26419089SVasumathi.Sundaram@Sun.COM 	if (ipif->ipif_id != 0) {
26429089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(buf, LIFNAMSIZ, "%s:%d",
26439089SVasumathi.Sundaram@Sun.COM 		    ill_name, ipif->ipif_id);
26449089SVasumathi.Sundaram@Sun.COM 	} else {
26459089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(buf, LIFNAMSIZ, "%s", ill_name);
26469089SVasumathi.Sundaram@Sun.COM 	}
26479089SVasumathi.Sundaram@Sun.COM 	mdb_snprintf(bitfields, sizeof (bitfields), "%s",
26489089SVasumathi.Sundaram@Sun.COM 	    ipif->ipif_addr_ready ? ",ADR" : "",
26499089SVasumathi.Sundaram@Sun.COM 	    ipif->ipif_was_up ? ",WU" : "",
2650*11042SErik.Nordmark@Sun.COM 	    ipif->ipif_was_dup ? ",WD" : "");
26519089SVasumathi.Sundaram@Sun.COM 	mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%llb%s",
26529089SVasumathi.Sundaram@Sun.COM 	    ipif->ipif_flags, fmasks, bitfields);
26539089SVasumathi.Sundaram@Sun.COM 	mdb_snprintf(sflagsbuf, sizeof (sflagsbuf), "%b",
26549089SVasumathi.Sundaram@Sun.COM 	    ipif->ipif_state_flags, sfmasks);
26559089SVasumathi.Sundaram@Sun.COM 
2656*11042SErik.Nordmark@Sun.COM 	cnt = ipif->ipif_refcnt;
26579089SVasumathi.Sundaram@Sun.COM 
26589089SVasumathi.Sundaram@Sun.COM 	if (ipifcb->ill.ill_isv6) {
26599089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(addrstr, sizeof (addrstr), "%N",
26609089SVasumathi.Sundaram@Sun.COM 		    &ipif->ipif_v6lcl_addr);
26619089SVasumathi.Sundaram@Sun.COM 		af = AF_INET6;
26629089SVasumathi.Sundaram@Sun.COM 	} else {
26639089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(addrstr, sizeof (addrstr), "%I",
26649089SVasumathi.Sundaram@Sun.COM 		    V4_PART_OF_V6((ipif->ipif_v6lcl_addr)));
26659089SVasumathi.Sundaram@Sun.COM 		af = AF_INET;
26669089SVasumathi.Sundaram@Sun.COM 	}
26679089SVasumathi.Sundaram@Sun.COM 
26689089SVasumathi.Sundaram@Sun.COM 	if (verbose) {
26699089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?p %-10s %3d %-?p %-8s %-30s\n",
26709089SVasumathi.Sundaram@Sun.COM 		    addr, buf, cnt, ipif->ipif_ill,
26719089SVasumathi.Sundaram@Sun.COM 		    sflagsbuf, flagsbuf);
26729089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(sbuf, sizeof (sbuf), "%*s %12s",
26739089SVasumathi.Sundaram@Sun.COM 		    sizeof (uintptr_t) * 2, "", "");
26749089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%s |\n%s +---> %4d %-15s "
26759089SVasumathi.Sundaram@Sun.COM 		    "Active consistent reader cnt\n",
26769089SVasumathi.Sundaram@Sun.COM 		    sbuf, sbuf, ipif->ipif_refcnt, "ipif_refcnt");
26779089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-s/%d\n",
26789089SVasumathi.Sundaram@Sun.COM 		    addrstr, mask_to_prefixlen(af, &ipif->ipif_v6net_mask));
26799089SVasumathi.Sundaram@Sun.COM 		if (ipifcb->ill.ill_isv6) {
26809089SVasumathi.Sundaram@Sun.COM 			mdb_printf("%-N\n", &ipif->ipif_v6brd_addr);
26819089SVasumathi.Sundaram@Sun.COM 		} else {
26829089SVasumathi.Sundaram@Sun.COM 			mdb_printf("%-I\n",
26839089SVasumathi.Sundaram@Sun.COM 			    V4_PART_OF_V6((ipif->ipif_v6brd_addr)));
26849089SVasumathi.Sundaram@Sun.COM 		}
26859089SVasumathi.Sundaram@Sun.COM 	} else {
26869089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?p %-10s %6d %-?p %-8s %-30s\n",
26879089SVasumathi.Sundaram@Sun.COM 		    addr, buf, cnt, ipif->ipif_ill,
26889089SVasumathi.Sundaram@Sun.COM 		    sflagsbuf, flagsbuf);
26899089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-s/%d\n",
26909089SVasumathi.Sundaram@Sun.COM 		    addrstr, mask_to_prefixlen(af, &ipif->ipif_v6net_mask));
26919089SVasumathi.Sundaram@Sun.COM 	}
26929089SVasumathi.Sundaram@Sun.COM 
26939089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
26949089SVasumathi.Sundaram@Sun.COM }
26959089SVasumathi.Sundaram@Sun.COM 
26969089SVasumathi.Sundaram@Sun.COM static int
26979089SVasumathi.Sundaram@Sun.COM ipif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
26989089SVasumathi.Sundaram@Sun.COM {
26999089SVasumathi.Sundaram@Sun.COM 	ipif_t ipif;
27009089SVasumathi.Sundaram@Sun.COM 	ipif_cbdata_t id;
27019089SVasumathi.Sundaram@Sun.COM 	int ipversion = 0;
27029089SVasumathi.Sundaram@Sun.COM 	const char *opt_P = NULL;
27039089SVasumathi.Sundaram@Sun.COM 	uint_t verbose = FALSE;
27049089SVasumathi.Sundaram@Sun.COM 
27059089SVasumathi.Sundaram@Sun.COM 	if (mdb_getopts(argc, argv,
27069089SVasumathi.Sundaram@Sun.COM 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
27079089SVasumathi.Sundaram@Sun.COM 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
27089089SVasumathi.Sundaram@Sun.COM 		return (DCMD_USAGE);
27099089SVasumathi.Sundaram@Sun.COM 
27109089SVasumathi.Sundaram@Sun.COM 	if (opt_P != NULL) {
27119089SVasumathi.Sundaram@Sun.COM 		if (strcmp("v4", opt_P) == 0) {
27129089SVasumathi.Sundaram@Sun.COM 			ipversion = IPV4_VERSION;
27139089SVasumathi.Sundaram@Sun.COM 		} else if (strcmp("v6", opt_P) == 0) {
27149089SVasumathi.Sundaram@Sun.COM 			ipversion = IPV6_VERSION;
27159089SVasumathi.Sundaram@Sun.COM 		} else {
27169089SVasumathi.Sundaram@Sun.COM 			mdb_warn("invalid protocol '%s'\n", opt_P);
27179089SVasumathi.Sundaram@Sun.COM 			return (DCMD_USAGE);
27189089SVasumathi.Sundaram@Sun.COM 		}
27199089SVasumathi.Sundaram@Sun.COM 	}
27209089SVasumathi.Sundaram@Sun.COM 
27219089SVasumathi.Sundaram@Sun.COM 	id.verbose = verbose;
27229089SVasumathi.Sundaram@Sun.COM 	id.ipif_ipversion = ipversion;
27239089SVasumathi.Sundaram@Sun.COM 
27249089SVasumathi.Sundaram@Sun.COM 	if (flags & DCMD_ADDRSPEC) {
27259089SVasumathi.Sundaram@Sun.COM 		if (mdb_vread(&ipif, sizeof (ipif_t), addr) == -1) {
27269089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to read ipif at %p\n", addr);
27279089SVasumathi.Sundaram@Sun.COM 			return (DCMD_ERR);
27289089SVasumathi.Sundaram@Sun.COM 		}
27299089SVasumathi.Sundaram@Sun.COM 		ipif_header(verbose);
27309089SVasumathi.Sundaram@Sun.COM 		if (mdb_vread(&id.ill, sizeof (ill_t),
27319089SVasumathi.Sundaram@Sun.COM 		    (uintptr_t)ipif.ipif_ill) == -1) {
27329089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to read ill at %p", ipif.ipif_ill);
27339089SVasumathi.Sundaram@Sun.COM 			return (WALK_NEXT);
27349089SVasumathi.Sundaram@Sun.COM 		}
27359089SVasumathi.Sundaram@Sun.COM 		return (ipif_format(addr, &ipif, &id));
27369089SVasumathi.Sundaram@Sun.COM 	} else {
27379089SVasumathi.Sundaram@Sun.COM 		ipif_header(verbose);
27389089SVasumathi.Sundaram@Sun.COM 		if (mdb_walk("ipif", (mdb_walk_cb_t)ipif_cb, &id) == -1) {
27399089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to walk ipifs\n");
27409089SVasumathi.Sundaram@Sun.COM 			return (DCMD_ERR);
27419089SVasumathi.Sundaram@Sun.COM 		}
27429089SVasumathi.Sundaram@Sun.COM 	}
27439089SVasumathi.Sundaram@Sun.COM 	return (DCMD_OK);
27449089SVasumathi.Sundaram@Sun.COM }
27459089SVasumathi.Sundaram@Sun.COM 
27469089SVasumathi.Sundaram@Sun.COM static void
27479089SVasumathi.Sundaram@Sun.COM ipif_help(void)
27489089SVasumathi.Sundaram@Sun.COM {
27499089SVasumathi.Sundaram@Sun.COM 	mdb_printf("Prints the following fields: ipif ptr, name, "
27509089SVasumathi.Sundaram@Sun.COM 	    "count, ill ptr, state flags and ipif flags.\n"
27519089SVasumathi.Sundaram@Sun.COM 	    "The count field is a sum of individual refcnts and is expanded "
27529089SVasumathi.Sundaram@Sun.COM 	    "with the -v option.\n"
27539089SVasumathi.Sundaram@Sun.COM 	    "The flags field shows the following:"
27549089SVasumathi.Sundaram@Sun.COM 	    "\n\tUNN -> UNNUMBERED, DHCP -> DHCPRUNNING, PRIV -> PRIVATE, "
27559089SVasumathi.Sundaram@Sun.COM 	    "\n\tNOXMT -> NOXMIT, NOLCL -> NOLOCAL, DEPR -> DEPRECATED, "
27569089SVasumathi.Sundaram@Sun.COM 	    "\n\tPREF -> PREFERRED, TEMP -> TEMPORARY, ACONF -> ADDRCONF, "
27579089SVasumathi.Sundaram@Sun.COM 	    "\n\tANY -> ANYCAST, NFAIL -> NOFAILOVER, "
27589089SVasumathi.Sundaram@Sun.COM 	    "\n\tADR -> ipif_addr_ready, MU -> ipif_multicast_up, "
27599089SVasumathi.Sundaram@Sun.COM 	    "\n\tWU -> ipif_was_up, WD -> ipif_was_dup, "
27609089SVasumathi.Sundaram@Sun.COM 	    "JA -> ipif_joined_allhosts.\n\n");
27619089SVasumathi.Sundaram@Sun.COM 	mdb_printf("Options:\n");
27629089SVasumathi.Sundaram@Sun.COM 	mdb_printf("\t-P v4 | v6"
27639089SVasumathi.Sundaram@Sun.COM 	    "\tfilter ipif structures on ills for the specified protocol\n");
27649089SVasumathi.Sundaram@Sun.COM }
27659089SVasumathi.Sundaram@Sun.COM 
27669089SVasumathi.Sundaram@Sun.COM static int
27679089SVasumathi.Sundaram@Sun.COM conn_status_walk_fanout(uintptr_t addr, mdb_walk_state_t *wsp,
27689089SVasumathi.Sundaram@Sun.COM     const char *walkname)
27699089SVasumathi.Sundaram@Sun.COM {
27709089SVasumathi.Sundaram@Sun.COM 	if (mdb_pwalk(walkname, wsp->walk_callback, wsp->walk_cbdata,
27719089SVasumathi.Sundaram@Sun.COM 	    addr) == -1) {
27729089SVasumathi.Sundaram@Sun.COM 		mdb_warn("couldn't walk '%s' at %p", walkname, addr);
27739089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
27749089SVasumathi.Sundaram@Sun.COM 	}
27759089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
27769089SVasumathi.Sundaram@Sun.COM }
27779089SVasumathi.Sundaram@Sun.COM 
27789089SVasumathi.Sundaram@Sun.COM static int
27799089SVasumathi.Sundaram@Sun.COM conn_status_walk_step(mdb_walk_state_t *wsp)
27809089SVasumathi.Sundaram@Sun.COM {
27819089SVasumathi.Sundaram@Sun.COM 	uintptr_t addr = wsp->walk_addr;
27829089SVasumathi.Sundaram@Sun.COM 
27839089SVasumathi.Sundaram@Sun.COM 	(void) conn_status_walk_fanout(addr, wsp, "udp_hash");
27849089SVasumathi.Sundaram@Sun.COM 	(void) conn_status_walk_fanout(addr, wsp, "conn_hash");
27859089SVasumathi.Sundaram@Sun.COM 	(void) conn_status_walk_fanout(addr, wsp, "bind_hash");
27869089SVasumathi.Sundaram@Sun.COM 	(void) conn_status_walk_fanout(addr, wsp, "proto_hash");
27879089SVasumathi.Sundaram@Sun.COM 	(void) conn_status_walk_fanout(addr, wsp, "proto_v6_hash");
27889089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
27899089SVasumathi.Sundaram@Sun.COM }
27909089SVasumathi.Sundaram@Sun.COM 
27919089SVasumathi.Sundaram@Sun.COM /* ARGSUSED */
27929089SVasumathi.Sundaram@Sun.COM static int
27939089SVasumathi.Sundaram@Sun.COM conn_status_cb(uintptr_t addr, const void *walk_data,
27949089SVasumathi.Sundaram@Sun.COM     void *private)
27959089SVasumathi.Sundaram@Sun.COM {
27969089SVasumathi.Sundaram@Sun.COM 	netstack_t nss;
27979089SVasumathi.Sundaram@Sun.COM 	char src_addrstr[INET6_ADDRSTRLEN];
27989089SVasumathi.Sundaram@Sun.COM 	char rem_addrstr[INET6_ADDRSTRLEN];
27999089SVasumathi.Sundaram@Sun.COM 	const ipcl_hash_walk_data_t *iw = walk_data;
28009089SVasumathi.Sundaram@Sun.COM 	conn_t *conn = iw->conn;
28019089SVasumathi.Sundaram@Sun.COM 
28029089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(conn, sizeof (conn_t), addr) == -1) {
28039089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read conn_t at %p", addr);
28049089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
28059089SVasumathi.Sundaram@Sun.COM 	}
28069089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&nss, sizeof (nss),
28079089SVasumathi.Sundaram@Sun.COM 	    (uintptr_t)conn->conn_netstack) == -1) {
28089089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read netstack_t %p",
28099089SVasumathi.Sundaram@Sun.COM 		    conn->conn_netstack);
28109089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
28119089SVasumathi.Sundaram@Sun.COM 	}
28129089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%-?p %-?p %?d %?d\n", addr, conn->conn_wq,
28139089SVasumathi.Sundaram@Sun.COM 	    nss.netstack_stackid, conn->conn_zoneid);
28149089SVasumathi.Sundaram@Sun.COM 
2815*11042SErik.Nordmark@Sun.COM 	if (conn->conn_family == AF_INET6) {
28169089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(src_addrstr, sizeof (rem_addrstr), "%N",
2817*11042SErik.Nordmark@Sun.COM 		    &conn->conn_laddr_v6);
28189089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(rem_addrstr, sizeof (rem_addrstr), "%N",
2819*11042SErik.Nordmark@Sun.COM 		    &conn->conn_faddr_v6);
28209089SVasumathi.Sundaram@Sun.COM 	} else {
28219089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(src_addrstr, sizeof (src_addrstr), "%I",
2822*11042SErik.Nordmark@Sun.COM 		    V4_PART_OF_V6((conn->conn_laddr_v6)));
28239089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(rem_addrstr, sizeof (rem_addrstr), "%I",
2824*11042SErik.Nordmark@Sun.COM 		    V4_PART_OF_V6((conn->conn_faddr_v6)));
28259089SVasumathi.Sundaram@Sun.COM 	}
28269089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%s:%-5d\n%s:%-5d\n",
28279089SVasumathi.Sundaram@Sun.COM 	    src_addrstr, conn->conn_lport, rem_addrstr, conn->conn_fport);
28289089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
28299089SVasumathi.Sundaram@Sun.COM }
28309089SVasumathi.Sundaram@Sun.COM 
28319089SVasumathi.Sundaram@Sun.COM static void
28329089SVasumathi.Sundaram@Sun.COM conn_header(void)
28339089SVasumathi.Sundaram@Sun.COM {
28349089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%-?s %-?s %?s %?s\n%s\n%s\n",
28359089SVasumathi.Sundaram@Sun.COM 	    "ADDR", "WQ", "STACK", "ZONE", "SRC:PORT", "DEST:PORT");
28369089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%<u>%80s%</u>\n", "");
28379089SVasumathi.Sundaram@Sun.COM }
28389089SVasumathi.Sundaram@Sun.COM 
28399089SVasumathi.Sundaram@Sun.COM /*ARGSUSED*/
28409089SVasumathi.Sundaram@Sun.COM static int
28419089SVasumathi.Sundaram@Sun.COM conn_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
28429089SVasumathi.Sundaram@Sun.COM {
28439089SVasumathi.Sundaram@Sun.COM 	conn_header();
28449089SVasumathi.Sundaram@Sun.COM 	if (flags & DCMD_ADDRSPEC) {
28459089SVasumathi.Sundaram@Sun.COM 		(void) conn_status_cb(addr, NULL, NULL);
28469089SVasumathi.Sundaram@Sun.COM 	} else {
28479089SVasumathi.Sundaram@Sun.COM 		if (mdb_walk("conn_status", (mdb_walk_cb_t)conn_status_cb,
28489089SVasumathi.Sundaram@Sun.COM 		    NULL) == -1) {
28499089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to walk conn_fanout");
28509089SVasumathi.Sundaram@Sun.COM 			return (DCMD_ERR);
28519089SVasumathi.Sundaram@Sun.COM 		}
28529089SVasumathi.Sundaram@Sun.COM 	}
28539089SVasumathi.Sundaram@Sun.COM 	return (DCMD_OK);
28549089SVasumathi.Sundaram@Sun.COM }
28559089SVasumathi.Sundaram@Sun.COM 
28569089SVasumathi.Sundaram@Sun.COM static void
28579089SVasumathi.Sundaram@Sun.COM conn_status_help(void)
28589089SVasumathi.Sundaram@Sun.COM {
28599089SVasumathi.Sundaram@Sun.COM 	mdb_printf("Prints conn_t structures from the following hash tables: "
28609089SVasumathi.Sundaram@Sun.COM 	    "\n\tips_ipcl_udp_fanout\n\tips_ipcl_bind_fanout"
2861*11042SErik.Nordmark@Sun.COM 	    "\n\tips_ipcl_conn_fanout\n\tips_ipcl_proto_fanout_v4"
28629089SVasumathi.Sundaram@Sun.COM 	    "\n\tips_ipcl_proto_fanout_v6\n");
28639089SVasumathi.Sundaram@Sun.COM }
28649089SVasumathi.Sundaram@Sun.COM 
28659089SVasumathi.Sundaram@Sun.COM static int
28669089SVasumathi.Sundaram@Sun.COM srcid_walk_step(mdb_walk_state_t *wsp)
28679089SVasumathi.Sundaram@Sun.COM {
28689089SVasumathi.Sundaram@Sun.COM 	if (mdb_pwalk("srcid_list", wsp->walk_callback, wsp->walk_cbdata,
28699089SVasumathi.Sundaram@Sun.COM 	    wsp->walk_addr) == -1) {
28709089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't walk 'srcid_list'");
28719089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
28729089SVasumathi.Sundaram@Sun.COM 	}
28739089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
28749089SVasumathi.Sundaram@Sun.COM }
28759089SVasumathi.Sundaram@Sun.COM 
28769089SVasumathi.Sundaram@Sun.COM /* ARGSUSED */
28779089SVasumathi.Sundaram@Sun.COM static int
28789089SVasumathi.Sundaram@Sun.COM srcid_status_cb(uintptr_t addr, const void *walk_data,
28799089SVasumathi.Sundaram@Sun.COM     void *private)
28809089SVasumathi.Sundaram@Sun.COM {
28819089SVasumathi.Sundaram@Sun.COM 	srcid_map_t smp;
28829089SVasumathi.Sundaram@Sun.COM 
28839089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&smp, sizeof (srcid_map_t), addr) == -1) {
28849089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read srcid_map at %p", addr);
28859089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
28869089SVasumathi.Sundaram@Sun.COM 	}
28879089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%-?p %3d %4d %6d %N\n",
28889089SVasumathi.Sundaram@Sun.COM 	    addr, smp.sm_srcid, smp.sm_zoneid, smp.sm_refcnt,
28899089SVasumathi.Sundaram@Sun.COM 	    &smp.sm_addr);
28909089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
28919089SVasumathi.Sundaram@Sun.COM }
28929089SVasumathi.Sundaram@Sun.COM 
28939089SVasumathi.Sundaram@Sun.COM static void
28949089SVasumathi.Sundaram@Sun.COM srcid_header(void)
28959089SVasumathi.Sundaram@Sun.COM {
28969089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%-?s %3s %4s %6s %s\n",
28979089SVasumathi.Sundaram@Sun.COM 	    "ADDR", "ID", "ZONE", "REFCNT", "IPADDR");
28989089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%<u>%80s%</u>\n", "");
28999089SVasumathi.Sundaram@Sun.COM }
29009089SVasumathi.Sundaram@Sun.COM 
29019089SVasumathi.Sundaram@Sun.COM /*ARGSUSED*/
29029089SVasumathi.Sundaram@Sun.COM static int
29039089SVasumathi.Sundaram@Sun.COM srcid_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
29049089SVasumathi.Sundaram@Sun.COM {
29059089SVasumathi.Sundaram@Sun.COM 	srcid_header();
29069089SVasumathi.Sundaram@Sun.COM 	if (flags & DCMD_ADDRSPEC) {
29079089SVasumathi.Sundaram@Sun.COM 		(void) srcid_status_cb(addr, NULL, NULL);
29089089SVasumathi.Sundaram@Sun.COM 	} else {
29099089SVasumathi.Sundaram@Sun.COM 		if (mdb_walk("srcid", (mdb_walk_cb_t)srcid_status_cb,
29109089SVasumathi.Sundaram@Sun.COM 		    NULL) == -1) {
29119089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to walk srcid_map");
29129089SVasumathi.Sundaram@Sun.COM 			return (DCMD_ERR);
29139089SVasumathi.Sundaram@Sun.COM 		}
29149089SVasumathi.Sundaram@Sun.COM 	}
29159089SVasumathi.Sundaram@Sun.COM 	return (DCMD_OK);
29169089SVasumathi.Sundaram@Sun.COM }
291710946SSangeeta.Misra@Sun.COM 
291810946SSangeeta.Misra@Sun.COM static int
291910946SSangeeta.Misra@Sun.COM ilb_stacks_walk_step(mdb_walk_state_t *wsp)
292010946SSangeeta.Misra@Sun.COM {
292110946SSangeeta.Misra@Sun.COM 	uintptr_t kaddr;
292210946SSangeeta.Misra@Sun.COM 	netstack_t nss;
292310946SSangeeta.Misra@Sun.COM 
292410946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
292510946SSangeeta.Misra@Sun.COM 		mdb_warn("can't read netstack at %p", wsp->walk_addr);
292610946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
292710946SSangeeta.Misra@Sun.COM 	}
292810946SSangeeta.Misra@Sun.COM 	kaddr = (uintptr_t)nss.netstack_modules[NS_ILB];
292910946SSangeeta.Misra@Sun.COM 
293010946SSangeeta.Misra@Sun.COM 	return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
293110946SSangeeta.Misra@Sun.COM }
293210946SSangeeta.Misra@Sun.COM 
293310946SSangeeta.Misra@Sun.COM static int
293410946SSangeeta.Misra@Sun.COM ilb_rules_walk_init(mdb_walk_state_t *wsp)
293510946SSangeeta.Misra@Sun.COM {
293610946SSangeeta.Misra@Sun.COM 	ilb_stack_t ilbs;
293710946SSangeeta.Misra@Sun.COM 
293810946SSangeeta.Misra@Sun.COM 	if (wsp->walk_addr == NULL)
293910946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
294010946SSangeeta.Misra@Sun.COM 
294110946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&ilbs, sizeof (ilbs), wsp->walk_addr) == -1) {
294210946SSangeeta.Misra@Sun.COM 		mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr);
294310946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
294410946SSangeeta.Misra@Sun.COM 	}
294510946SSangeeta.Misra@Sun.COM 	if ((wsp->walk_addr = (uintptr_t)ilbs.ilbs_rule_head) != NULL)
294610946SSangeeta.Misra@Sun.COM 		return (WALK_NEXT);
294710946SSangeeta.Misra@Sun.COM 	else
294810946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
294910946SSangeeta.Misra@Sun.COM }
295010946SSangeeta.Misra@Sun.COM 
295110946SSangeeta.Misra@Sun.COM static int
295210946SSangeeta.Misra@Sun.COM ilb_rules_walk_step(mdb_walk_state_t *wsp)
295310946SSangeeta.Misra@Sun.COM {
295410946SSangeeta.Misra@Sun.COM 	ilb_rule_t rule;
295510946SSangeeta.Misra@Sun.COM 	int status;
295610946SSangeeta.Misra@Sun.COM 
295710946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&rule, sizeof (rule), wsp->walk_addr) == -1) {
295810946SSangeeta.Misra@Sun.COM 		mdb_warn("failed to read ilb_rule_t at %p", wsp->walk_addr);
295910946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
296010946SSangeeta.Misra@Sun.COM 	}
296110946SSangeeta.Misra@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, &rule, wsp->walk_cbdata);
296210946SSangeeta.Misra@Sun.COM 	if (status != WALK_NEXT)
296310946SSangeeta.Misra@Sun.COM 		return (status);
296410946SSangeeta.Misra@Sun.COM 	if ((wsp->walk_addr = (uintptr_t)rule.ir_next) == NULL)
296510946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
296610946SSangeeta.Misra@Sun.COM 	else
296710946SSangeeta.Misra@Sun.COM 		return (WALK_NEXT);
296810946SSangeeta.Misra@Sun.COM }
296910946SSangeeta.Misra@Sun.COM 
297010946SSangeeta.Misra@Sun.COM static int
297110946SSangeeta.Misra@Sun.COM ilb_servers_walk_init(mdb_walk_state_t *wsp)
297210946SSangeeta.Misra@Sun.COM {
297310946SSangeeta.Misra@Sun.COM 	ilb_rule_t rule;
297410946SSangeeta.Misra@Sun.COM 
297510946SSangeeta.Misra@Sun.COM 	if (wsp->walk_addr == NULL)
297610946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
297710946SSangeeta.Misra@Sun.COM 
297810946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&rule, sizeof (rule), wsp->walk_addr) == -1) {
297910946SSangeeta.Misra@Sun.COM 		mdb_warn("failed to read ilb_rule_t at %p", wsp->walk_addr);
298010946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
298110946SSangeeta.Misra@Sun.COM 	}
298210946SSangeeta.Misra@Sun.COM 	if ((wsp->walk_addr = (uintptr_t)rule.ir_servers) != NULL)
298310946SSangeeta.Misra@Sun.COM 		return (WALK_NEXT);
298410946SSangeeta.Misra@Sun.COM 	else
298510946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
298610946SSangeeta.Misra@Sun.COM }
298710946SSangeeta.Misra@Sun.COM 
298810946SSangeeta.Misra@Sun.COM static int
298910946SSangeeta.Misra@Sun.COM ilb_servers_walk_step(mdb_walk_state_t *wsp)
299010946SSangeeta.Misra@Sun.COM {
299110946SSangeeta.Misra@Sun.COM 	ilb_server_t server;
299210946SSangeeta.Misra@Sun.COM 	int status;
299310946SSangeeta.Misra@Sun.COM 
299410946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&server, sizeof (server), wsp->walk_addr) == -1) {
299510946SSangeeta.Misra@Sun.COM 		mdb_warn("failed to read ilb_server_t at %p", wsp->walk_addr);
299610946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
299710946SSangeeta.Misra@Sun.COM 	}
299810946SSangeeta.Misra@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, &server, wsp->walk_cbdata);
299910946SSangeeta.Misra@Sun.COM 	if (status != WALK_NEXT)
300010946SSangeeta.Misra@Sun.COM 		return (status);
300110946SSangeeta.Misra@Sun.COM 	if ((wsp->walk_addr = (uintptr_t)server.iser_next) == NULL)
300210946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
300310946SSangeeta.Misra@Sun.COM 	else
300410946SSangeeta.Misra@Sun.COM 		return (WALK_NEXT);
300510946SSangeeta.Misra@Sun.COM }
300610946SSangeeta.Misra@Sun.COM 
300710946SSangeeta.Misra@Sun.COM /*
300810946SSangeeta.Misra@Sun.COM  * Helper structure for ilb_nat_src walker.  It stores the current index of the
300910946SSangeeta.Misra@Sun.COM  * nat src table.
301010946SSangeeta.Misra@Sun.COM  */
301110946SSangeeta.Misra@Sun.COM typedef struct {
301210946SSangeeta.Misra@Sun.COM 	ilb_stack_t ilbs;
301310946SSangeeta.Misra@Sun.COM 	int idx;
301410946SSangeeta.Misra@Sun.COM } ilb_walk_t;
301510946SSangeeta.Misra@Sun.COM 
301610946SSangeeta.Misra@Sun.COM /* Copy from list.c */
301710946SSangeeta.Misra@Sun.COM #define	list_object(a, node)	((void *)(((char *)node) - (a)->list_offset))
301810946SSangeeta.Misra@Sun.COM 
301910946SSangeeta.Misra@Sun.COM static int
302010946SSangeeta.Misra@Sun.COM ilb_nat_src_walk_init(mdb_walk_state_t *wsp)
302110946SSangeeta.Misra@Sun.COM {
302210946SSangeeta.Misra@Sun.COM 	int i;
302310946SSangeeta.Misra@Sun.COM 	ilb_walk_t *ns_walk;
302410946SSangeeta.Misra@Sun.COM 	ilb_nat_src_entry_t *entry = NULL;
302510946SSangeeta.Misra@Sun.COM 
302610946SSangeeta.Misra@Sun.COM 	if (wsp->walk_addr == NULL)
302710946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
302810946SSangeeta.Misra@Sun.COM 
302910946SSangeeta.Misra@Sun.COM 	ns_walk = mdb_alloc(sizeof (ilb_walk_t), UM_SLEEP);
303010946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&ns_walk->ilbs, sizeof (ns_walk->ilbs),
303110946SSangeeta.Misra@Sun.COM 	    wsp->walk_addr) == -1) {
303210946SSangeeta.Misra@Sun.COM 		mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr);
303310946SSangeeta.Misra@Sun.COM 		mdb_free(ns_walk, sizeof (ilb_walk_t));
303410946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
303510946SSangeeta.Misra@Sun.COM 	}
303610946SSangeeta.Misra@Sun.COM 
303710946SSangeeta.Misra@Sun.COM 	if (ns_walk->ilbs.ilbs_nat_src == NULL) {
303810946SSangeeta.Misra@Sun.COM 		mdb_free(ns_walk, sizeof (ilb_walk_t));
303910946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
304010946SSangeeta.Misra@Sun.COM 	}
304110946SSangeeta.Misra@Sun.COM 
304210946SSangeeta.Misra@Sun.COM 	wsp->walk_data = ns_walk;
304310946SSangeeta.Misra@Sun.COM 	for (i = 0; i < ns_walk->ilbs.ilbs_nat_src_hash_size; i++) {
304410946SSangeeta.Misra@Sun.COM 		list_t head;
304510946SSangeeta.Misra@Sun.COM 		char  *khead;
304610946SSangeeta.Misra@Sun.COM 
304710946SSangeeta.Misra@Sun.COM 		/* Read in the nsh_head in the i-th element of the array. */
304810946SSangeeta.Misra@Sun.COM 		khead = (char *)ns_walk->ilbs.ilbs_nat_src + i *
304910946SSangeeta.Misra@Sun.COM 		    sizeof (ilb_nat_src_hash_t);
305010946SSangeeta.Misra@Sun.COM 		if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) {
305110946SSangeeta.Misra@Sun.COM 			mdb_warn("failed to read ilbs_nat_src at %p\n", khead);
305210946SSangeeta.Misra@Sun.COM 			return (WALK_ERR);
305310946SSangeeta.Misra@Sun.COM 		}
305410946SSangeeta.Misra@Sun.COM 
305510946SSangeeta.Misra@Sun.COM 		/*
305610946SSangeeta.Misra@Sun.COM 		 * Note that list_next points to a kernel address and we need
305710946SSangeeta.Misra@Sun.COM 		 * to compare list_next with the kernel address of the list
305810946SSangeeta.Misra@Sun.COM 		 * head.  So we need to calculate the address manually.
305910946SSangeeta.Misra@Sun.COM 		 */
306010946SSangeeta.Misra@Sun.COM 		if ((char *)head.list_head.list_next != khead +
306110946SSangeeta.Misra@Sun.COM 		    offsetof(list_t, list_head)) {
306210946SSangeeta.Misra@Sun.COM 			entry = list_object(&head, head.list_head.list_next);
306310946SSangeeta.Misra@Sun.COM 			break;
306410946SSangeeta.Misra@Sun.COM 		}
306510946SSangeeta.Misra@Sun.COM 	}
306610946SSangeeta.Misra@Sun.COM 
306710946SSangeeta.Misra@Sun.COM 	if (entry == NULL)
306810946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
306910946SSangeeta.Misra@Sun.COM 
307010946SSangeeta.Misra@Sun.COM 	wsp->walk_addr = (uintptr_t)entry;
307110946SSangeeta.Misra@Sun.COM 	ns_walk->idx = i;
307210946SSangeeta.Misra@Sun.COM 	return (WALK_NEXT);
307310946SSangeeta.Misra@Sun.COM }
307410946SSangeeta.Misra@Sun.COM 
307510946SSangeeta.Misra@Sun.COM static int
307610946SSangeeta.Misra@Sun.COM ilb_nat_src_walk_step(mdb_walk_state_t *wsp)
307710946SSangeeta.Misra@Sun.COM {
307810946SSangeeta.Misra@Sun.COM 	int status;
307910946SSangeeta.Misra@Sun.COM 	ilb_nat_src_entry_t entry, *next_entry;
308010946SSangeeta.Misra@Sun.COM 	ilb_walk_t *ns_walk;
308110946SSangeeta.Misra@Sun.COM 	ilb_stack_t *ilbs;
308210946SSangeeta.Misra@Sun.COM 	list_t head;
308310946SSangeeta.Misra@Sun.COM 	char *khead;
308410946SSangeeta.Misra@Sun.COM 	int i;
308510946SSangeeta.Misra@Sun.COM 
308610946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&entry, sizeof (ilb_nat_src_entry_t),
308710946SSangeeta.Misra@Sun.COM 	    wsp->walk_addr) == -1) {
308810946SSangeeta.Misra@Sun.COM 		mdb_warn("failed to read ilb_nat_src_entry_t at %p",
308910946SSangeeta.Misra@Sun.COM 		    wsp->walk_addr);
309010946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
309110946SSangeeta.Misra@Sun.COM 	}
309210946SSangeeta.Misra@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, &entry, wsp->walk_cbdata);
309310946SSangeeta.Misra@Sun.COM 	if (status != WALK_NEXT)
309410946SSangeeta.Misra@Sun.COM 		return (status);
309510946SSangeeta.Misra@Sun.COM 
309610946SSangeeta.Misra@Sun.COM 	ns_walk = (ilb_walk_t *)wsp->walk_data;
309710946SSangeeta.Misra@Sun.COM 	ilbs = &ns_walk->ilbs;
309810946SSangeeta.Misra@Sun.COM 	i = ns_walk->idx;
309910946SSangeeta.Misra@Sun.COM 
310010946SSangeeta.Misra@Sun.COM 	/* Read in the nsh_head in the i-th element of the array. */
310110946SSangeeta.Misra@Sun.COM 	khead = (char *)ilbs->ilbs_nat_src + i * sizeof (ilb_nat_src_hash_t);
310210946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) {
310310946SSangeeta.Misra@Sun.COM 		mdb_warn("failed to read ilbs_nat_src at %p\n", khead);
310410946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
310510946SSangeeta.Misra@Sun.COM 	}
310610946SSangeeta.Misra@Sun.COM 
310710946SSangeeta.Misra@Sun.COM 	/*
310810946SSangeeta.Misra@Sun.COM 	 * Check if there is still entry in the current list.
310910946SSangeeta.Misra@Sun.COM 	 *
311010946SSangeeta.Misra@Sun.COM 	 * Note that list_next points to a kernel address and we need to
311110946SSangeeta.Misra@Sun.COM 	 * compare list_next with the kernel address of the list head.
311210946SSangeeta.Misra@Sun.COM 	 * So we need to calculate the address manually.
311310946SSangeeta.Misra@Sun.COM 	 */
311410946SSangeeta.Misra@Sun.COM 	if ((char *)entry.nse_link.list_next != khead + offsetof(list_t,
311510946SSangeeta.Misra@Sun.COM 	    list_head)) {
311610946SSangeeta.Misra@Sun.COM 		wsp->walk_addr = (uintptr_t)list_object(&head,
311710946SSangeeta.Misra@Sun.COM 		    entry.nse_link.list_next);
311810946SSangeeta.Misra@Sun.COM 		return (WALK_NEXT);
311910946SSangeeta.Misra@Sun.COM 	}
312010946SSangeeta.Misra@Sun.COM 
312110946SSangeeta.Misra@Sun.COM 	/* Start with the next bucket in the array. */
312210946SSangeeta.Misra@Sun.COM 	next_entry = NULL;
312310946SSangeeta.Misra@Sun.COM 	for (i++; i < ilbs->ilbs_nat_src_hash_size; i++) {
312410946SSangeeta.Misra@Sun.COM 		khead = (char *)ilbs->ilbs_nat_src + i *
312510946SSangeeta.Misra@Sun.COM 		    sizeof (ilb_nat_src_hash_t);
312610946SSangeeta.Misra@Sun.COM 		if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) {
312710946SSangeeta.Misra@Sun.COM 			mdb_warn("failed to read ilbs_nat_src at %p\n", khead);
312810946SSangeeta.Misra@Sun.COM 			return (WALK_ERR);
312910946SSangeeta.Misra@Sun.COM 		}
313010946SSangeeta.Misra@Sun.COM 
313110946SSangeeta.Misra@Sun.COM 		if ((char *)head.list_head.list_next != khead +
313210946SSangeeta.Misra@Sun.COM 		    offsetof(list_t, list_head)) {
313310946SSangeeta.Misra@Sun.COM 			next_entry = list_object(&head,
313410946SSangeeta.Misra@Sun.COM 			    head.list_head.list_next);
313510946SSangeeta.Misra@Sun.COM 			break;
313610946SSangeeta.Misra@Sun.COM 		}
313710946SSangeeta.Misra@Sun.COM 	}
313810946SSangeeta.Misra@Sun.COM 
313910946SSangeeta.Misra@Sun.COM 	if (next_entry == NULL)
314010946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
314110946SSangeeta.Misra@Sun.COM 
314210946SSangeeta.Misra@Sun.COM 	wsp->walk_addr = (uintptr_t)next_entry;
314310946SSangeeta.Misra@Sun.COM 	ns_walk->idx = i;
314410946SSangeeta.Misra@Sun.COM 	return (WALK_NEXT);
314510946SSangeeta.Misra@Sun.COM }
314610946SSangeeta.Misra@Sun.COM 
314710946SSangeeta.Misra@Sun.COM static void
314810946SSangeeta.Misra@Sun.COM ilb_common_walk_fini(mdb_walk_state_t *wsp)
314910946SSangeeta.Misra@Sun.COM {
315010946SSangeeta.Misra@Sun.COM 	ilb_walk_t *walk;
315110946SSangeeta.Misra@Sun.COM 
315210946SSangeeta.Misra@Sun.COM 	walk = (ilb_walk_t *)wsp->walk_data;
315310946SSangeeta.Misra@Sun.COM 	if (walk == NULL)
315410946SSangeeta.Misra@Sun.COM 		return;
315510946SSangeeta.Misra@Sun.COM 	mdb_free(walk, sizeof (ilb_walk_t *));
315610946SSangeeta.Misra@Sun.COM }
315710946SSangeeta.Misra@Sun.COM 
315810946SSangeeta.Misra@Sun.COM static int
315910946SSangeeta.Misra@Sun.COM ilb_conn_walk_init(mdb_walk_state_t *wsp)
316010946SSangeeta.Misra@Sun.COM {
316110946SSangeeta.Misra@Sun.COM 	int i;
316210946SSangeeta.Misra@Sun.COM 	ilb_walk_t *conn_walk;
316310946SSangeeta.Misra@Sun.COM 	ilb_conn_hash_t head;
316410946SSangeeta.Misra@Sun.COM 
316510946SSangeeta.Misra@Sun.COM 	if (wsp->walk_addr == NULL)
316610946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
316710946SSangeeta.Misra@Sun.COM 
316810946SSangeeta.Misra@Sun.COM 	conn_walk = mdb_alloc(sizeof (ilb_walk_t), UM_SLEEP);
316910946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&conn_walk->ilbs, sizeof (conn_walk->ilbs),
317010946SSangeeta.Misra@Sun.COM 	    wsp->walk_addr) == -1) {
317110946SSangeeta.Misra@Sun.COM 		mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr);
317210946SSangeeta.Misra@Sun.COM 		mdb_free(conn_walk, sizeof (ilb_walk_t));
317310946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
317410946SSangeeta.Misra@Sun.COM 	}
317510946SSangeeta.Misra@Sun.COM 
317610946SSangeeta.Misra@Sun.COM 	if (conn_walk->ilbs.ilbs_c2s_conn_hash == NULL) {
317710946SSangeeta.Misra@Sun.COM 		mdb_free(conn_walk, sizeof (ilb_walk_t));
317810946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
317910946SSangeeta.Misra@Sun.COM 	}
318010946SSangeeta.Misra@Sun.COM 
318110946SSangeeta.Misra@Sun.COM 	wsp->walk_data = conn_walk;
318210946SSangeeta.Misra@Sun.COM 	for (i = 0; i < conn_walk->ilbs.ilbs_conn_hash_size; i++) {
318310946SSangeeta.Misra@Sun.COM 		char *khead;
318410946SSangeeta.Misra@Sun.COM 
318510946SSangeeta.Misra@Sun.COM 		/* Read in the nsh_head in the i-th element of the array. */
318610946SSangeeta.Misra@Sun.COM 		khead = (char *)conn_walk->ilbs.ilbs_c2s_conn_hash + i *
318710946SSangeeta.Misra@Sun.COM 		    sizeof (ilb_conn_hash_t);
318810946SSangeeta.Misra@Sun.COM 		if (mdb_vread(&head, sizeof (ilb_conn_hash_t),
318910946SSangeeta.Misra@Sun.COM 		    (uintptr_t)khead) == -1) {
319010946SSangeeta.Misra@Sun.COM 			mdb_warn("failed to read ilbs_c2s_conn_hash at %p\n",
319110946SSangeeta.Misra@Sun.COM 			    khead);
319210946SSangeeta.Misra@Sun.COM 			return (WALK_ERR);
319310946SSangeeta.Misra@Sun.COM 		}
319410946SSangeeta.Misra@Sun.COM 
319510946SSangeeta.Misra@Sun.COM 		if (head.ilb_connp != NULL)
319610946SSangeeta.Misra@Sun.COM 			break;
319710946SSangeeta.Misra@Sun.COM 	}
319810946SSangeeta.Misra@Sun.COM 
319910946SSangeeta.Misra@Sun.COM 	if (head.ilb_connp == NULL)
320010946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
320110946SSangeeta.Misra@Sun.COM 
320210946SSangeeta.Misra@Sun.COM 	wsp->walk_addr = (uintptr_t)head.ilb_connp;
320310946SSangeeta.Misra@Sun.COM 	conn_walk->idx = i;
320410946SSangeeta.Misra@Sun.COM 	return (WALK_NEXT);
320510946SSangeeta.Misra@Sun.COM }
320610946SSangeeta.Misra@Sun.COM 
320710946SSangeeta.Misra@Sun.COM static int
320810946SSangeeta.Misra@Sun.COM ilb_conn_walk_step(mdb_walk_state_t *wsp)
320910946SSangeeta.Misra@Sun.COM {
321010946SSangeeta.Misra@Sun.COM 	int status;
321110946SSangeeta.Misra@Sun.COM 	ilb_conn_t conn;
321210946SSangeeta.Misra@Sun.COM 	ilb_walk_t *conn_walk;
321310946SSangeeta.Misra@Sun.COM 	ilb_stack_t *ilbs;
321410946SSangeeta.Misra@Sun.COM 	ilb_conn_hash_t head;
321510946SSangeeta.Misra@Sun.COM 	char *khead;
321610946SSangeeta.Misra@Sun.COM 	int i;
321710946SSangeeta.Misra@Sun.COM 
321810946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&conn, sizeof (ilb_conn_t), wsp->walk_addr) == -1) {
321910946SSangeeta.Misra@Sun.COM 		mdb_warn("failed to read ilb_conn_t at %p", wsp->walk_addr);
322010946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
322110946SSangeeta.Misra@Sun.COM 	}
322210946SSangeeta.Misra@Sun.COM 
322310946SSangeeta.Misra@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, &conn, wsp->walk_cbdata);
322410946SSangeeta.Misra@Sun.COM 	if (status != WALK_NEXT)
322510946SSangeeta.Misra@Sun.COM 		return (status);
322610946SSangeeta.Misra@Sun.COM 
322710946SSangeeta.Misra@Sun.COM 	conn_walk = (ilb_walk_t *)wsp->walk_data;
322810946SSangeeta.Misra@Sun.COM 	ilbs = &conn_walk->ilbs;
322910946SSangeeta.Misra@Sun.COM 	i = conn_walk->idx;
323010946SSangeeta.Misra@Sun.COM 
323110946SSangeeta.Misra@Sun.COM 	/* Check if there is still entry in the current list. */
323210946SSangeeta.Misra@Sun.COM 	if (conn.conn_c2s_next != NULL) {
323310946SSangeeta.Misra@Sun.COM 		wsp->walk_addr = (uintptr_t)conn.conn_c2s_next;
323410946SSangeeta.Misra@Sun.COM 		return (WALK_NEXT);
323510946SSangeeta.Misra@Sun.COM 	}
323610946SSangeeta.Misra@Sun.COM 
323710946SSangeeta.Misra@Sun.COM 	/* Start with the next bucket in the array. */
323810946SSangeeta.Misra@Sun.COM 	for (i++; i < ilbs->ilbs_conn_hash_size; i++) {
323910946SSangeeta.Misra@Sun.COM 		khead = (char *)ilbs->ilbs_c2s_conn_hash + i *
324010946SSangeeta.Misra@Sun.COM 		    sizeof (ilb_conn_hash_t);
324110946SSangeeta.Misra@Sun.COM 		if (mdb_vread(&head, sizeof (ilb_conn_hash_t),
324210946SSangeeta.Misra@Sun.COM 		    (uintptr_t)khead) == -1) {
324310946SSangeeta.Misra@Sun.COM 			mdb_warn("failed to read ilbs_c2s_conn_hash at %p\n",
324410946SSangeeta.Misra@Sun.COM 			    khead);
324510946SSangeeta.Misra@Sun.COM 			return (WALK_ERR);
324610946SSangeeta.Misra@Sun.COM 		}
324710946SSangeeta.Misra@Sun.COM 
324810946SSangeeta.Misra@Sun.COM 		if (head.ilb_connp != NULL)
324910946SSangeeta.Misra@Sun.COM 			break;
325010946SSangeeta.Misra@Sun.COM 	}
325110946SSangeeta.Misra@Sun.COM 
325210946SSangeeta.Misra@Sun.COM 	if (head.ilb_connp == NULL)
325310946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
325410946SSangeeta.Misra@Sun.COM 
325510946SSangeeta.Misra@Sun.COM 	wsp->walk_addr = (uintptr_t)head.ilb_connp;
325610946SSangeeta.Misra@Sun.COM 	conn_walk->idx = i;
325710946SSangeeta.Misra@Sun.COM 	return (WALK_NEXT);
325810946SSangeeta.Misra@Sun.COM }
325910946SSangeeta.Misra@Sun.COM 
326010946SSangeeta.Misra@Sun.COM static int
326110946SSangeeta.Misra@Sun.COM ilb_sticky_walk_init(mdb_walk_state_t *wsp)
326210946SSangeeta.Misra@Sun.COM {
326310946SSangeeta.Misra@Sun.COM 	int i;
326410946SSangeeta.Misra@Sun.COM 	ilb_walk_t *sticky_walk;
326510946SSangeeta.Misra@Sun.COM 	ilb_sticky_t *st = NULL;
326610946SSangeeta.Misra@Sun.COM 
326710946SSangeeta.Misra@Sun.COM 	if (wsp->walk_addr == NULL)
326810946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
326910946SSangeeta.Misra@Sun.COM 
327010946SSangeeta.Misra@Sun.COM 	sticky_walk = mdb_alloc(sizeof (ilb_walk_t), UM_SLEEP);
327110946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&sticky_walk->ilbs, sizeof (sticky_walk->ilbs),
327210946SSangeeta.Misra@Sun.COM 	    wsp->walk_addr) == -1) {
327310946SSangeeta.Misra@Sun.COM 		mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr);
327410946SSangeeta.Misra@Sun.COM 		mdb_free(sticky_walk, sizeof (ilb_walk_t));
327510946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
327610946SSangeeta.Misra@Sun.COM 	}
327710946SSangeeta.Misra@Sun.COM 
327810946SSangeeta.Misra@Sun.COM 	if (sticky_walk->ilbs.ilbs_sticky_hash == NULL) {
327910946SSangeeta.Misra@Sun.COM 		mdb_free(sticky_walk, sizeof (ilb_walk_t));
328010946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
328110946SSangeeta.Misra@Sun.COM 	}
328210946SSangeeta.Misra@Sun.COM 
328310946SSangeeta.Misra@Sun.COM 	wsp->walk_data = sticky_walk;
328410946SSangeeta.Misra@Sun.COM 	for (i = 0; i < sticky_walk->ilbs.ilbs_sticky_hash_size; i++) {
328510946SSangeeta.Misra@Sun.COM 		list_t head;
328610946SSangeeta.Misra@Sun.COM 		char *khead;
328710946SSangeeta.Misra@Sun.COM 
328810946SSangeeta.Misra@Sun.COM 		/* Read in the nsh_head in the i-th element of the array. */
328910946SSangeeta.Misra@Sun.COM 		khead = (char *)sticky_walk->ilbs.ilbs_sticky_hash + i *
329010946SSangeeta.Misra@Sun.COM 		    sizeof (ilb_sticky_hash_t);
329110946SSangeeta.Misra@Sun.COM 		if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) {
329210946SSangeeta.Misra@Sun.COM 			mdb_warn("failed to read ilbs_sticky_hash at %p\n",
329310946SSangeeta.Misra@Sun.COM 			    khead);
329410946SSangeeta.Misra@Sun.COM 			return (WALK_ERR);
329510946SSangeeta.Misra@Sun.COM 		}
329610946SSangeeta.Misra@Sun.COM 
329710946SSangeeta.Misra@Sun.COM 		/*
329810946SSangeeta.Misra@Sun.COM 		 * Note that list_next points to a kernel address and we need
329910946SSangeeta.Misra@Sun.COM 		 * to compare list_next with the kernel address of the list
330010946SSangeeta.Misra@Sun.COM 		 * head.  So we need to calculate the address manually.
330110946SSangeeta.Misra@Sun.COM 		 */
330210946SSangeeta.Misra@Sun.COM 		if ((char *)head.list_head.list_next != khead +
330310946SSangeeta.Misra@Sun.COM 		    offsetof(list_t, list_head)) {
330410946SSangeeta.Misra@Sun.COM 			st = list_object(&head, head.list_head.list_next);
330510946SSangeeta.Misra@Sun.COM 			break;
330610946SSangeeta.Misra@Sun.COM 		}
330710946SSangeeta.Misra@Sun.COM 	}
330810946SSangeeta.Misra@Sun.COM 
330910946SSangeeta.Misra@Sun.COM 	if (st == NULL)
331010946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
331110946SSangeeta.Misra@Sun.COM 
331210946SSangeeta.Misra@Sun.COM 	wsp->walk_addr = (uintptr_t)st;
331310946SSangeeta.Misra@Sun.COM 	sticky_walk->idx = i;
331410946SSangeeta.Misra@Sun.COM 	return (WALK_NEXT);
331510946SSangeeta.Misra@Sun.COM }
331610946SSangeeta.Misra@Sun.COM 
331710946SSangeeta.Misra@Sun.COM static int
331810946SSangeeta.Misra@Sun.COM ilb_sticky_walk_step(mdb_walk_state_t *wsp)
331910946SSangeeta.Misra@Sun.COM {
332010946SSangeeta.Misra@Sun.COM 	int status;
332110946SSangeeta.Misra@Sun.COM 	ilb_sticky_t st, *st_next;
332210946SSangeeta.Misra@Sun.COM 	ilb_walk_t *sticky_walk;
332310946SSangeeta.Misra@Sun.COM 	ilb_stack_t *ilbs;
332410946SSangeeta.Misra@Sun.COM 	list_t head;
332510946SSangeeta.Misra@Sun.COM 	char *khead;
332610946SSangeeta.Misra@Sun.COM 	int i;
332710946SSangeeta.Misra@Sun.COM 
332810946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&st, sizeof (ilb_sticky_t), wsp->walk_addr) == -1) {
332910946SSangeeta.Misra@Sun.COM 		mdb_warn("failed to read ilb_sticky_t at %p", wsp->walk_addr);
333010946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
333110946SSangeeta.Misra@Sun.COM 	}
333210946SSangeeta.Misra@Sun.COM 
333310946SSangeeta.Misra@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, &st, wsp->walk_cbdata);
333410946SSangeeta.Misra@Sun.COM 	if (status != WALK_NEXT)
333510946SSangeeta.Misra@Sun.COM 		return (status);
333610946SSangeeta.Misra@Sun.COM 
333710946SSangeeta.Misra@Sun.COM 	sticky_walk = (ilb_walk_t *)wsp->walk_data;
333810946SSangeeta.Misra@Sun.COM 	ilbs = &sticky_walk->ilbs;
333910946SSangeeta.Misra@Sun.COM 	i = sticky_walk->idx;
334010946SSangeeta.Misra@Sun.COM 
334110946SSangeeta.Misra@Sun.COM 	/* Read in the nsh_head in the i-th element of the array. */
334210946SSangeeta.Misra@Sun.COM 	khead = (char *)ilbs->ilbs_sticky_hash + i * sizeof (ilb_sticky_hash_t);
334310946SSangeeta.Misra@Sun.COM 	if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) {
334410946SSangeeta.Misra@Sun.COM 		mdb_warn("failed to read ilbs_sticky_hash at %p\n", khead);
334510946SSangeeta.Misra@Sun.COM 		return (WALK_ERR);
334610946SSangeeta.Misra@Sun.COM 	}
334710946SSangeeta.Misra@Sun.COM 
334810946SSangeeta.Misra@Sun.COM 	/*
334910946SSangeeta.Misra@Sun.COM 	 * Check if there is still entry in the current list.
335010946SSangeeta.Misra@Sun.COM 	 *
335110946SSangeeta.Misra@Sun.COM 	 * Note that list_next points to a kernel address and we need to
335210946SSangeeta.Misra@Sun.COM 	 * compare list_next with the kernel address of the list head.
335310946SSangeeta.Misra@Sun.COM 	 * So we need to calculate the address manually.
335410946SSangeeta.Misra@Sun.COM 	 */
335510946SSangeeta.Misra@Sun.COM 	if ((char *)st.list.list_next != khead + offsetof(list_t,
335610946SSangeeta.Misra@Sun.COM 	    list_head)) {
335710946SSangeeta.Misra@Sun.COM 		wsp->walk_addr = (uintptr_t)list_object(&head,
335810946SSangeeta.Misra@Sun.COM 		    st.list.list_next);
335910946SSangeeta.Misra@Sun.COM 		return (WALK_NEXT);
336010946SSangeeta.Misra@Sun.COM 	}
336110946SSangeeta.Misra@Sun.COM 
336210946SSangeeta.Misra@Sun.COM 	/* Start with the next bucket in the array. */
336310946SSangeeta.Misra@Sun.COM 	st_next = NULL;
336410946SSangeeta.Misra@Sun.COM 	for (i++; i < ilbs->ilbs_nat_src_hash_size; i++) {
336510946SSangeeta.Misra@Sun.COM 		khead = (char *)ilbs->ilbs_sticky_hash + i *
336610946SSangeeta.Misra@Sun.COM 		    sizeof (ilb_sticky_hash_t);
336710946SSangeeta.Misra@Sun.COM 		if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) {
336810946SSangeeta.Misra@Sun.COM 			mdb_warn("failed to read ilbs_sticky_hash at %p\n",
336910946SSangeeta.Misra@Sun.COM 			    khead);
337010946SSangeeta.Misra@Sun.COM 			return (WALK_ERR);
337110946SSangeeta.Misra@Sun.COM 		}
337210946SSangeeta.Misra@Sun.COM 
337310946SSangeeta.Misra@Sun.COM 		if ((char *)head.list_head.list_next != khead +
337410946SSangeeta.Misra@Sun.COM 		    offsetof(list_t, list_head)) {
337510946SSangeeta.Misra@Sun.COM 			st_next = list_object(&head,
337610946SSangeeta.Misra@Sun.COM 			    head.list_head.list_next);
337710946SSangeeta.Misra@Sun.COM 			break;
337810946SSangeeta.Misra@Sun.COM 		}
337910946SSangeeta.Misra@Sun.COM 	}
338010946SSangeeta.Misra@Sun.COM 
338110946SSangeeta.Misra@Sun.COM 	if (st_next == NULL)
338210946SSangeeta.Misra@Sun.COM 		return (WALK_DONE);
338310946SSangeeta.Misra@Sun.COM 
338410946SSangeeta.Misra@Sun.COM 	wsp->walk_addr = (uintptr_t)st_next;
338510946SSangeeta.Misra@Sun.COM 	sticky_walk->idx = i;
338610946SSangeeta.Misra@Sun.COM 	return (WALK_NEXT);
338710946SSangeeta.Misra@Sun.COM }
3388