xref: /onnv-gate/usr/src/cmd/mdb/common/modules/ip/ip.c (revision 9089:f2cd448729f6)
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>
31*9089SVasumathi.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>
495940Ssowmini #include <sys/dlpi.h>
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
520Sstevel@tonic-gate #include <mdb/mdb_ks.h>
530Sstevel@tonic-gate 
540Sstevel@tonic-gate #define	ADDR_WIDTH 11
555940Ssowmini #define	L2MAXADDRSTRLEN	255
565940Ssowmini #define	MAX_SAP_LEN	255
57*9089SVasumathi.Sundaram@Sun.COM #define	DEFCOLS		80
580Sstevel@tonic-gate 
590Sstevel@tonic-gate typedef struct {
600Sstevel@tonic-gate 	const char *bit_name;	/* name of bit */
610Sstevel@tonic-gate 	const char *bit_descr;	/* description of bit's purpose */
620Sstevel@tonic-gate } bitname_t;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate static const bitname_t squeue_states[] = {
650Sstevel@tonic-gate 	{ "SQS_PROC",		"being processed" },
660Sstevel@tonic-gate 	{ "SQS_WORKER",		"... by a worker thread" },
670Sstevel@tonic-gate 	{ "SQS_ENTER",		"... by an squeue_enter() thread" },
680Sstevel@tonic-gate 	{ "SQS_FAST",		"... in fast-path mode" },
690Sstevel@tonic-gate 	{ "SQS_USER", 		"A non interrupt user" },
700Sstevel@tonic-gate 	{ "SQS_BOUND",		"worker thread bound to CPU" },
710Sstevel@tonic-gate 	{ "SQS_PROFILE",	"profiling enabled" },
720Sstevel@tonic-gate 	{ "SQS_REENTER",	"re-entered thred" },
730Sstevel@tonic-gate 	{ NULL }
740Sstevel@tonic-gate };
750Sstevel@tonic-gate 
760Sstevel@tonic-gate typedef struct illif_walk_data {
770Sstevel@tonic-gate 	ill_g_head_t ill_g_heads[MAX_G_HEADS];
780Sstevel@tonic-gate 	int ill_list;
790Sstevel@tonic-gate 	ill_if_t ill_if;
800Sstevel@tonic-gate } illif_walk_data_t;
810Sstevel@tonic-gate 
825940Ssowmini typedef struct nce_walk_data_s {
835940Ssowmini 	struct ndp_g_s	nce_ip_ndp;
845940Ssowmini 	int		nce_hash_tbl_index;
855940Ssowmini 	nce_t 		nce;
865940Ssowmini } nce_walk_data_t;
875940Ssowmini 
885940Ssowmini typedef struct nce_cbdata_s {
895940Ssowmini 	uintptr_t nce_addr;
905940Ssowmini 	int	  nce_ipversion;
915940Ssowmini } nce_cbdata_t;
925940Ssowmini 
935940Ssowmini typedef struct ire_cbdata_s {
945940Ssowmini 	int		ire_ipversion;
955940Ssowmini 	boolean_t	verbose;
965940Ssowmini } ire_cbdata_t;
975940Ssowmini 
985023Scarlsonj typedef struct th_walk_data {
995023Scarlsonj 	uint_t		thw_non_zero_only;
1005023Scarlsonj 	boolean_t	thw_match;
1015023Scarlsonj 	uintptr_t	thw_matchkey;
1025023Scarlsonj 	uintptr_t	thw_ipst;
1035023Scarlsonj 	clock_t		thw_lbolt;
1045023Scarlsonj } th_walk_data_t;
1055023Scarlsonj 
106*9089SVasumathi.Sundaram@Sun.COM typedef struct ipcl_hash_walk_data_s {
107*9089SVasumathi.Sundaram@Sun.COM 	conn_t		*conn;
108*9089SVasumathi.Sundaram@Sun.COM 	int		connf_tbl_index;
109*9089SVasumathi.Sundaram@Sun.COM 	uintptr_t	hash_tbl;
110*9089SVasumathi.Sundaram@Sun.COM 	int		hash_tbl_size;
111*9089SVasumathi.Sundaram@Sun.COM } ipcl_hash_walk_data_t;
112*9089SVasumathi.Sundaram@Sun.COM 
113*9089SVasumathi.Sundaram@Sun.COM typedef struct ill_walk_data_s {
114*9089SVasumathi.Sundaram@Sun.COM 	ill_t 		ill;
115*9089SVasumathi.Sundaram@Sun.COM } ill_walk_data_t;
116*9089SVasumathi.Sundaram@Sun.COM 
117*9089SVasumathi.Sundaram@Sun.COM typedef struct ill_cbdata_s {
118*9089SVasumathi.Sundaram@Sun.COM 	uintptr_t ill_addr;
119*9089SVasumathi.Sundaram@Sun.COM 	int	  ill_ipversion;
120*9089SVasumathi.Sundaram@Sun.COM 	boolean_t verbose;
121*9089SVasumathi.Sundaram@Sun.COM } ill_cbdata_t;
122*9089SVasumathi.Sundaram@Sun.COM 
123*9089SVasumathi.Sundaram@Sun.COM typedef struct ipif_walk_data_s {
124*9089SVasumathi.Sundaram@Sun.COM 	ipif_t 		ipif;
125*9089SVasumathi.Sundaram@Sun.COM } ipif_walk_data_t;
126*9089SVasumathi.Sundaram@Sun.COM 
127*9089SVasumathi.Sundaram@Sun.COM typedef struct ipif_cbdata_s {
128*9089SVasumathi.Sundaram@Sun.COM 	ill_t		ill;
129*9089SVasumathi.Sundaram@Sun.COM 	int		ipif_ipversion;
130*9089SVasumathi.Sundaram@Sun.COM 	boolean_t 	verbose;
131*9089SVasumathi.Sundaram@Sun.COM } ipif_cbdata_t;
132*9089SVasumathi.Sundaram@Sun.COM 
133*9089SVasumathi.Sundaram@Sun.COM typedef struct hash_walk_arg_s {
134*9089SVasumathi.Sundaram@Sun.COM 	off_t	tbl_off;
135*9089SVasumathi.Sundaram@Sun.COM 	off_t	size_off;
136*9089SVasumathi.Sundaram@Sun.COM } hash_walk_arg_t;
137*9089SVasumathi.Sundaram@Sun.COM 
138*9089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t udp_hash_arg = {
139*9089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_udp_fanout),
140*9089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_udp_fanout_size)
141*9089SVasumathi.Sundaram@Sun.COM };
142*9089SVasumathi.Sundaram@Sun.COM 
143*9089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t conn_hash_arg = {
144*9089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_conn_fanout),
145*9089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_conn_fanout_size)
146*9089SVasumathi.Sundaram@Sun.COM };
147*9089SVasumathi.Sundaram@Sun.COM 
148*9089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t bind_hash_arg = {
149*9089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_bind_fanout),
150*9089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_bind_fanout_size)
151*9089SVasumathi.Sundaram@Sun.COM };
152*9089SVasumathi.Sundaram@Sun.COM 
153*9089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t proto_hash_arg = {
154*9089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout),
155*9089SVasumathi.Sundaram@Sun.COM 	0
156*9089SVasumathi.Sundaram@Sun.COM };
157*9089SVasumathi.Sundaram@Sun.COM 
158*9089SVasumathi.Sundaram@Sun.COM static hash_walk_arg_t proto_v6_hash_arg = {
159*9089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v6),
160*9089SVasumathi.Sundaram@Sun.COM 	0
161*9089SVasumathi.Sundaram@Sun.COM };
162*9089SVasumathi.Sundaram@Sun.COM 
163*9089SVasumathi.Sundaram@Sun.COM typedef struct ip_list_walk_data_s {
164*9089SVasumathi.Sundaram@Sun.COM 	off_t 	nextoff;
165*9089SVasumathi.Sundaram@Sun.COM } ip_list_walk_data_t;
166*9089SVasumathi.Sundaram@Sun.COM 
167*9089SVasumathi.Sundaram@Sun.COM typedef struct ip_list_walk_arg_s {
168*9089SVasumathi.Sundaram@Sun.COM 	off_t	off;
169*9089SVasumathi.Sundaram@Sun.COM 	size_t	size;
170*9089SVasumathi.Sundaram@Sun.COM 	off_t	nextp_off;
171*9089SVasumathi.Sundaram@Sun.COM } ip_list_walk_arg_t;
172*9089SVasumathi.Sundaram@Sun.COM 
173*9089SVasumathi.Sundaram@Sun.COM static ip_list_walk_arg_t ipif_walk_arg = {
174*9089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ill_t, ill_ipif),
175*9089SVasumathi.Sundaram@Sun.COM 	sizeof (ipif_t),
176*9089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ipif_t, ipif_next)
177*9089SVasumathi.Sundaram@Sun.COM };
178*9089SVasumathi.Sundaram@Sun.COM 
179*9089SVasumathi.Sundaram@Sun.COM static ip_list_walk_arg_t srcid_walk_arg = {
180*9089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(ip_stack_t, ips_srcid_head),
181*9089SVasumathi.Sundaram@Sun.COM 	sizeof (srcid_map_t),
182*9089SVasumathi.Sundaram@Sun.COM 	OFFSETOF(srcid_map_t, sm_next)
183*9089SVasumathi.Sundaram@Sun.COM };
184*9089SVasumathi.Sundaram@Sun.COM 
1850Sstevel@tonic-gate static int iphdr(uintptr_t, uint_t, int, const mdb_arg_t *);
1860Sstevel@tonic-gate static int ip6hdr(uintptr_t, uint_t, int, const mdb_arg_t *);
1870Sstevel@tonic-gate 
188*9089SVasumathi.Sundaram@Sun.COM static int ill(uintptr_t, uint_t, int, const mdb_arg_t *);
189*9089SVasumathi.Sundaram@Sun.COM static void ill_help(void);
190*9089SVasumathi.Sundaram@Sun.COM static int ill_walk_init(mdb_walk_state_t *);
191*9089SVasumathi.Sundaram@Sun.COM static int ill_walk_step(mdb_walk_state_t *);
192*9089SVasumathi.Sundaram@Sun.COM static int ill_format(uintptr_t, const void *, void *);
193*9089SVasumathi.Sundaram@Sun.COM static void ill_header(boolean_t);
194*9089SVasumathi.Sundaram@Sun.COM 
195*9089SVasumathi.Sundaram@Sun.COM static int ipif(uintptr_t, uint_t, int, const mdb_arg_t *);
196*9089SVasumathi.Sundaram@Sun.COM static void ipif_help(void);
197*9089SVasumathi.Sundaram@Sun.COM static int ipif_walk_init(mdb_walk_state_t *);
198*9089SVasumathi.Sundaram@Sun.COM static int ipif_walk_step(mdb_walk_state_t *);
199*9089SVasumathi.Sundaram@Sun.COM static int ipif_format(uintptr_t, const void *, void *);
200*9089SVasumathi.Sundaram@Sun.COM static void ipif_header(boolean_t);
201*9089SVasumathi.Sundaram@Sun.COM 
202*9089SVasumathi.Sundaram@Sun.COM static int ip_list_walk_init(mdb_walk_state_t *);
203*9089SVasumathi.Sundaram@Sun.COM static int ip_list_walk_step(mdb_walk_state_t *);
204*9089SVasumathi.Sundaram@Sun.COM static void ip_list_walk_fini(mdb_walk_state_t *);
205*9089SVasumathi.Sundaram@Sun.COM static int srcid_walk_step(mdb_walk_state_t *);
206*9089SVasumathi.Sundaram@Sun.COM 
2075940Ssowmini static int ire_format(uintptr_t addr, const void *, void *);
2085940Ssowmini static int nce_format(uintptr_t addr, const nce_t *nce, int ipversion);
2095940Ssowmini static int nce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv);
2105940Ssowmini static int nce_walk_step(mdb_walk_state_t *wsp);
2115940Ssowmini static int nce_stack_walk_init(mdb_walk_state_t *wsp);
2125940Ssowmini static int nce_stack_walk_step(mdb_walk_state_t *wsp);
2135940Ssowmini static void nce_stack_walk_fini(mdb_walk_state_t *wsp);
2145940Ssowmini static int nce_cb(uintptr_t addr, const nce_walk_data_t *iw, nce_cbdata_t *id);
2153448Sdh155122 
216*9089SVasumathi.Sundaram@Sun.COM static int ipcl_hash_walk_init(mdb_walk_state_t *);
217*9089SVasumathi.Sundaram@Sun.COM static int ipcl_hash_walk_step(mdb_walk_state_t *);
218*9089SVasumathi.Sundaram@Sun.COM static void ipcl_hash_walk_fini(mdb_walk_state_t *);
219*9089SVasumathi.Sundaram@Sun.COM 
220*9089SVasumathi.Sundaram@Sun.COM static int conn_status_walk_step(mdb_walk_state_t *);
221*9089SVasumathi.Sundaram@Sun.COM static int conn_status(uintptr_t, uint_t, int, const mdb_arg_t *);
222*9089SVasumathi.Sundaram@Sun.COM static void conn_status_help(void);
223*9089SVasumathi.Sundaram@Sun.COM 
224*9089SVasumathi.Sundaram@Sun.COM static int srcid_status(uintptr_t, uint_t, int, const mdb_arg_t *);
225*9089SVasumathi.Sundaram@Sun.COM 
2263448Sdh155122 /*
2273448Sdh155122  * Given the kernel address of an ip_stack_t, return the stackid
2283448Sdh155122  */
2293448Sdh155122 static int
2303448Sdh155122 ips_to_stackid(uintptr_t kaddr)
2313448Sdh155122 {
2323448Sdh155122 	ip_stack_t ipss;
2333448Sdh155122 	netstack_t nss;
2343448Sdh155122 
2353448Sdh155122 	if (mdb_vread(&ipss, sizeof (ipss), kaddr) == -1) {
2363448Sdh155122 		mdb_warn("failed to read ip_stack_t %p", kaddr);
2373448Sdh155122 		return (0);
2383448Sdh155122 	}
2393448Sdh155122 	kaddr = (uintptr_t)ipss.ips_netstack;
2403448Sdh155122 	if (mdb_vread(&nss, sizeof (nss), kaddr) == -1) {
2413448Sdh155122 		mdb_warn("failed to read netstack_t %p", kaddr);
2423448Sdh155122 		return (0);
2433448Sdh155122 	}
2443448Sdh155122 	return (nss.netstack_stackid);
2453448Sdh155122 }
2463448Sdh155122 
2470Sstevel@tonic-gate int
2483448Sdh155122 ip_stacks_walk_init(mdb_walk_state_t *wsp)
2493448Sdh155122 {
2503448Sdh155122 	if (mdb_layered_walk("netstack", wsp) == -1) {
2513448Sdh155122 		mdb_warn("can't walk 'netstack'");
2523448Sdh155122 		return (WALK_ERR);
2533448Sdh155122 	}
2543448Sdh155122 	return (WALK_NEXT);
2553448Sdh155122 }
2563448Sdh155122 
2573448Sdh155122 int
2583448Sdh155122 ip_stacks_walk_step(mdb_walk_state_t *wsp)
2593448Sdh155122 {
2603448Sdh155122 	uintptr_t kaddr;
2613448Sdh155122 	netstack_t nss;
2623448Sdh155122 
2633448Sdh155122 	if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
2643448Sdh155122 		mdb_warn("can't read netstack at %p", wsp->walk_addr);
2653448Sdh155122 		return (WALK_ERR);
2663448Sdh155122 	}
2673448Sdh155122 	kaddr = (uintptr_t)nss.netstack_modules[NS_IP];
2683448Sdh155122 
2693448Sdh155122 	return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
2703448Sdh155122 }
2713448Sdh155122 
2725023Scarlsonj int
2735023Scarlsonj th_hash_walk_init(mdb_walk_state_t *wsp)
2745023Scarlsonj {
2755023Scarlsonj 	GElf_Sym sym;
2765023Scarlsonj 	list_node_t *next;
2775023Scarlsonj 
2785023Scarlsonj 	if (wsp->walk_addr == NULL) {
2795023Scarlsonj 		if (mdb_lookup_by_obj("ip", "ip_thread_list", &sym) == 0) {
2805023Scarlsonj 			wsp->walk_addr = sym.st_value;
2815023Scarlsonj 		} else {
2825023Scarlsonj 			mdb_warn("unable to locate ip_thread_list\n");
2835023Scarlsonj 			return (WALK_ERR);
2845023Scarlsonj 		}
2855023Scarlsonj 	}
2865023Scarlsonj 
2875023Scarlsonj 	if (mdb_vread(&next, sizeof (next),
2885023Scarlsonj 	    wsp->walk_addr + offsetof(list_t, list_head) +
2895023Scarlsonj 	    offsetof(list_node_t, list_next)) == -1 ||
2905023Scarlsonj 	    next == NULL) {
2915023Scarlsonj 		mdb_warn("non-DEBUG image; cannot walk th_hash list\n");
2925023Scarlsonj 		return (WALK_ERR);
2935023Scarlsonj 	}
2945023Scarlsonj 
2955023Scarlsonj 	if (mdb_layered_walk("list", wsp) == -1) {
2965023Scarlsonj 		mdb_warn("can't walk 'list'");
2975023Scarlsonj 		return (WALK_ERR);
2985023Scarlsonj 	} else {
2995023Scarlsonj 		return (WALK_NEXT);
3005023Scarlsonj 	}
3015023Scarlsonj }
3025023Scarlsonj 
3035023Scarlsonj int
3045023Scarlsonj th_hash_walk_step(mdb_walk_state_t *wsp)
3055023Scarlsonj {
3065023Scarlsonj 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
3075023Scarlsonj 	    wsp->walk_cbdata));
3085023Scarlsonj }
3095023Scarlsonj 
3103448Sdh155122 /*
3113448Sdh155122  * Called with walk_addr being the address of ips_ill_g_heads
3123448Sdh155122  */
3133448Sdh155122 int
3143448Sdh155122 illif_stack_walk_init(mdb_walk_state_t *wsp)
3150Sstevel@tonic-gate {
3160Sstevel@tonic-gate 	illif_walk_data_t *iw;
3170Sstevel@tonic-gate 
3183448Sdh155122 	if (wsp->walk_addr == NULL) {
3193448Sdh155122 		mdb_warn("illif_stack supports only local walks\n");
3200Sstevel@tonic-gate 		return (WALK_ERR);
3210Sstevel@tonic-gate 	}
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	iw = mdb_alloc(sizeof (illif_walk_data_t), UM_SLEEP);
3240Sstevel@tonic-gate 
3253448Sdh155122 	if (mdb_vread(iw->ill_g_heads, MAX_G_HEADS * sizeof (ill_g_head_t),
3263448Sdh155122 	    wsp->walk_addr) == -1) {
3273448Sdh155122 		mdb_warn("failed to read 'ips_ill_g_heads' at %p",
3283448Sdh155122 		    wsp->walk_addr);
3290Sstevel@tonic-gate 		mdb_free(iw, sizeof (illif_walk_data_t));
3300Sstevel@tonic-gate 		return (WALK_ERR);
3310Sstevel@tonic-gate 	}
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	iw->ill_list = 0;
3343448Sdh155122 	wsp->walk_addr = (uintptr_t)iw->ill_g_heads[0].ill_g_list_head;
3350Sstevel@tonic-gate 	wsp->walk_data = iw;
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	return (WALK_NEXT);
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate int
3413448Sdh155122 illif_stack_walk_step(mdb_walk_state_t *wsp)
3420Sstevel@tonic-gate {
3430Sstevel@tonic-gate 	uintptr_t addr = wsp->walk_addr;
3440Sstevel@tonic-gate 	illif_walk_data_t *iw = wsp->walk_data;
3450Sstevel@tonic-gate 	int list = iw->ill_list;
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	if (mdb_vread(&iw->ill_if, sizeof (ill_if_t), addr) == -1) {
3480Sstevel@tonic-gate 		mdb_warn("failed to read ill_if_t at %p", addr);
3490Sstevel@tonic-gate 		return (WALK_ERR);
3500Sstevel@tonic-gate 	}
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)iw->ill_if.illif_next;
3530Sstevel@tonic-gate 
3543448Sdh155122 	if (wsp->walk_addr ==
3553448Sdh155122 	    (uintptr_t)iw->ill_g_heads[list].ill_g_list_head) {
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 		if (++list >= MAX_G_HEADS)
3580Sstevel@tonic-gate 			return (WALK_DONE);
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 		iw->ill_list = list;
3613448Sdh155122 		wsp->walk_addr =
3623448Sdh155122 		    (uintptr_t)iw->ill_g_heads[list].ill_g_list_head;
3630Sstevel@tonic-gate 		return (WALK_NEXT);
3640Sstevel@tonic-gate 	}
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 	return (wsp->walk_callback(addr, iw, wsp->walk_cbdata));
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate void
3703448Sdh155122 illif_stack_walk_fini(mdb_walk_state_t *wsp)
3710Sstevel@tonic-gate {
3720Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (illif_walk_data_t));
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate typedef struct illif_cbdata {
3760Sstevel@tonic-gate 	uint_t ill_flags;
3770Sstevel@tonic-gate 	uintptr_t ill_addr;
3780Sstevel@tonic-gate 	int ill_printlist;	/* list to be printed (MAX_G_HEADS for all) */
3790Sstevel@tonic-gate 	boolean_t ill_printed;
3800Sstevel@tonic-gate } illif_cbdata_t;
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate static int
3830Sstevel@tonic-gate illif_cb(uintptr_t addr, const illif_walk_data_t *iw, illif_cbdata_t *id)
3840Sstevel@tonic-gate {
3850Sstevel@tonic-gate 	const char *version;
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	if (id->ill_printlist < MAX_G_HEADS &&
3880Sstevel@tonic-gate 	    id->ill_printlist != iw->ill_list)
3890Sstevel@tonic-gate 		return (WALK_NEXT);
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	if (id->ill_flags & DCMD_ADDRSPEC && id->ill_addr != addr)
3920Sstevel@tonic-gate 		return (WALK_NEXT);
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 	if (id->ill_flags & DCMD_PIPE_OUT) {
3950Sstevel@tonic-gate 		mdb_printf("%p\n", addr);
3960Sstevel@tonic-gate 		return (WALK_NEXT);
3970Sstevel@tonic-gate 	}
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	switch (iw->ill_list) {
4000Sstevel@tonic-gate 		case IP_V4_G_HEAD:	version = "v4";	break;
4010Sstevel@tonic-gate 		case IP_V6_G_HEAD:	version = "v6";	break;
4020Sstevel@tonic-gate 		default:		version = "??"; break;
4030Sstevel@tonic-gate 	}
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	mdb_printf("%?p %2s %?p %10d %?p %s\n",
4060Sstevel@tonic-gate 	    addr, version, addr + offsetof(ill_if_t, illif_avl_by_ppa),
4070Sstevel@tonic-gate 	    iw->ill_if.illif_avl_by_ppa.avl_numnodes,
4080Sstevel@tonic-gate 	    iw->ill_if.illif_ppa_arena, iw->ill_if.illif_name);
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	id->ill_printed = TRUE;
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 	return (WALK_NEXT);
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate int
4165940Ssowmini ip_stacks_common_walk_init(mdb_walk_state_t *wsp)
4173448Sdh155122 {
4183448Sdh155122 	if (mdb_layered_walk("ip_stacks", wsp) == -1) {
4193448Sdh155122 		mdb_warn("can't walk 'ip_stacks'");
4203448Sdh155122 		return (WALK_ERR);
4213448Sdh155122 	}
4223448Sdh155122 
4233448Sdh155122 	return (WALK_NEXT);
4243448Sdh155122 }
4253448Sdh155122 
4263448Sdh155122 int
4273448Sdh155122 illif_walk_step(mdb_walk_state_t *wsp)
4283448Sdh155122 {
4293448Sdh155122 	uintptr_t kaddr;
4303448Sdh155122 
4313448Sdh155122 	kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ill_g_heads);
4323448Sdh155122 
4333448Sdh155122 	if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) {
4343448Sdh155122 		mdb_warn("can't read ips_ip_cache_table at %p", kaddr);
4353448Sdh155122 		return (WALK_ERR);
4363448Sdh155122 	}
4373448Sdh155122 
4383448Sdh155122 	if (mdb_pwalk("illif_stack", wsp->walk_callback,
4395023Scarlsonj 	    wsp->walk_cbdata, kaddr) == -1) {
4403448Sdh155122 		mdb_warn("couldn't walk 'illif_stack' for ips_ill_g_heads %p",
4413448Sdh155122 		    kaddr);
4423448Sdh155122 		return (WALK_ERR);
4433448Sdh155122 	}
4443448Sdh155122 	return (WALK_NEXT);
4453448Sdh155122 }
4463448Sdh155122 
4473448Sdh155122 int
4480Sstevel@tonic-gate illif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4490Sstevel@tonic-gate {
4500Sstevel@tonic-gate 	illif_cbdata_t id;
4510Sstevel@tonic-gate 	ill_if_t ill_if;
4520Sstevel@tonic-gate 	const char *opt_P = NULL;
4530Sstevel@tonic-gate 	int printlist = MAX_G_HEADS;
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
4560Sstevel@tonic-gate 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
4570Sstevel@tonic-gate 		return (DCMD_USAGE);
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 	if (opt_P != NULL) {
4600Sstevel@tonic-gate 		if (strcmp("v4", opt_P) == 0) {
4610Sstevel@tonic-gate 			printlist = IP_V4_G_HEAD;
4620Sstevel@tonic-gate 		} else if (strcmp("v6", opt_P) == 0) {
4630Sstevel@tonic-gate 			printlist = IP_V6_G_HEAD;
4640Sstevel@tonic-gate 		} else {
4650Sstevel@tonic-gate 			mdb_warn("invalid protocol '%s'\n", opt_P);
4660Sstevel@tonic-gate 			return (DCMD_USAGE);
4670Sstevel@tonic-gate 		}
4680Sstevel@tonic-gate 	}
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) {
4710Sstevel@tonic-gate 		mdb_printf("%<u>%?s %2s %?s %10s %?s %-10s%</u>\n",
4720Sstevel@tonic-gate 		    "ADDR", "IP", "AVLADDR", "NUMNODES", "ARENA", "NAME");
4730Sstevel@tonic-gate 	}
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	id.ill_flags = flags;
4760Sstevel@tonic-gate 	id.ill_addr = addr;
4770Sstevel@tonic-gate 	id.ill_printlist = printlist;
4780Sstevel@tonic-gate 	id.ill_printed = FALSE;
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 	if (mdb_walk("illif", (mdb_walk_cb_t)illif_cb, &id) == -1) {
4810Sstevel@tonic-gate 		mdb_warn("can't walk ill_if_t structures");
4820Sstevel@tonic-gate 		return (DCMD_ERR);
4830Sstevel@tonic-gate 	}
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC) || opt_P != NULL || id.ill_printed)
4860Sstevel@tonic-gate 		return (DCMD_OK);
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	/*
4890Sstevel@tonic-gate 	 * If an address is specified and the walk doesn't find it,
4900Sstevel@tonic-gate 	 * print it anyway.
4910Sstevel@tonic-gate 	 */
4920Sstevel@tonic-gate 	if (mdb_vread(&ill_if, sizeof (ill_if_t), addr) == -1) {
4930Sstevel@tonic-gate 		mdb_warn("failed to read ill_if_t at %p", addr);
4940Sstevel@tonic-gate 		return (DCMD_ERR);
4950Sstevel@tonic-gate 	}
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	mdb_printf("%?p %2s %?p %10d %?p %s\n",
4980Sstevel@tonic-gate 	    addr, "??", addr + offsetof(ill_if_t, illif_avl_by_ppa),
4990Sstevel@tonic-gate 	    ill_if.illif_avl_by_ppa.avl_numnodes,
5000Sstevel@tonic-gate 	    ill_if.illif_ppa_arena, ill_if.illif_name);
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	return (DCMD_OK);
5030Sstevel@tonic-gate }
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate static void
5060Sstevel@tonic-gate illif_help(void)
5070Sstevel@tonic-gate {
5080Sstevel@tonic-gate 	mdb_printf("Options:\n");
5090Sstevel@tonic-gate 	mdb_printf("\t-P v4 | v6"
5100Sstevel@tonic-gate 	    "\tfilter interface structures for the specified protocol\n");
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate int
5140Sstevel@tonic-gate ire_walk_init(mdb_walk_state_t *wsp)
5150Sstevel@tonic-gate {
5160Sstevel@tonic-gate 	if (mdb_layered_walk("ire_cache", wsp) == -1) {
5170Sstevel@tonic-gate 		mdb_warn("can't walk 'ire_cache'");
5180Sstevel@tonic-gate 		return (WALK_ERR);
5190Sstevel@tonic-gate 	}
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 	return (WALK_NEXT);
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate int
5250Sstevel@tonic-gate ire_walk_step(mdb_walk_state_t *wsp)
5260Sstevel@tonic-gate {
5270Sstevel@tonic-gate 	ire_t ire;
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) {
5300Sstevel@tonic-gate 		mdb_warn("can't read ire at %p", wsp->walk_addr);
5310Sstevel@tonic-gate 		return (WALK_ERR);
5320Sstevel@tonic-gate 	}
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	return (wsp->walk_callback(wsp->walk_addr, &ire, wsp->walk_cbdata));
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate 
5373448Sdh155122 
5383448Sdh155122 int
5393448Sdh155122 ire_ctable_walk_step(mdb_walk_state_t *wsp)
5403448Sdh155122 {
5413448Sdh155122 	uintptr_t kaddr;
5423448Sdh155122 	irb_t *irb;
5433448Sdh155122 	uint32_t cache_table_size;
5443448Sdh155122 	int i;
5455940Ssowmini 	ire_cbdata_t ire_cb;
5463448Sdh155122 
5475940Ssowmini 	ire_cb.verbose = B_FALSE;
5485940Ssowmini 	ire_cb.ire_ipversion = 0;
5495940Ssowmini 
5503448Sdh155122 
5513448Sdh155122 	kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ip_cache_table_size);
5523448Sdh155122 
5533448Sdh155122 	if (mdb_vread(&cache_table_size, sizeof (uint32_t), kaddr) == -1) {
5543448Sdh155122 		mdb_warn("can't read ips_ip_cache_table at %p", kaddr);
5553448Sdh155122 		return (WALK_ERR);
5563448Sdh155122 	}
5573448Sdh155122 
5583448Sdh155122 	kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ip_cache_table);
5593448Sdh155122 	if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) {
5603448Sdh155122 		mdb_warn("can't read ips_ip_cache_table at %p", kaddr);
5613448Sdh155122 		return (WALK_ERR);
5623448Sdh155122 	}
5633448Sdh155122 
5643448Sdh155122 	irb = mdb_alloc(sizeof (irb_t) * cache_table_size, UM_SLEEP|UM_GC);
5653448Sdh155122 	if (mdb_vread(irb, sizeof (irb_t) * cache_table_size, kaddr) == -1) {
5663448Sdh155122 		mdb_warn("can't read irb at %p", kaddr);
5673448Sdh155122 		return (WALK_ERR);
5683448Sdh155122 	}
5693448Sdh155122 	for (i = 0; i < cache_table_size; i++) {
5703448Sdh155122 		kaddr = (uintptr_t)irb[i].irb_ire;
5713448Sdh155122 
5725940Ssowmini 		if (mdb_pwalk("ire_next", ire_format, &ire_cb,
5735023Scarlsonj 		    kaddr) == -1) {
5743448Sdh155122 			mdb_warn("can't walk 'ire_next' for ire %p", kaddr);
5753448Sdh155122 			return (WALK_ERR);
5763448Sdh155122 		}
5773448Sdh155122 	}
5783448Sdh155122 	return (WALK_NEXT);
5793448Sdh155122 }
5803448Sdh155122 
5813448Sdh155122 /* ARGSUSED */
5823448Sdh155122 int
5833448Sdh155122 ire_next_walk_init(mdb_walk_state_t *wsp)
5843448Sdh155122 {
5853448Sdh155122 	return (WALK_NEXT);
5863448Sdh155122 }
5873448Sdh155122 
5883448Sdh155122 int
5893448Sdh155122 ire_next_walk_step(mdb_walk_state_t *wsp)
5903448Sdh155122 {
5913448Sdh155122 	ire_t ire;
5923448Sdh155122 	int status;
5933448Sdh155122 
5943448Sdh155122 
5953448Sdh155122 	if (wsp->walk_addr == NULL)
5963448Sdh155122 		return (WALK_DONE);
5973448Sdh155122 
5983448Sdh155122 	if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) {
5993448Sdh155122 		mdb_warn("can't read ire at %p", wsp->walk_addr);
6003448Sdh155122 		return (WALK_ERR);
6013448Sdh155122 	}
6023448Sdh155122 	status = wsp->walk_callback(wsp->walk_addr, &ire,
6033448Sdh155122 	    wsp->walk_cbdata);
6043448Sdh155122 
6053448Sdh155122 	if (status != WALK_NEXT)
6063448Sdh155122 		return (status);
6073448Sdh155122 
6083448Sdh155122 	wsp->walk_addr = (uintptr_t)ire.ire_next;
6093448Sdh155122 	return (status);
6103448Sdh155122 }
6113448Sdh155122 
6120Sstevel@tonic-gate static int
6135940Ssowmini ire_format(uintptr_t addr, const void *ire_arg, void *ire_cb_arg)
6140Sstevel@tonic-gate {
6155940Ssowmini 	const ire_t *irep = ire_arg;
6165940Ssowmini 	ire_cbdata_t *ire_cb = ire_cb_arg;
6175940Ssowmini 	boolean_t verbose = ire_cb->verbose;
6185940Ssowmini 
6190Sstevel@tonic-gate 	static const mdb_bitmask_t tmasks[] = {
6200Sstevel@tonic-gate 		{ "BROADCAST",	IRE_BROADCAST,		IRE_BROADCAST	},
6210Sstevel@tonic-gate 		{ "DEFAULT",	IRE_DEFAULT,		IRE_DEFAULT	},
6220Sstevel@tonic-gate 		{ "LOCAL",	IRE_LOCAL,		IRE_LOCAL	},
6230Sstevel@tonic-gate 		{ "LOOPBACK",	IRE_LOOPBACK,		IRE_LOOPBACK	},
6240Sstevel@tonic-gate 		{ "PREFIX",	IRE_PREFIX,		IRE_PREFIX	},
6250Sstevel@tonic-gate 		{ "CACHE",	IRE_CACHE,		IRE_CACHE	},
6260Sstevel@tonic-gate 		{ "IF_NORESOLVER", IRE_IF_NORESOLVER,	IRE_IF_NORESOLVER },
6270Sstevel@tonic-gate 		{ "IF_RESOLVER", IRE_IF_RESOLVER,	IRE_IF_RESOLVER	},
6280Sstevel@tonic-gate 		{ "HOST",	IRE_HOST,		IRE_HOST	},
6290Sstevel@tonic-gate 		{ "HOST_REDIRECT", IRE_HOST_REDIRECT,	IRE_HOST_REDIRECT },
6300Sstevel@tonic-gate 		{ NULL,		0,			0		}
6310Sstevel@tonic-gate 	};
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	static const mdb_bitmask_t mmasks[] = {
6340Sstevel@tonic-gate 		{ "CONDEMNED",	IRE_MARK_CONDEMNED,	IRE_MARK_CONDEMNED },
635*9089SVasumathi.Sundaram@Sun.COM 		{ "TESTHIDDEN", IRE_MARK_TESTHIDDEN,    IRE_MARK_TESTHIDDEN },
6360Sstevel@tonic-gate 		{ "NOADD",	IRE_MARK_NOADD,		IRE_MARK_NOADD	},
6370Sstevel@tonic-gate 		{ "TEMPORARY",	IRE_MARK_TEMPORARY,	IRE_MARK_TEMPORARY },
6385940Ssowmini 		{ "USESRC",	IRE_MARK_USESRC_CHECK,	IRE_MARK_USESRC_CHECK },
6395940Ssowmini 		{ "PRIVATE",	IRE_MARK_PRIVATE_ADDR,	IRE_MARK_PRIVATE_ADDR },
6405940Ssowmini 		{ "UNCACHED",	IRE_MARK_UNCACHED,	IRE_MARK_UNCACHED },
6410Sstevel@tonic-gate 		{ NULL,		0,			0		}
6420Sstevel@tonic-gate 	};
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate 	static const mdb_bitmask_t fmasks[] = {
6450Sstevel@tonic-gate 		{ "UP",		RTF_UP,			RTF_UP		},
6460Sstevel@tonic-gate 		{ "GATEWAY",	RTF_GATEWAY,		RTF_GATEWAY	},
6470Sstevel@tonic-gate 		{ "HOST",	RTF_HOST,		RTF_HOST	},
6480Sstevel@tonic-gate 		{ "REJECT",	RTF_REJECT,		RTF_REJECT	},
6490Sstevel@tonic-gate 		{ "DYNAMIC",	RTF_DYNAMIC,		RTF_DYNAMIC	},
6500Sstevel@tonic-gate 		{ "MODIFIED",	RTF_MODIFIED,		RTF_MODIFIED	},
6510Sstevel@tonic-gate 		{ "DONE",	RTF_DONE,		RTF_DONE	},
6520Sstevel@tonic-gate 		{ "MASK",	RTF_MASK,		RTF_MASK	},
6530Sstevel@tonic-gate 		{ "CLONING",	RTF_CLONING,		RTF_CLONING	},
6540Sstevel@tonic-gate 		{ "XRESOLVE",	RTF_XRESOLVE,		RTF_XRESOLVE	},
6550Sstevel@tonic-gate 		{ "LLINFO",	RTF_LLINFO,		RTF_LLINFO	},
6560Sstevel@tonic-gate 		{ "STATIC",	RTF_STATIC,		RTF_STATIC	},
6570Sstevel@tonic-gate 		{ "BLACKHOLE",	RTF_BLACKHOLE,		RTF_BLACKHOLE	},
6580Sstevel@tonic-gate 		{ "PRIVATE",	RTF_PRIVATE,		RTF_PRIVATE	},
6590Sstevel@tonic-gate 		{ "PROTO2",	RTF_PROTO2,		RTF_PROTO2	},
6600Sstevel@tonic-gate 		{ "PROTO1",	RTF_PROTO1,		RTF_PROTO1	},
6610Sstevel@tonic-gate 		{ "MULTIRT",	RTF_MULTIRT,		RTF_MULTIRT	},
6620Sstevel@tonic-gate 		{ "SETSRC",	RTF_SETSRC,		RTF_SETSRC	},
6630Sstevel@tonic-gate 		{ NULL,		0,			0		}
6640Sstevel@tonic-gate 	};
6650Sstevel@tonic-gate 
6665940Ssowmini 	if (ire_cb->ire_ipversion != 0 &&
6675940Ssowmini 	    irep->ire_ipversion != ire_cb->ire_ipversion)
6685940Ssowmini 		return (WALK_NEXT);
6695940Ssowmini 
6705940Ssowmini 	if (irep->ire_ipversion == IPV6_VERSION && verbose) {
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 		mdb_printf("%<b>%?p%</b> %40N <%hb>\n"
6730Sstevel@tonic-gate 		    "%?s %40N <%hb>\n"
6743448Sdh155122 		    "%?s %40d %4d <%hb>\n",
6750Sstevel@tonic-gate 		    addr, &irep->ire_src_addr_v6, irep->ire_type, tmasks,
6760Sstevel@tonic-gate 		    "", &irep->ire_addr_v6, (ushort_t)irep->ire_marks, mmasks,
6773448Sdh155122 		    "", ips_to_stackid((uintptr_t)irep->ire_ipst),
6783448Sdh155122 		    irep->ire_zoneid,
6793448Sdh155122 		    irep->ire_flags, fmasks);
6800Sstevel@tonic-gate 
6815940Ssowmini 	} else if (irep->ire_ipversion == IPV6_VERSION) {
6820Sstevel@tonic-gate 
6833448Sdh155122 		mdb_printf("%?p %30N %30N %5d %4d\n",
6843448Sdh155122 		    addr, &irep->ire_src_addr_v6,
6853448Sdh155122 		    &irep->ire_addr_v6,
6863448Sdh155122 		    ips_to_stackid((uintptr_t)irep->ire_ipst),
6873448Sdh155122 		    irep->ire_zoneid);
6880Sstevel@tonic-gate 
6895940Ssowmini 	} else if (verbose) {
6900Sstevel@tonic-gate 
6910Sstevel@tonic-gate 		mdb_printf("%<b>%?p%</b> %40I <%hb>\n"
6920Sstevel@tonic-gate 		    "%?s %40I <%hb>\n"
6935940Ssowmini 		    "%?s %40d %4d <%hb>\n",
6940Sstevel@tonic-gate 		    addr, irep->ire_src_addr, irep->ire_type, tmasks,
6950Sstevel@tonic-gate 		    "", irep->ire_addr, (ushort_t)irep->ire_marks, mmasks,
6963448Sdh155122 		    "", ips_to_stackid((uintptr_t)irep->ire_ipst),
6973448Sdh155122 		    irep->ire_zoneid, irep->ire_flags, fmasks);
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 	} else {
7000Sstevel@tonic-gate 
7013448Sdh155122 		mdb_printf("%?p %30I %30I %5d %4d\n", addr, irep->ire_src_addr,
7023448Sdh155122 		    irep->ire_addr, ips_to_stackid((uintptr_t)irep->ire_ipst),
7033448Sdh155122 		    irep->ire_zoneid);
7040Sstevel@tonic-gate 	}
7050Sstevel@tonic-gate 
7060Sstevel@tonic-gate 	return (WALK_NEXT);
7070Sstevel@tonic-gate }
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate /*
7100Sstevel@tonic-gate  * There are faster ways to do this.  Given the interactive nature of this
7110Sstevel@tonic-gate  * use I don't think its worth much effort.
7120Sstevel@tonic-gate  */
7130Sstevel@tonic-gate static unsigned short
7140Sstevel@tonic-gate ipcksum(void *p, int len)
7150Sstevel@tonic-gate {
7160Sstevel@tonic-gate 	int32_t	sum = 0;
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 	while (len > 1) {
7190Sstevel@tonic-gate 		/* alignment */
7200Sstevel@tonic-gate 		sum += *(uint16_t *)p;
7210Sstevel@tonic-gate 		p = (char *)p + sizeof (uint16_t);
7220Sstevel@tonic-gate 		if (sum & 0x80000000)
7230Sstevel@tonic-gate 			sum = (sum & 0xFFFF) + (sum >> 16);
7240Sstevel@tonic-gate 		len -= 2;
7250Sstevel@tonic-gate 	}
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 	if (len)
7280Sstevel@tonic-gate 		sum += (uint16_t)*(unsigned char *)p;
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 	while (sum >> 16)
7310Sstevel@tonic-gate 		sum = (sum & 0xFFFF) + (sum >> 16);
7320Sstevel@tonic-gate 
7330Sstevel@tonic-gate 	return (~sum);
7340Sstevel@tonic-gate }
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate static const mdb_bitmask_t tcp_flags[] = {
7370Sstevel@tonic-gate 	{ "SYN",	TH_SYN,		TH_SYN	},
7380Sstevel@tonic-gate 	{ "ACK",	TH_ACK,		TH_ACK	},
7390Sstevel@tonic-gate 	{ "FIN",	TH_FIN,		TH_FIN	},
7400Sstevel@tonic-gate 	{ "RST",	TH_RST,		TH_RST	},
7410Sstevel@tonic-gate 	{ "PSH",	TH_PUSH,	TH_PUSH	},
7420Sstevel@tonic-gate 	{ "ECE",	TH_ECE,		TH_ECE	},
7430Sstevel@tonic-gate 	{ "CWR",	TH_CWR,		TH_CWR	},
7440Sstevel@tonic-gate 	{ NULL,		0,		0	}
7450Sstevel@tonic-gate };
7460Sstevel@tonic-gate 
7470Sstevel@tonic-gate static void
7480Sstevel@tonic-gate tcphdr_print(struct tcphdr *tcph)
7490Sstevel@tonic-gate {
7500Sstevel@tonic-gate 	in_port_t	sport, dport;
7510Sstevel@tonic-gate 	tcp_seq		seq, ack;
7520Sstevel@tonic-gate 	uint16_t	win, urp;
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 	mdb_printf("%<b>TCP header%</b>\n");
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 	mdb_nhconvert(&sport, &tcph->th_sport, sizeof (sport));
7570Sstevel@tonic-gate 	mdb_nhconvert(&dport, &tcph->th_dport, sizeof (dport));
7580Sstevel@tonic-gate 	mdb_nhconvert(&seq, &tcph->th_seq, sizeof (seq));
7590Sstevel@tonic-gate 	mdb_nhconvert(&ack, &tcph->th_ack, sizeof (ack));
7600Sstevel@tonic-gate 	mdb_nhconvert(&win, &tcph->th_win, sizeof (win));
7610Sstevel@tonic-gate 	mdb_nhconvert(&urp, &tcph->th_urp, sizeof (urp));
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate 	mdb_printf("%<u>%6s %6s %10s %10s %4s %5s %5s %5s %-15s%</u>\n",
7640Sstevel@tonic-gate 	    "SPORT", "DPORT", "SEQ", "ACK", "HLEN", "WIN", "CSUM", "URP",
7650Sstevel@tonic-gate 	    "FLAGS");
7660Sstevel@tonic-gate 	mdb_printf("%6hu %6hu %10u %10u %4d %5hu %5hu %5hu <%b>\n",
7670Sstevel@tonic-gate 	    sport, dport, seq, ack, tcph->th_off << 2, win,
7680Sstevel@tonic-gate 	    tcph->th_sum, urp, tcph->th_flags, tcp_flags);
7690Sstevel@tonic-gate 	mdb_printf("0x%04x 0x%04x 0x%08x 0x%08x\n\n",
7700Sstevel@tonic-gate 	    sport, dport, seq, ack);
7710Sstevel@tonic-gate }
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate /* ARGSUSED */
7740Sstevel@tonic-gate static int
7750Sstevel@tonic-gate tcphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av)
7760Sstevel@tonic-gate {
7770Sstevel@tonic-gate 	struct tcphdr	tcph;
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
7800Sstevel@tonic-gate 		return (DCMD_USAGE);
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate 	if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) {
7830Sstevel@tonic-gate 		mdb_warn("failed to read TCP header at %p", addr);
7840Sstevel@tonic-gate 		return (DCMD_ERR);
7850Sstevel@tonic-gate 	}
7860Sstevel@tonic-gate 	tcphdr_print(&tcph);
7870Sstevel@tonic-gate 	return (DCMD_OK);
7880Sstevel@tonic-gate }
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate static void
7910Sstevel@tonic-gate udphdr_print(struct udphdr *udph)
7920Sstevel@tonic-gate {
7930Sstevel@tonic-gate 	in_port_t	sport, dport;
7940Sstevel@tonic-gate 	uint16_t	hlen;
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate 	mdb_printf("%<b>UDP header%</b>\n");
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate 	mdb_nhconvert(&sport, &udph->uh_sport, sizeof (sport));
7990Sstevel@tonic-gate 	mdb_nhconvert(&dport, &udph->uh_dport, sizeof (dport));
8000Sstevel@tonic-gate 	mdb_nhconvert(&hlen, &udph->uh_ulen, sizeof (hlen));
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 	mdb_printf("%<u>%14s %14s %5s %6s%</u>\n",
8030Sstevel@tonic-gate 	    "SPORT", "DPORT", "LEN", "CSUM");
8040Sstevel@tonic-gate 	mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %5hu 0x%04hx\n\n", sport, sport,
8050Sstevel@tonic-gate 	    dport, dport, hlen, udph->uh_sum);
8060Sstevel@tonic-gate }
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate /* ARGSUSED */
8090Sstevel@tonic-gate static int
8100Sstevel@tonic-gate udphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av)
8110Sstevel@tonic-gate {
8120Sstevel@tonic-gate 	struct udphdr	udph;
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
8150Sstevel@tonic-gate 		return (DCMD_USAGE);
8160Sstevel@tonic-gate 
8170Sstevel@tonic-gate 	if (mdb_vread(&udph, sizeof (udph), addr) == -1) {
8180Sstevel@tonic-gate 		mdb_warn("failed to read UDP header at %p", addr);
8190Sstevel@tonic-gate 		return (DCMD_ERR);
8200Sstevel@tonic-gate 	}
8210Sstevel@tonic-gate 	udphdr_print(&udph);
8220Sstevel@tonic-gate 	return (DCMD_OK);
8230Sstevel@tonic-gate }
8240Sstevel@tonic-gate 
8250Sstevel@tonic-gate static void
8260Sstevel@tonic-gate sctphdr_print(sctp_hdr_t *sctph)
8270Sstevel@tonic-gate {
8280Sstevel@tonic-gate 	in_port_t sport, dport;
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate 	mdb_printf("%<b>SCTP header%</b>\n");
8310Sstevel@tonic-gate 	mdb_nhconvert(&sport, &sctph->sh_sport, sizeof (sport));
8320Sstevel@tonic-gate 	mdb_nhconvert(&dport, &sctph->sh_dport, sizeof (dport));
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 	mdb_printf("%<u>%14s %14s %10s %10s%</u>\n",
8350Sstevel@tonic-gate 	    "SPORT", "DPORT", "VTAG", "CHKSUM");
8360Sstevel@tonic-gate 	mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %10u 0x%08x\n\n", sport, sport,
8370Sstevel@tonic-gate 	    dport, dport, sctph->sh_verf, sctph->sh_chksum);
8380Sstevel@tonic-gate }
8390Sstevel@tonic-gate 
8400Sstevel@tonic-gate /* ARGSUSED */
8410Sstevel@tonic-gate static int
8420Sstevel@tonic-gate sctphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av)
8430Sstevel@tonic-gate {
8440Sstevel@tonic-gate 	sctp_hdr_t sctph;
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
8470Sstevel@tonic-gate 		return (DCMD_USAGE);
8480Sstevel@tonic-gate 
8490Sstevel@tonic-gate 	if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) {
8500Sstevel@tonic-gate 		mdb_warn("failed to read SCTP header at %p", addr);
8510Sstevel@tonic-gate 		return (DCMD_ERR);
8520Sstevel@tonic-gate 	}
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 	sctphdr_print(&sctph);
8550Sstevel@tonic-gate 	return (DCMD_OK);
8560Sstevel@tonic-gate }
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate static int
8590Sstevel@tonic-gate transport_hdr(int proto, uintptr_t addr)
8600Sstevel@tonic-gate {
8610Sstevel@tonic-gate 	mdb_printf("\n");
8620Sstevel@tonic-gate 	switch (proto) {
8630Sstevel@tonic-gate 	case IPPROTO_TCP: {
8640Sstevel@tonic-gate 		struct tcphdr tcph;
8650Sstevel@tonic-gate 
8660Sstevel@tonic-gate 		if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) {
8670Sstevel@tonic-gate 			mdb_warn("failed to read TCP header at %p", addr);
8680Sstevel@tonic-gate 			return (DCMD_ERR);
8690Sstevel@tonic-gate 		}
8700Sstevel@tonic-gate 		tcphdr_print(&tcph);
8710Sstevel@tonic-gate 		break;
8720Sstevel@tonic-gate 	}
8730Sstevel@tonic-gate 	case IPPROTO_UDP:  {
8740Sstevel@tonic-gate 		struct udphdr udph;
8750Sstevel@tonic-gate 
8760Sstevel@tonic-gate 		if (mdb_vread(&udph, sizeof (udph), addr) == -1) {
8770Sstevel@tonic-gate 			mdb_warn("failed to read UDP header at %p", addr);
8780Sstevel@tonic-gate 			return (DCMD_ERR);
8790Sstevel@tonic-gate 		}
8800Sstevel@tonic-gate 		udphdr_print(&udph);
8810Sstevel@tonic-gate 		break;
8820Sstevel@tonic-gate 	}
8830Sstevel@tonic-gate 	case IPPROTO_SCTP: {
8840Sstevel@tonic-gate 		sctp_hdr_t sctph;
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate 		if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) {
8870Sstevel@tonic-gate 			mdb_warn("failed to read SCTP header at %p", addr);
8880Sstevel@tonic-gate 			return (DCMD_ERR);
8890Sstevel@tonic-gate 		}
8900Sstevel@tonic-gate 		sctphdr_print(&sctph);
8910Sstevel@tonic-gate 		break;
8920Sstevel@tonic-gate 	}
8930Sstevel@tonic-gate 	default:
8940Sstevel@tonic-gate 		break;
8950Sstevel@tonic-gate 	}
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 	return (DCMD_OK);
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate 
9000Sstevel@tonic-gate static const mdb_bitmask_t ip_flags[] = {
9010Sstevel@tonic-gate 	{ "DF",	IPH_DF, IPH_DF	},
9020Sstevel@tonic-gate 	{ "MF", IPH_MF,	IPH_MF	},
9030Sstevel@tonic-gate 	{ NULL, 0,	0	}
9040Sstevel@tonic-gate };
9050Sstevel@tonic-gate 
9060Sstevel@tonic-gate /* ARGSUSED */
9070Sstevel@tonic-gate static int
9080Sstevel@tonic-gate iphdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
9090Sstevel@tonic-gate {
9100Sstevel@tonic-gate 	uint_t		verbose = FALSE, force = FALSE;
9110Sstevel@tonic-gate 	ipha_t		iph[1];
9120Sstevel@tonic-gate 	uint16_t	ver, totlen, hdrlen, ipid, off, csum;
9130Sstevel@tonic-gate 	uintptr_t	nxt_proto;
9140Sstevel@tonic-gate 	char		exp_csum[8];
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
9170Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
9180Sstevel@tonic-gate 	    'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc)
9190Sstevel@tonic-gate 		return (DCMD_USAGE);
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate 	if (mdb_vread(iph, sizeof (*iph), addr) == -1) {
9220Sstevel@tonic-gate 		mdb_warn("failed to read IPv4 header at %p", addr);
9230Sstevel@tonic-gate 		return (DCMD_ERR);
9240Sstevel@tonic-gate 	}
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 	ver = (iph->ipha_version_and_hdr_length & 0xf0) >> 4;
9270Sstevel@tonic-gate 	if (ver != IPV4_VERSION) {
9280Sstevel@tonic-gate 		if (ver == IPV6_VERSION) {
9290Sstevel@tonic-gate 			return (ip6hdr(addr, flags, argc, argv));
9300Sstevel@tonic-gate 		} else if (!force) {
9310Sstevel@tonic-gate 			mdb_warn("unknown IP version: %d\n", ver);
9320Sstevel@tonic-gate 			return (DCMD_ERR);
9330Sstevel@tonic-gate 		}
9340Sstevel@tonic-gate 	}
9350Sstevel@tonic-gate 
9360Sstevel@tonic-gate 	mdb_printf("%<b>IPv4 header%</b>\n");
9370Sstevel@tonic-gate 	mdb_printf("%-34s %-34s\n"
9380Sstevel@tonic-gate 	    "%<u>%-4s %-4s %-5s %-5s %-6s %-5s %-5s %-6s %-8s %-6s%</u>\n",
9390Sstevel@tonic-gate 	    "SRC", "DST",
9400Sstevel@tonic-gate 	    "HLEN", "TOS", "LEN", "ID", "OFFSET", "TTL", "PROTO", "CHKSUM",
9410Sstevel@tonic-gate 	    "EXP-CSUM", "FLGS");
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 	hdrlen = (iph->ipha_version_and_hdr_length & 0x0f) << 2;
9440Sstevel@tonic-gate 	mdb_nhconvert(&totlen, &iph->ipha_length, sizeof (totlen));
9450Sstevel@tonic-gate 	mdb_nhconvert(&ipid, &iph->ipha_ident, sizeof (ipid));
9460Sstevel@tonic-gate 	mdb_nhconvert(&off, &iph->ipha_fragment_offset_and_flags, sizeof (off));
9470Sstevel@tonic-gate 	if (hdrlen == IP_SIMPLE_HDR_LENGTH) {
9480Sstevel@tonic-gate 		if ((csum = ipcksum(iph, sizeof (*iph))) != 0)
9490Sstevel@tonic-gate 			csum = ~(~csum + ~iph->ipha_hdr_checksum);
9500Sstevel@tonic-gate 		else
9510Sstevel@tonic-gate 			csum = iph->ipha_hdr_checksum;
9520Sstevel@tonic-gate 		mdb_snprintf(exp_csum, 8, "%u", csum);
9530Sstevel@tonic-gate 	} else {
9540Sstevel@tonic-gate 		mdb_snprintf(exp_csum, 8, "<n/a>");
9550Sstevel@tonic-gate 	}
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 	mdb_printf("%-34I %-34I%\n"
9580Sstevel@tonic-gate 	    "%-4d %-4d %-5hu %-5hu %-6hu %-5hu %-5hu %-6u %-8s <%5hb>\n",
9590Sstevel@tonic-gate 	    iph->ipha_src, iph->ipha_dst,
9600Sstevel@tonic-gate 	    hdrlen, iph->ipha_type_of_service, totlen, ipid,
9610Sstevel@tonic-gate 	    (off << 3) & 0xffff, iph->ipha_ttl, iph->ipha_protocol,
9620Sstevel@tonic-gate 	    iph->ipha_hdr_checksum, exp_csum, off, ip_flags);
9630Sstevel@tonic-gate 
9640Sstevel@tonic-gate 	if (verbose) {
9650Sstevel@tonic-gate 		nxt_proto = addr + hdrlen;
9660Sstevel@tonic-gate 		return (transport_hdr(iph->ipha_protocol, nxt_proto));
9670Sstevel@tonic-gate 	} else {
9680Sstevel@tonic-gate 		return (DCMD_OK);
9690Sstevel@tonic-gate 	}
9700Sstevel@tonic-gate }
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate /* ARGSUSED */
9730Sstevel@tonic-gate static int
9740Sstevel@tonic-gate ip6hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
9750Sstevel@tonic-gate {
9760Sstevel@tonic-gate 	uint_t		verbose = FALSE, force = FALSE;
9770Sstevel@tonic-gate 	ip6_t		iph[1];
9780Sstevel@tonic-gate 	int		ver, class, flow;
9790Sstevel@tonic-gate 	uint16_t	plen;
9800Sstevel@tonic-gate 	uintptr_t	nxt_proto;
9810Sstevel@tonic-gate 
9820Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
9830Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
9840Sstevel@tonic-gate 	    'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc)
9850Sstevel@tonic-gate 		return (DCMD_USAGE);
9860Sstevel@tonic-gate 
9870Sstevel@tonic-gate 	if (mdb_vread(iph, sizeof (*iph), addr) == -1) {
9880Sstevel@tonic-gate 		mdb_warn("failed to read IPv6 header at %p", addr);
9890Sstevel@tonic-gate 		return (DCMD_ERR);
9900Sstevel@tonic-gate 	}
9910Sstevel@tonic-gate 
9920Sstevel@tonic-gate 	ver = (iph->ip6_vfc & 0xf0) >> 4;
9930Sstevel@tonic-gate 	if (ver != IPV6_VERSION) {
9940Sstevel@tonic-gate 		if (ver == IPV4_VERSION) {
9950Sstevel@tonic-gate 			return (iphdr(addr, flags, argc, argv));
9960Sstevel@tonic-gate 		} else if (!force) {
9970Sstevel@tonic-gate 			mdb_warn("unknown IP version: %d\n", ver);
9980Sstevel@tonic-gate 			return (DCMD_ERR);
9990Sstevel@tonic-gate 		}
10000Sstevel@tonic-gate 	}
10010Sstevel@tonic-gate 
10020Sstevel@tonic-gate 	mdb_printf("%<b>IPv6 header%</b>\n");
10030Sstevel@tonic-gate 	mdb_printf("%<u>%-26s %-26s %4s %7s %5s %3s %3s%</u>\n",
10040Sstevel@tonic-gate 	    "SRC", "DST", "TCLS", "FLOW-ID", "PLEN", "NXT", "HOP");
10050Sstevel@tonic-gate 
10060Sstevel@tonic-gate 	class = (iph->ip6_vcf & IPV6_FLOWINFO_TCLASS) >> 20;
10070Sstevel@tonic-gate 	mdb_nhconvert(&class, &class, sizeof (class));
10080Sstevel@tonic-gate 	flow = iph->ip6_vcf & IPV6_FLOWINFO_FLOWLABEL;
10090Sstevel@tonic-gate 	mdb_nhconvert(&flow, &flow, sizeof (flow));
10100Sstevel@tonic-gate 	mdb_nhconvert(&plen, &iph->ip6_plen, sizeof (plen));
10110Sstevel@tonic-gate 
10120Sstevel@tonic-gate 	mdb_printf("%-26N %-26N %4d %7d %5hu %3d %3d\n",
10130Sstevel@tonic-gate 	    &iph->ip6_src, &iph->ip6_dst,
10140Sstevel@tonic-gate 	    class, flow, plen, iph->ip6_nxt, iph->ip6_hlim);
10150Sstevel@tonic-gate 
10160Sstevel@tonic-gate 	if (verbose) {
10170Sstevel@tonic-gate 		nxt_proto = addr + sizeof (ip6_t);
10180Sstevel@tonic-gate 		return (transport_hdr(iph->ip6_nxt, nxt_proto));
10190Sstevel@tonic-gate 	} else {
10200Sstevel@tonic-gate 		return (DCMD_OK);
10210Sstevel@tonic-gate 	}
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate 
10240Sstevel@tonic-gate int
10250Sstevel@tonic-gate ire(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
10260Sstevel@tonic-gate {
10270Sstevel@tonic-gate 	uint_t verbose = FALSE;
10280Sstevel@tonic-gate 	ire_t ire;
10295940Ssowmini 	ire_cbdata_t ire_cb;
10305940Ssowmini 	int ipversion = 0;
10315940Ssowmini 	const char *opt_P = NULL;
10320Sstevel@tonic-gate 
10330Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
10345940Ssowmini 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
10355940Ssowmini 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
10360Sstevel@tonic-gate 		return (DCMD_USAGE);
10370Sstevel@tonic-gate 
10385940Ssowmini 	if (opt_P != NULL) {
10395940Ssowmini 		if (strcmp("v4", opt_P) == 0) {
10405940Ssowmini 			ipversion = IPV4_VERSION;
10415940Ssowmini 		} else if (strcmp("v6", opt_P) == 0) {
10425940Ssowmini 			ipversion = IPV6_VERSION;
10435940Ssowmini 		} else {
10445940Ssowmini 			mdb_warn("invalid protocol '%s'\n", opt_P);
10455940Ssowmini 			return (DCMD_USAGE);
10465940Ssowmini 		}
10475940Ssowmini 	}
10485940Ssowmini 
10490Sstevel@tonic-gate 	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
10500Sstevel@tonic-gate 
10510Sstevel@tonic-gate 		if (verbose) {
10520Sstevel@tonic-gate 			mdb_printf("%?s %40s %-20s%\n"
10530Sstevel@tonic-gate 			    "%?s %40s %-20s%\n"
10543448Sdh155122 			    "%<u>%?s %40s %4s %-20s%</u>\n",
10550Sstevel@tonic-gate 			    "ADDR", "SRC", "TYPE",
10560Sstevel@tonic-gate 			    "", "DST", "MARKS",
10573448Sdh155122 			    "", "STACK", "ZONE", "FLAGS");
10580Sstevel@tonic-gate 		} else {
10593448Sdh155122 			mdb_printf("%<u>%?s %30s %30s %5s %4s%</u>\n",
10603448Sdh155122 			    "ADDR", "SRC", "DST", "STACK", "ZONE");
10610Sstevel@tonic-gate 		}
10620Sstevel@tonic-gate 	}
10630Sstevel@tonic-gate 
10645940Ssowmini 	ire_cb.verbose = (verbose == TRUE);
10655940Ssowmini 	ire_cb.ire_ipversion = ipversion;
10665940Ssowmini 
10670Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC) {
10680Sstevel@tonic-gate 		(void) mdb_vread(&ire, sizeof (ire_t), addr);
10695940Ssowmini 		(void) ire_format(addr, &ire, &ire_cb);
10705940Ssowmini 	} else if (mdb_walk("ire", (mdb_walk_cb_t)ire_format, &ire_cb) == -1) {
10710Sstevel@tonic-gate 		mdb_warn("failed to walk ire table");
10720Sstevel@tonic-gate 		return (DCMD_ERR);
10730Sstevel@tonic-gate 	}
10740Sstevel@tonic-gate 
10750Sstevel@tonic-gate 	return (DCMD_OK);
10760Sstevel@tonic-gate }
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate static size_t
10790Sstevel@tonic-gate mi_osize(const queue_t *q)
10800Sstevel@tonic-gate {
10810Sstevel@tonic-gate 	/*
10820Sstevel@tonic-gate 	 * The code in common/inet/mi.c allocates an extra word to store the
10830Sstevel@tonic-gate 	 * size of the allocation.  An mi_o_s is thus a size_t plus an mi_o_s.
10840Sstevel@tonic-gate 	 */
10850Sstevel@tonic-gate 	struct mi_block {
10860Sstevel@tonic-gate 		size_t mi_nbytes;
10870Sstevel@tonic-gate 		struct mi_o_s mi_o;
10880Sstevel@tonic-gate 	} m;
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 	if (mdb_vread(&m, sizeof (m), (uintptr_t)q->q_ptr -
10910Sstevel@tonic-gate 	    sizeof (m)) == sizeof (m))
10920Sstevel@tonic-gate 		return (m.mi_nbytes - sizeof (m));
10930Sstevel@tonic-gate 
10940Sstevel@tonic-gate 	return (0);
10950Sstevel@tonic-gate }
10960Sstevel@tonic-gate 
10970Sstevel@tonic-gate static void
10980Sstevel@tonic-gate ip_ill_qinfo(const queue_t *q, char *buf, size_t nbytes)
10990Sstevel@tonic-gate {
11000Sstevel@tonic-gate 	char name[32];
11010Sstevel@tonic-gate 	ill_t ill;
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	if (mdb_vread(&ill, sizeof (ill),
11040Sstevel@tonic-gate 	    (uintptr_t)q->q_ptr) == sizeof (ill) &&
11050Sstevel@tonic-gate 	    mdb_readstr(name, sizeof (name), (uintptr_t)ill.ill_name) > 0)
11060Sstevel@tonic-gate 		(void) mdb_snprintf(buf, nbytes, "if: %s", name);
11070Sstevel@tonic-gate }
11080Sstevel@tonic-gate 
11090Sstevel@tonic-gate void
11100Sstevel@tonic-gate ip_qinfo(const queue_t *q, char *buf, size_t nbytes)
11110Sstevel@tonic-gate {
11120Sstevel@tonic-gate 	size_t size = mi_osize(q);
11130Sstevel@tonic-gate 
11140Sstevel@tonic-gate 	if (size == sizeof (ill_t))
11150Sstevel@tonic-gate 		ip_ill_qinfo(q, buf, nbytes);
11160Sstevel@tonic-gate }
11170Sstevel@tonic-gate 
11180Sstevel@tonic-gate uintptr_t
11190Sstevel@tonic-gate ip_rnext(const queue_t *q)
11200Sstevel@tonic-gate {
11210Sstevel@tonic-gate 	size_t size = mi_osize(q);
11220Sstevel@tonic-gate 	ill_t ill;
11230Sstevel@tonic-gate 
11240Sstevel@tonic-gate 	if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill),
11250Sstevel@tonic-gate 	    (uintptr_t)q->q_ptr) == sizeof (ill))
11260Sstevel@tonic-gate 		return ((uintptr_t)ill.ill_rq);
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate 	return (NULL);
11290Sstevel@tonic-gate }
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate uintptr_t
11320Sstevel@tonic-gate ip_wnext(const queue_t *q)
11330Sstevel@tonic-gate {
11340Sstevel@tonic-gate 	size_t size = mi_osize(q);
11350Sstevel@tonic-gate 	ill_t ill;
11360Sstevel@tonic-gate 
11370Sstevel@tonic-gate 	if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill),
11380Sstevel@tonic-gate 	    (uintptr_t)q->q_ptr) == sizeof (ill))
11390Sstevel@tonic-gate 		return ((uintptr_t)ill.ill_wq);
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 	return (NULL);
11420Sstevel@tonic-gate }
11430Sstevel@tonic-gate 
11440Sstevel@tonic-gate /*
11450Sstevel@tonic-gate  * Print the core fields in an squeue_t.  With the "-v" argument,
11460Sstevel@tonic-gate  * provide more verbose output.
11470Sstevel@tonic-gate  */
11480Sstevel@tonic-gate static int
11490Sstevel@tonic-gate squeue(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11500Sstevel@tonic-gate {
11510Sstevel@tonic-gate 	unsigned int	i;
11520Sstevel@tonic-gate 	unsigned int	verbose = FALSE;
11530Sstevel@tonic-gate 	const int	SQUEUE_STATEDELT = (int)(sizeof (uintptr_t) + 9);
11540Sstevel@tonic-gate 	boolean_t	arm;
11550Sstevel@tonic-gate 	squeue_t	squeue;
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
11580Sstevel@tonic-gate 		if (mdb_walk_dcmd("genunix`squeue_cache", "ip`squeue",
11590Sstevel@tonic-gate 		    argc, argv) == -1) {
11600Sstevel@tonic-gate 			mdb_warn("failed to walk squeue cache");
11610Sstevel@tonic-gate 			return (DCMD_ERR);
11620Sstevel@tonic-gate 		}
11630Sstevel@tonic-gate 		return (DCMD_OK);
11640Sstevel@tonic-gate 	}
11650Sstevel@tonic-gate 
11660Sstevel@tonic-gate 	if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL)
11670Sstevel@tonic-gate 	    != argc)
11680Sstevel@tonic-gate 		return (DCMD_USAGE);
11690Sstevel@tonic-gate 
11700Sstevel@tonic-gate 	if (!DCMD_HDRSPEC(flags) && verbose)
11710Sstevel@tonic-gate 		mdb_printf("\n\n");
11720Sstevel@tonic-gate 
11730Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) || verbose) {
11740Sstevel@tonic-gate 		mdb_printf("%?s %-5s %-3s %?s %?s %?s\n",
11750Sstevel@tonic-gate 		    "ADDR", "STATE", "CPU",
11760Sstevel@tonic-gate 		    "FIRST", "LAST", "WORKER");
11770Sstevel@tonic-gate 	}
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate 	if (mdb_vread(&squeue, sizeof (squeue_t), addr) == -1) {
11800Sstevel@tonic-gate 		mdb_warn("cannot read squeue_t at %p", addr);
11810Sstevel@tonic-gate 		return (DCMD_ERR);
11820Sstevel@tonic-gate 	}
11830Sstevel@tonic-gate 
11840Sstevel@tonic-gate 	mdb_printf("%0?p %05x %3d %0?p %0?p %0?p\n",
11850Sstevel@tonic-gate 	    addr, squeue.sq_state, squeue.sq_bind,
11860Sstevel@tonic-gate 	    squeue.sq_first, squeue.sq_last, squeue.sq_worker);
11870Sstevel@tonic-gate 
11880Sstevel@tonic-gate 	if (!verbose)
11890Sstevel@tonic-gate 		return (DCMD_OK);
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate 	arm = B_TRUE;
11920Sstevel@tonic-gate 	for (i = 0; squeue_states[i].bit_name != NULL; i++) {
11930Sstevel@tonic-gate 		if (((squeue.sq_state) & (1 << i)) == 0)
11940Sstevel@tonic-gate 			continue;
11950Sstevel@tonic-gate 
11960Sstevel@tonic-gate 		if (arm) {
11970Sstevel@tonic-gate 			mdb_printf("%*s|\n", SQUEUE_STATEDELT, "");
11980Sstevel@tonic-gate 			mdb_printf("%*s+-->  ", SQUEUE_STATEDELT, "");
11990Sstevel@tonic-gate 			arm = B_FALSE;
12000Sstevel@tonic-gate 		} else
12010Sstevel@tonic-gate 			mdb_printf("%*s      ", SQUEUE_STATEDELT, "");
12020Sstevel@tonic-gate 
12030Sstevel@tonic-gate 		mdb_printf("%-12s %s\n", squeue_states[i].bit_name,
12040Sstevel@tonic-gate 		    squeue_states[i].bit_descr);
12050Sstevel@tonic-gate 	}
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate 	return (DCMD_OK);
12080Sstevel@tonic-gate }
12090Sstevel@tonic-gate 
12100Sstevel@tonic-gate static void
12110Sstevel@tonic-gate ip_squeue_help(void)
12120Sstevel@tonic-gate {
12130Sstevel@tonic-gate 	mdb_printf("Print the core information for a given NCA squeue_t.\n\n");
12140Sstevel@tonic-gate 	mdb_printf("Options:\n");
12150Sstevel@tonic-gate 	mdb_printf("\t-v\tbe verbose (more descriptive)\n");
12160Sstevel@tonic-gate }
12170Sstevel@tonic-gate 
12185023Scarlsonj /*
12195023Scarlsonj  * This is called by ::th_trace (via a callback) when walking the th_hash
12205023Scarlsonj  * list.  It calls modent to find the entries.
12215023Scarlsonj  */
12225023Scarlsonj /* ARGSUSED */
12235023Scarlsonj static int
12245023Scarlsonj modent_summary(uintptr_t addr, const void *data, void *private)
12255023Scarlsonj {
12265023Scarlsonj 	th_walk_data_t *thw = private;
12275023Scarlsonj 	const struct mod_hash_entry *mhe = data;
12285023Scarlsonj 	th_trace_t th;
12295023Scarlsonj 
12305023Scarlsonj 	if (mdb_vread(&th, sizeof (th), (uintptr_t)mhe->mhe_val) == -1) {
12315023Scarlsonj 		mdb_warn("failed to read th_trace_t %p", mhe->mhe_val);
12325023Scarlsonj 		return (WALK_ERR);
12335023Scarlsonj 	}
12345023Scarlsonj 
12355023Scarlsonj 	if (th.th_refcnt == 0 && thw->thw_non_zero_only)
12365023Scarlsonj 		return (WALK_NEXT);
12375023Scarlsonj 
12385023Scarlsonj 	if (!thw->thw_match) {
12395023Scarlsonj 		mdb_printf("%?p %?p %?p %8d %?p\n", thw->thw_ipst, mhe->mhe_key,
12405023Scarlsonj 		    mhe->mhe_val, th.th_refcnt, th.th_id);
12415023Scarlsonj 	} else if (thw->thw_matchkey == (uintptr_t)mhe->mhe_key) {
12425023Scarlsonj 		int i, j, k;
12435023Scarlsonj 		tr_buf_t *tr;
12445023Scarlsonj 
12455023Scarlsonj 		mdb_printf("Object %p in IP stack %p:\n", mhe->mhe_key,
12465023Scarlsonj 		    thw->thw_ipst);
12475023Scarlsonj 		i = th.th_trace_lastref;
12485023Scarlsonj 		mdb_printf("\tThread %p refcnt %d:\n", th.th_id,
12495023Scarlsonj 		    th.th_refcnt);
12505023Scarlsonj 		for (j = TR_BUF_MAX; j > 0; j--) {
12515023Scarlsonj 			tr = th.th_trbuf + i;
12525023Scarlsonj 			if (tr->tr_depth == 0 || tr->tr_depth > TR_STACK_DEPTH)
12535023Scarlsonj 				break;
12545023Scarlsonj 			mdb_printf("\t  T%+ld:\n", tr->tr_time -
12555023Scarlsonj 			    thw->thw_lbolt);
12565023Scarlsonj 			for (k = 0; k < tr->tr_depth; k++)
12575023Scarlsonj 				mdb_printf("\t\t%a\n", tr->tr_stack[k]);
12585023Scarlsonj 			if (--i < 0)
12595023Scarlsonj 				i = TR_BUF_MAX - 1;
12605023Scarlsonj 		}
12615023Scarlsonj 	}
12625023Scarlsonj 	return (WALK_NEXT);
12635023Scarlsonj }
12645023Scarlsonj 
12655023Scarlsonj /*
12665023Scarlsonj  * This is called by ::th_trace (via a callback) when walking the th_hash
12675023Scarlsonj  * list.  It calls modent to find the entries.
12685023Scarlsonj  */
12695023Scarlsonj /* ARGSUSED */
12705023Scarlsonj static int
12715023Scarlsonj th_hash_summary(uintptr_t addr, const void *data, void *private)
12725023Scarlsonj {
12735023Scarlsonj 	const th_hash_t *thh = data;
12745023Scarlsonj 	th_walk_data_t *thw = private;
12755023Scarlsonj 
12765023Scarlsonj 	thw->thw_ipst = (uintptr_t)thh->thh_ipst;
12775023Scarlsonj 	return (mdb_pwalk("modent", modent_summary, private,
12785023Scarlsonj 	    (uintptr_t)thh->thh_hash));
12795023Scarlsonj }
12805023Scarlsonj 
12815023Scarlsonj /*
12825023Scarlsonj  * Print or summarize the th_trace_t structures.
12835023Scarlsonj  */
12845023Scarlsonj static int
12855023Scarlsonj th_trace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
12865023Scarlsonj {
12875023Scarlsonj 	th_walk_data_t thw;
12885023Scarlsonj 
12895023Scarlsonj 	(void) memset(&thw, 0, sizeof (thw));
12905023Scarlsonj 
12915023Scarlsonj 	if (mdb_getopts(argc, argv,
12925023Scarlsonj 	    'n', MDB_OPT_SETBITS, TRUE, &thw.thw_non_zero_only,
12935023Scarlsonj 	    NULL) != argc)
12945023Scarlsonj 		return (DCMD_USAGE);
12955023Scarlsonj 
12965023Scarlsonj 	if (!(flags & DCMD_ADDRSPEC)) {
12975023Scarlsonj 		/*
12985023Scarlsonj 		 * No address specified.  Walk all of the th_hash_t in the
12995023Scarlsonj 		 * system, and summarize the th_trace_t entries in each.
13005023Scarlsonj 		 */
13015023Scarlsonj 		mdb_printf("%?s %?s %?s %8s %?s\n",
13025023Scarlsonj 		    "IPSTACK", "OBJECT", "TRACE", "REFCNT", "THREAD");
13035023Scarlsonj 		thw.thw_match = B_FALSE;
13045023Scarlsonj 	} else {
13055023Scarlsonj 		thw.thw_match = B_TRUE;
13065023Scarlsonj 		thw.thw_matchkey = addr;
13075023Scarlsonj 		if (mdb_readvar(&thw.thw_lbolt,
13085023Scarlsonj 		    mdb_prop_postmortem ? "panic_lbolt" : "lbolt") == -1) {
13095023Scarlsonj 			mdb_warn("failed to read lbolt");
13105023Scarlsonj 			return (DCMD_ERR);
13115023Scarlsonj 		}
13125023Scarlsonj 	}
13135023Scarlsonj 	if (mdb_pwalk("th_hash", th_hash_summary, &thw, NULL) == -1) {
13145023Scarlsonj 		mdb_warn("can't walk th_hash entries");
13155023Scarlsonj 		return (DCMD_ERR);
13165023Scarlsonj 	}
13175023Scarlsonj 	return (DCMD_OK);
13185023Scarlsonj }
13195023Scarlsonj 
13205023Scarlsonj static void
13215023Scarlsonj th_trace_help(void)
13225023Scarlsonj {
13235023Scarlsonj 	mdb_printf("If given an address of an ill_t, ipif_t, ire_t, or nce_t, "
13245023Scarlsonj 	    "print the\n"
13255023Scarlsonj 	    "corresponding th_trace_t structure in detail.  Otherwise, if no "
13265023Scarlsonj 	    "address is\n"
13275023Scarlsonj 	    "given, then summarize all th_trace_t structures.\n\n");
13285023Scarlsonj 	mdb_printf("Options:\n"
13295023Scarlsonj 	    "\t-n\tdisplay only entries with non-zero th_refcnt\n");
13305023Scarlsonj }
13315023Scarlsonj 
13320Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = {
1333*9089SVasumathi.Sundaram@Sun.COM 	{ "conn_status", ":",
1334*9089SVasumathi.Sundaram@Sun.COM 	    "display connection structures from ipcl hash tables",
1335*9089SVasumathi.Sundaram@Sun.COM 	    conn_status, conn_status_help },
1336*9089SVasumathi.Sundaram@Sun.COM 	{ "srcid_status", ":",
1337*9089SVasumathi.Sundaram@Sun.COM 	    "display connection structures from ipcl hash tables",
1338*9089SVasumathi.Sundaram@Sun.COM 	    srcid_status },
1339*9089SVasumathi.Sundaram@Sun.COM 	{ "ill", "?[-v] [-P v4 | v6]", "display ill_t structures",
1340*9089SVasumathi.Sundaram@Sun.COM 	    ill, ill_help },
13410Sstevel@tonic-gate 	{ "illif", "?[-P v4 | v6]",
13420Sstevel@tonic-gate 	    "display or filter IP Lower Level InterFace structures", illif,
13430Sstevel@tonic-gate 	    illif_help },
13440Sstevel@tonic-gate 	{ "iphdr", ":[-vf]", "display an IPv4 header", iphdr },
13450Sstevel@tonic-gate 	{ "ip6hdr", ":[-vf]", "display an IPv6 header", ip6hdr },
1346*9089SVasumathi.Sundaram@Sun.COM 	{ "ipif", "?[-v] [-P v4 | v6]", "display ipif structures",
1347*9089SVasumathi.Sundaram@Sun.COM 	    ipif, ipif_help },
13485940Ssowmini 	{ "ire", "?[-v] [-P v4|v6]",
13495940Ssowmini 	    "display Internet Route Entry structures", ire },
13505940Ssowmini 	{ "nce", "?[-P v4 | v6]", "display Neighbor Cache Entry structures",
13515940Ssowmini 	    nce },
13520Sstevel@tonic-gate 	{ "squeue", ":[-v]", "print core squeue_t info", squeue,
13530Sstevel@tonic-gate 	    ip_squeue_help },
13540Sstevel@tonic-gate 	{ "tcphdr", ":", "display a TCP header", tcphdr },
13550Sstevel@tonic-gate 	{ "udphdr", ":", "display an UDP header", udphdr },
13560Sstevel@tonic-gate 	{ "sctphdr", ":", "display an SCTP header", sctphdr },
13575023Scarlsonj 	{ "th_trace", "?[-n]", "display th_trace_t structures", th_trace,
13585023Scarlsonj 	    th_trace_help },
13590Sstevel@tonic-gate 	{ NULL }
13600Sstevel@tonic-gate };
13610Sstevel@tonic-gate 
13620Sstevel@tonic-gate static const mdb_walker_t walkers[] = {
1363*9089SVasumathi.Sundaram@Sun.COM 	{ "conn_status", "walk list of conn_t structures",
1364*9089SVasumathi.Sundaram@Sun.COM 		ip_stacks_common_walk_init, conn_status_walk_step, NULL },
13653448Sdh155122 	{ "illif", "walk list of ill interface types for all stacks",
13665940Ssowmini 		ip_stacks_common_walk_init, illif_walk_step, NULL },
13673448Sdh155122 	{ "illif_stack", "walk list of ill interface types",
13683448Sdh155122 		illif_stack_walk_init, illif_stack_walk_step,
13693448Sdh155122 		illif_stack_walk_fini },
1370*9089SVasumathi.Sundaram@Sun.COM 	{ "ill", "walk list of nce structures for all stacks",
1371*9089SVasumathi.Sundaram@Sun.COM 		ill_walk_init, ill_walk_step, NULL },
1372*9089SVasumathi.Sundaram@Sun.COM 	{ "ipif", "walk list of ipif structures for all stacks",
1373*9089SVasumathi.Sundaram@Sun.COM 		ipif_walk_init, ipif_walk_step, NULL },
1374*9089SVasumathi.Sundaram@Sun.COM 	{ "ipif_list", "walk the linked list of ipif structures "
1375*9089SVasumathi.Sundaram@Sun.COM 		"for a given ill",
1376*9089SVasumathi.Sundaram@Sun.COM 		ip_list_walk_init, ip_list_walk_step,
1377*9089SVasumathi.Sundaram@Sun.COM 		ip_list_walk_fini, &ipif_walk_arg },
1378*9089SVasumathi.Sundaram@Sun.COM 	{ "srcid", "walk list of srcid_map structures for all stacks",
1379*9089SVasumathi.Sundaram@Sun.COM 		ip_stacks_common_walk_init, srcid_walk_step, NULL },
1380*9089SVasumathi.Sundaram@Sun.COM 	{ "srcid_list", "walk list of srcid_map structures for a stack",
1381*9089SVasumathi.Sundaram@Sun.COM 		ip_list_walk_init, ip_list_walk_step, ip_list_walk_fini,
1382*9089SVasumathi.Sundaram@Sun.COM 		&srcid_walk_arg },
13830Sstevel@tonic-gate 	{ "ire", "walk active ire_t structures",
13840Sstevel@tonic-gate 		ire_walk_init, ire_walk_step, NULL },
13853448Sdh155122 	{ "ire_ctable", "walk ire_t structures in the ctable",
13865940Ssowmini 		ip_stacks_common_walk_init, ire_ctable_walk_step, NULL },
13873448Sdh155122 	{ "ire_next", "walk ire_t structures in the ctable",
13883448Sdh155122 		ire_next_walk_init, ire_next_walk_step, NULL },
13893448Sdh155122 	{ "ip_stacks", "walk all the ip_stack_t",
13903448Sdh155122 		ip_stacks_walk_init, ip_stacks_walk_step, NULL },
13915023Scarlsonj 	{ "th_hash", "walk all the th_hash_t entries",
13925023Scarlsonj 		th_hash_walk_init, th_hash_walk_step, NULL },
13935940Ssowmini 	{ "nce", "walk list of nce structures for all stacks",
13945940Ssowmini 		ip_stacks_common_walk_init, nce_walk_step, NULL },
13955940Ssowmini 	{ "nce_stack", "walk list of nce structures",
13965940Ssowmini 		nce_stack_walk_init, nce_stack_walk_step,
13975940Ssowmini 		nce_stack_walk_fini},
1398*9089SVasumathi.Sundaram@Sun.COM 	{ "udp_hash", "walk list of conn_t structures in ips_ipcl_udp_fanout",
1399*9089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_init, ipcl_hash_walk_step,
1400*9089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_fini, &udp_hash_arg},
1401*9089SVasumathi.Sundaram@Sun.COM 	{ "conn_hash", "walk list of conn_t structures in ips_ipcl_conn_fanout",
1402*9089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_init, ipcl_hash_walk_step,
1403*9089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_fini, &conn_hash_arg},
1404*9089SVasumathi.Sundaram@Sun.COM 	{ "bind_hash", "walk list of conn_t structures in ips_ipcl_bind_fanout",
1405*9089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_init, ipcl_hash_walk_step,
1406*9089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_fini, &bind_hash_arg},
1407*9089SVasumathi.Sundaram@Sun.COM 	{ "proto_hash", "walk list of conn_t structures in "
1408*9089SVasumathi.Sundaram@Sun.COM 	    "ips_ipcl_proto_fanout",
1409*9089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_init, ipcl_hash_walk_step,
1410*9089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_fini, &proto_hash_arg},
1411*9089SVasumathi.Sundaram@Sun.COM 	{ "proto_v6_hash", "walk list of conn_t structures in "
1412*9089SVasumathi.Sundaram@Sun.COM 	    "ips_ipcl_proto_fanout_v6",
1413*9089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_init, ipcl_hash_walk_step,
1414*9089SVasumathi.Sundaram@Sun.COM 		ipcl_hash_walk_fini, &proto_v6_hash_arg},
14150Sstevel@tonic-gate 	{ NULL }
14160Sstevel@tonic-gate };
14170Sstevel@tonic-gate 
14180Sstevel@tonic-gate static const mdb_qops_t ip_qops = { ip_qinfo, ip_rnext, ip_wnext };
14190Sstevel@tonic-gate static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
14200Sstevel@tonic-gate 
14210Sstevel@tonic-gate const mdb_modinfo_t *
14220Sstevel@tonic-gate _mdb_init(void)
14230Sstevel@tonic-gate {
14240Sstevel@tonic-gate 	GElf_Sym sym;
14250Sstevel@tonic-gate 
14262546Scarlsonj 	if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0)
14270Sstevel@tonic-gate 		mdb_qops_install(&ip_qops, (uintptr_t)sym.st_value);
14280Sstevel@tonic-gate 
14290Sstevel@tonic-gate 	return (&modinfo);
14300Sstevel@tonic-gate }
14310Sstevel@tonic-gate 
14320Sstevel@tonic-gate void
14330Sstevel@tonic-gate _mdb_fini(void)
14340Sstevel@tonic-gate {
14350Sstevel@tonic-gate 	GElf_Sym sym;
14360Sstevel@tonic-gate 
14372546Scarlsonj 	if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0)
14380Sstevel@tonic-gate 		mdb_qops_remove(&ip_qops, (uintptr_t)sym.st_value);
14390Sstevel@tonic-gate }
14405940Ssowmini 
14415940Ssowmini static char *
14425940Ssowmini nce_state(int nce_state)
14435940Ssowmini {
14445940Ssowmini 	switch (nce_state) {
14455940Ssowmini 	case ND_UNCHANGED:
14465940Ssowmini 		return ("unchanged");
14475940Ssowmini 	case ND_INCOMPLETE:
14485940Ssowmini 		return ("incomplete");
14495940Ssowmini 	case ND_REACHABLE:
14505940Ssowmini 		return ("reachable");
14515940Ssowmini 	case ND_STALE:
14525940Ssowmini 		return ("stale");
14535940Ssowmini 	case ND_DELAY:
14545940Ssowmini 		return ("delay");
14555940Ssowmini 	case ND_PROBE:
14565940Ssowmini 		return ("probe");
14575940Ssowmini 	case ND_UNREACHABLE:
14585940Ssowmini 		return ("unreach");
14595940Ssowmini 	case ND_INITIAL:
14605940Ssowmini 		return ("initial");
14615940Ssowmini 	default:
14625940Ssowmini 		return ("??");
14635940Ssowmini 	}
14645940Ssowmini }
14655940Ssowmini 
14665940Ssowmini static char *
14675940Ssowmini nce_l2_addr(const nce_t *nce, const ill_t *ill)
14685940Ssowmini {
14695940Ssowmini 	uchar_t *h;
14705940Ssowmini 	static char addr_buf[L2MAXADDRSTRLEN];
14715940Ssowmini 	mblk_t mp;
14725940Ssowmini 	size_t mblen;
14735940Ssowmini 
14745940Ssowmini 	if (ill->ill_flags & ILLF_XRESOLV) {
14755940Ssowmini 		return ("XRESOLV");
14765940Ssowmini 	}
14775940Ssowmini 
14785940Ssowmini 	if (nce->nce_res_mp == NULL) {
14795940Ssowmini 		return ("None");
14805940Ssowmini 	}
14815940Ssowmini 
14825940Ssowmini 	if (ill->ill_net_type == IRE_IF_RESOLVER) {
14835940Ssowmini 
14845940Ssowmini 		if (mdb_vread(&mp, sizeof (mblk_t),
14855940Ssowmini 		    (uintptr_t)nce->nce_res_mp) == -1) {
14865940Ssowmini 			mdb_warn("failed to read nce_res_mp at %p",
14875940Ssowmini 			    nce->nce_res_mp);
14885940Ssowmini 		}
14895940Ssowmini 
14905940Ssowmini 		if (ill->ill_nd_lla_len == 0)
14915940Ssowmini 			return ("None");
14925940Ssowmini 		mblen = mp.b_wptr - mp.b_rptr;
14935940Ssowmini 		if (mblen > (sizeof (dl_unitdata_req_t) + MAX_SAP_LEN) ||
14945940Ssowmini 		    ill->ill_nd_lla_len > MAX_SAP_LEN ||
14955940Ssowmini 		    NCE_LL_ADDR_OFFSET(ill) + ill->ill_nd_lla_len > mblen) {
14965940Ssowmini 			return ("Truncated");
14975940Ssowmini 		}
14985940Ssowmini 		h = mdb_zalloc(mblen, UM_SLEEP);
14995940Ssowmini 		if (mdb_vread(h, mblen, (uintptr_t)(mp.b_rptr)) == -1) {
15005940Ssowmini 			mdb_warn("failed to read hwaddr at %p",
15015940Ssowmini 			    mp.b_rptr + NCE_LL_ADDR_OFFSET(ill));
15025940Ssowmini 			return ("Unknown");
15035940Ssowmini 		}
15045940Ssowmini 		mdb_mac_addr(h + NCE_LL_ADDR_OFFSET(ill), ill->ill_nd_lla_len,
15055940Ssowmini 		    addr_buf, sizeof (addr_buf));
15065940Ssowmini 	} else {
15075940Ssowmini 		return ("None");
15085940Ssowmini 	}
15095940Ssowmini 	mdb_free(h, mblen);
15105940Ssowmini 	return (addr_buf);
15115940Ssowmini }
15125940Ssowmini 
15135940Ssowmini static void
15145940Ssowmini nce_header(uint_t flags)
15155940Ssowmini {
15165940Ssowmini 	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
15175940Ssowmini 
15185940Ssowmini 		mdb_printf("%<u>%?s %-20s %-10s %-8s %-5s %s%</u>\n",
15195940Ssowmini 		    "ADDR", "HW_ADDR", "STATE", "FLAGS", "ILL", "IP ADDR");
15205940Ssowmini 	}
15215940Ssowmini }
15225940Ssowmini 
15235940Ssowmini int
15245940Ssowmini nce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
15255940Ssowmini {
15265940Ssowmini 	nce_t nce;
15275940Ssowmini 	nce_cbdata_t id;
15285940Ssowmini 	int ipversion = 0;
15295940Ssowmini 	const char *opt_P = NULL;
15305940Ssowmini 
15315940Ssowmini 	if (mdb_getopts(argc, argv,
15325940Ssowmini 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
15335940Ssowmini 		return (DCMD_USAGE);
15345940Ssowmini 
15355940Ssowmini 	if (opt_P != NULL) {
15365940Ssowmini 		if (strcmp("v4", opt_P) == 0) {
15375940Ssowmini 			ipversion = IPV4_VERSION;
15385940Ssowmini 		} else if (strcmp("v6", opt_P) == 0) {
15395940Ssowmini 			ipversion = IPV6_VERSION;
15405940Ssowmini 		} else {
15415940Ssowmini 			mdb_warn("invalid protocol '%s'\n", opt_P);
15425940Ssowmini 			return (DCMD_USAGE);
15435940Ssowmini 		}
15445940Ssowmini 	}
15455940Ssowmini 
15465940Ssowmini 	if (flags & DCMD_ADDRSPEC) {
15475940Ssowmini 
15485940Ssowmini 		if (mdb_vread(&nce, sizeof (nce_t), addr) == -1) {
15495940Ssowmini 			mdb_warn("failed to read nce at %p\n", addr);
15505940Ssowmini 			return (DCMD_ERR);
15515940Ssowmini 		}
15525940Ssowmini 		if (ipversion != 0 && nce.nce_ipversion != ipversion) {
15535940Ssowmini 			mdb_printf("IP Version mismatch\n");
15545940Ssowmini 			return (DCMD_ERR);
15555940Ssowmini 		}
15565940Ssowmini 		nce_header(flags);
15575940Ssowmini 		return (nce_format(addr, &nce, ipversion));
15585940Ssowmini 
15595940Ssowmini 	} else {
15605940Ssowmini 		id.nce_addr = addr;
15615940Ssowmini 		id.nce_ipversion = ipversion;
15625940Ssowmini 		nce_header(flags);
15635940Ssowmini 		if (mdb_walk("nce", (mdb_walk_cb_t)nce_cb, &id) == -1) {
15645940Ssowmini 			mdb_warn("failed to walk nce table\n");
15655940Ssowmini 			return (DCMD_ERR);
15665940Ssowmini 		}
15675940Ssowmini 	}
15685940Ssowmini 	return (DCMD_OK);
15695940Ssowmini }
15705940Ssowmini 
15715940Ssowmini static int
15725940Ssowmini nce_format(uintptr_t addr, const nce_t *nce, int ipversion)
15735940Ssowmini {
15745940Ssowmini 	static const mdb_bitmask_t nce_flags[] = {
15755940Ssowmini 		{ "P",	NCE_F_PERMANENT,	NCE_F_PERMANENT },
15765940Ssowmini 		{ "R",	NCE_F_ISROUTER,		NCE_F_ISROUTER	},
15775940Ssowmini 		{ "N",	NCE_F_NONUD,		NCE_F_NONUD	},
15785940Ssowmini 		{ "A",	NCE_F_ANYCAST,		NCE_F_ANYCAST	},
15795940Ssowmini 		{ "C",	NCE_F_CONDEMNED,	NCE_F_CONDEMNED	},
15805940Ssowmini 		{ "U",	NCE_F_UNSOL_ADV,	NCE_F_UNSOL_ADV },
15815940Ssowmini 		{ "B",	NCE_F_BCAST,		NCE_F_BCAST	},
15825940Ssowmini 		{ NULL,	0,			0		}
15835940Ssowmini 	};
15845940Ssowmini #define	NCE_MAX_FLAGS	(sizeof (nce_flags) / sizeof (mdb_bitmask_t))
15855940Ssowmini 	struct in_addr nceaddr;
15865940Ssowmini 	ill_t ill;
15875940Ssowmini 	char ill_name[LIFNAMSIZ];
15885940Ssowmini 	char flagsbuf[NCE_MAX_FLAGS];
15895940Ssowmini 
15905940Ssowmini 	if (mdb_vread(&ill, sizeof (ill), (uintptr_t)nce->nce_ill) == -1) {
15915940Ssowmini 		mdb_warn("failed to read nce_ill at %p",
15925940Ssowmini 		    nce->nce_ill);
15935940Ssowmini 		return (DCMD_ERR);
15945940Ssowmini 	}
15955940Ssowmini 
15965940Ssowmini 	(void) mdb_readstr(ill_name, MIN(LIFNAMSIZ, ill.ill_name_length),
15975940Ssowmini 	    (uintptr_t)ill.ill_name);
15985940Ssowmini 
15995940Ssowmini 	mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%hb",
16005940Ssowmini 	    nce->nce_flags, nce_flags);
16015940Ssowmini 
16025940Ssowmini 	if (ipversion != 0 && nce->nce_ipversion != ipversion)
16035940Ssowmini 		return (DCMD_OK);
16045940Ssowmini 
16055940Ssowmini 	if (nce->nce_ipversion == IPV4_VERSION) {
16065940Ssowmini 		IN6_V4MAPPED_TO_INADDR(&nce->nce_addr, &nceaddr);
16075940Ssowmini 		mdb_printf("%?p %-20s %-10s "
16085940Ssowmini 		    "%-8s "
16095940Ssowmini 		    "%-5s %I\n",
16105940Ssowmini 		    addr, nce_l2_addr(nce, &ill),
16115940Ssowmini 		    nce_state(nce->nce_state),
16125940Ssowmini 		    flagsbuf,
16135940Ssowmini 		    ill_name, nceaddr.s_addr);
16145940Ssowmini 	} else {
16155940Ssowmini 		mdb_printf("%?p %-20s %-10s %-8s %-5s %N\n",
16165940Ssowmini 		    addr,  nce_l2_addr(nce, &ill),
16175940Ssowmini 		    nce_state(nce->nce_state),
16185940Ssowmini 		    flagsbuf,
16195940Ssowmini 		    ill_name, &nce->nce_addr);
16205940Ssowmini 	}
16215940Ssowmini 
16225940Ssowmini 	return (DCMD_OK);
16235940Ssowmini }
16245940Ssowmini 
16255940Ssowmini static uintptr_t
16265940Ssowmini nce_get_next_hash_tbl(uintptr_t start, int *index, struct ndp_g_s ndp)
16275940Ssowmini {
16285940Ssowmini 	uintptr_t addr = start;
16295940Ssowmini 	int i = *index;
16305940Ssowmini 
16315940Ssowmini 	while (addr == NULL) {
16325940Ssowmini 
16335940Ssowmini 		if (++i >= NCE_TABLE_SIZE)
16345940Ssowmini 			break;
16355940Ssowmini 		addr = (uintptr_t)ndp.nce_hash_tbl[i];
16365940Ssowmini 	}
16375940Ssowmini 	*index = i;
16385940Ssowmini 	return (addr);
16395940Ssowmini }
16405940Ssowmini 
16415940Ssowmini static int
16425940Ssowmini nce_walk_step(mdb_walk_state_t *wsp)
16435940Ssowmini {
16445940Ssowmini 	uintptr_t kaddr4, kaddr6;
16455940Ssowmini 
16465940Ssowmini 	kaddr4 = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ndp4);
16475940Ssowmini 	kaddr6 = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ndp6);
16485940Ssowmini 
16495940Ssowmini 	if (mdb_vread(&kaddr4, sizeof (kaddr4), kaddr4) == -1) {
16505940Ssowmini 		mdb_warn("can't read ips_ip_cache_table at %p", kaddr4);
16515940Ssowmini 		return (WALK_ERR);
16525940Ssowmini 	}
16535940Ssowmini 	if (mdb_vread(&kaddr6, sizeof (kaddr6), kaddr6) == -1) {
16545940Ssowmini 		mdb_warn("can't read ips_ip_cache_table at %p", kaddr6);
16555940Ssowmini 		return (WALK_ERR);
16565940Ssowmini 	}
16575940Ssowmini 	if (mdb_pwalk("nce_stack", wsp->walk_callback, wsp->walk_cbdata,
16585940Ssowmini 	    kaddr4) == -1) {
16595940Ssowmini 		mdb_warn("couldn't walk 'nce_stack' for ips_ndp4 %p",
16605940Ssowmini 		    kaddr4);
16615940Ssowmini 		return (WALK_ERR);
16625940Ssowmini 	}
16635940Ssowmini 	if (mdb_pwalk("nce_stack", wsp->walk_callback,
16645940Ssowmini 	    wsp->walk_cbdata, kaddr6) == -1) {
16655940Ssowmini 		mdb_warn("couldn't walk 'nce_stack' for ips_ndp6 %p",
16665940Ssowmini 		    kaddr6);
16675940Ssowmini 		return (WALK_ERR);
16685940Ssowmini 	}
16695940Ssowmini 	return (WALK_NEXT);
16705940Ssowmini }
16715940Ssowmini 
1672*9089SVasumathi.Sundaram@Sun.COM static uintptr_t
1673*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_get_next_connf_tbl(ipcl_hash_walk_data_t *iw)
1674*9089SVasumathi.Sundaram@Sun.COM {
1675*9089SVasumathi.Sundaram@Sun.COM 	struct connf_s connf;
1676*9089SVasumathi.Sundaram@Sun.COM 	uintptr_t addr = NULL, next;
1677*9089SVasumathi.Sundaram@Sun.COM 	int index = iw->connf_tbl_index;
1678*9089SVasumathi.Sundaram@Sun.COM 
1679*9089SVasumathi.Sundaram@Sun.COM 	do {
1680*9089SVasumathi.Sundaram@Sun.COM 		next = iw->hash_tbl + index * sizeof (struct connf_s);
1681*9089SVasumathi.Sundaram@Sun.COM 		if (++index >= iw->hash_tbl_size) {
1682*9089SVasumathi.Sundaram@Sun.COM 			addr = NULL;
1683*9089SVasumathi.Sundaram@Sun.COM 			break;
1684*9089SVasumathi.Sundaram@Sun.COM 		}
1685*9089SVasumathi.Sundaram@Sun.COM 		if (mdb_vread(&connf, sizeof (struct connf_s), next) == -1)  {
1686*9089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to read conn_t at %p", next);
1687*9089SVasumathi.Sundaram@Sun.COM 			return (NULL);
1688*9089SVasumathi.Sundaram@Sun.COM 		}
1689*9089SVasumathi.Sundaram@Sun.COM 		addr = (uintptr_t)connf.connf_head;
1690*9089SVasumathi.Sundaram@Sun.COM 	} while (addr == NULL);
1691*9089SVasumathi.Sundaram@Sun.COM 	iw->connf_tbl_index = index;
1692*9089SVasumathi.Sundaram@Sun.COM 	return (addr);
1693*9089SVasumathi.Sundaram@Sun.COM }
1694*9089SVasumathi.Sundaram@Sun.COM 
1695*9089SVasumathi.Sundaram@Sun.COM static int
1696*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_init(mdb_walk_state_t *wsp)
1697*9089SVasumathi.Sundaram@Sun.COM {
1698*9089SVasumathi.Sundaram@Sun.COM 	const hash_walk_arg_t *arg = wsp->walk_arg;
1699*9089SVasumathi.Sundaram@Sun.COM 	ipcl_hash_walk_data_t *iw;
1700*9089SVasumathi.Sundaram@Sun.COM 	uintptr_t tbladdr;
1701*9089SVasumathi.Sundaram@Sun.COM 	uintptr_t sizeaddr;
1702*9089SVasumathi.Sundaram@Sun.COM 
1703*9089SVasumathi.Sundaram@Sun.COM 	iw = mdb_alloc(sizeof (ipcl_hash_walk_data_t), UM_SLEEP);
1704*9089SVasumathi.Sundaram@Sun.COM 	iw->conn = mdb_alloc(sizeof (conn_t), UM_SLEEP);
1705*9089SVasumathi.Sundaram@Sun.COM 	tbladdr = wsp->walk_addr + arg->tbl_off;
1706*9089SVasumathi.Sundaram@Sun.COM 	sizeaddr = wsp->walk_addr + arg->size_off;
1707*9089SVasumathi.Sundaram@Sun.COM 
1708*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&iw->hash_tbl, sizeof (uintptr_t), tbladdr) == -1) {
1709*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't read fanout table addr at %p", tbladdr);
1710*9089SVasumathi.Sundaram@Sun.COM 		mdb_free(iw->conn, sizeof (conn_t));
1711*9089SVasumathi.Sundaram@Sun.COM 		mdb_free(iw, sizeof (ipcl_hash_walk_data_t));
1712*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
1713*9089SVasumathi.Sundaram@Sun.COM 	}
1714*9089SVasumathi.Sundaram@Sun.COM 	if (arg->tbl_off == OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout) ||
1715*9089SVasumathi.Sundaram@Sun.COM 	    arg->tbl_off == OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v6)) {
1716*9089SVasumathi.Sundaram@Sun.COM 		iw->hash_tbl_size = IPPROTO_MAX;
1717*9089SVasumathi.Sundaram@Sun.COM 	} else {
1718*9089SVasumathi.Sundaram@Sun.COM 		if (mdb_vread(&iw->hash_tbl_size, sizeof (int),
1719*9089SVasumathi.Sundaram@Sun.COM 		    sizeaddr) == -1) {
1720*9089SVasumathi.Sundaram@Sun.COM 			mdb_warn("can't read fanout table size addr at %p",
1721*9089SVasumathi.Sundaram@Sun.COM 			    sizeaddr);
1722*9089SVasumathi.Sundaram@Sun.COM 			mdb_free(iw->conn, sizeof (conn_t));
1723*9089SVasumathi.Sundaram@Sun.COM 			mdb_free(iw, sizeof (ipcl_hash_walk_data_t));
1724*9089SVasumathi.Sundaram@Sun.COM 			return (WALK_ERR);
1725*9089SVasumathi.Sundaram@Sun.COM 		}
1726*9089SVasumathi.Sundaram@Sun.COM 	}
1727*9089SVasumathi.Sundaram@Sun.COM 	iw->connf_tbl_index = 0;
1728*9089SVasumathi.Sundaram@Sun.COM 	wsp->walk_addr = ipcl_hash_get_next_connf_tbl(iw);
1729*9089SVasumathi.Sundaram@Sun.COM 	wsp->walk_data = iw;
1730*9089SVasumathi.Sundaram@Sun.COM 
1731*9089SVasumathi.Sundaram@Sun.COM 	if (wsp->walk_addr != NULL)
1732*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
1733*9089SVasumathi.Sundaram@Sun.COM 	else
1734*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_DONE);
1735*9089SVasumathi.Sundaram@Sun.COM }
1736*9089SVasumathi.Sundaram@Sun.COM 
1737*9089SVasumathi.Sundaram@Sun.COM static int
1738*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_step(mdb_walk_state_t *wsp)
1739*9089SVasumathi.Sundaram@Sun.COM {
1740*9089SVasumathi.Sundaram@Sun.COM 	uintptr_t addr = wsp->walk_addr;
1741*9089SVasumathi.Sundaram@Sun.COM 	ipcl_hash_walk_data_t *iw = wsp->walk_data;
1742*9089SVasumathi.Sundaram@Sun.COM 	conn_t *conn = iw->conn;
1743*9089SVasumathi.Sundaram@Sun.COM 	int ret = WALK_DONE;
1744*9089SVasumathi.Sundaram@Sun.COM 
1745*9089SVasumathi.Sundaram@Sun.COM 	while (addr != NULL) {
1746*9089SVasumathi.Sundaram@Sun.COM 		if (mdb_vread(conn, sizeof (conn_t), addr) == -1) {
1747*9089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to read conn_t at %p", addr);
1748*9089SVasumathi.Sundaram@Sun.COM 			return (WALK_ERR);
1749*9089SVasumathi.Sundaram@Sun.COM 		}
1750*9089SVasumathi.Sundaram@Sun.COM 		ret = wsp->walk_callback(addr, iw, wsp->walk_cbdata);
1751*9089SVasumathi.Sundaram@Sun.COM 		if (ret != WALK_NEXT)
1752*9089SVasumathi.Sundaram@Sun.COM 			break;
1753*9089SVasumathi.Sundaram@Sun.COM 		addr = (uintptr_t)conn->conn_next;
1754*9089SVasumathi.Sundaram@Sun.COM 	}
1755*9089SVasumathi.Sundaram@Sun.COM 	if (ret == WALK_NEXT) {
1756*9089SVasumathi.Sundaram@Sun.COM 		wsp->walk_addr = ipcl_hash_get_next_connf_tbl(iw);
1757*9089SVasumathi.Sundaram@Sun.COM 
1758*9089SVasumathi.Sundaram@Sun.COM 		if (wsp->walk_addr != NULL)
1759*9089SVasumathi.Sundaram@Sun.COM 			return (WALK_NEXT);
1760*9089SVasumathi.Sundaram@Sun.COM 		else
1761*9089SVasumathi.Sundaram@Sun.COM 			return (WALK_DONE);
1762*9089SVasumathi.Sundaram@Sun.COM 	}
1763*9089SVasumathi.Sundaram@Sun.COM 
1764*9089SVasumathi.Sundaram@Sun.COM 	return (ret);
1765*9089SVasumathi.Sundaram@Sun.COM }
1766*9089SVasumathi.Sundaram@Sun.COM 
1767*9089SVasumathi.Sundaram@Sun.COM static void
1768*9089SVasumathi.Sundaram@Sun.COM ipcl_hash_walk_fini(mdb_walk_state_t *wsp)
1769*9089SVasumathi.Sundaram@Sun.COM {
1770*9089SVasumathi.Sundaram@Sun.COM 	ipcl_hash_walk_data_t *iw = wsp->walk_data;
1771*9089SVasumathi.Sundaram@Sun.COM 
1772*9089SVasumathi.Sundaram@Sun.COM 	mdb_free(iw->conn, sizeof (conn_t));
1773*9089SVasumathi.Sundaram@Sun.COM 	mdb_free(iw, sizeof (ipcl_hash_walk_data_t));
1774*9089SVasumathi.Sundaram@Sun.COM }
1775*9089SVasumathi.Sundaram@Sun.COM 
17765940Ssowmini /*
17775940Ssowmini  * Called with walk_addr being the address of ips_ndp{4,6}
17785940Ssowmini  */
17795940Ssowmini static int
17805940Ssowmini nce_stack_walk_init(mdb_walk_state_t *wsp)
17815940Ssowmini {
17825940Ssowmini 	nce_walk_data_t *nw;
17835940Ssowmini 
17845940Ssowmini 	if (wsp->walk_addr == NULL) {
17855940Ssowmini 		mdb_warn("nce_stack requires ndp_g_s address\n");
17865940Ssowmini 		return (WALK_ERR);
17875940Ssowmini 	}
17885940Ssowmini 
17895940Ssowmini 	nw = mdb_alloc(sizeof (nce_walk_data_t), UM_SLEEP);
17905940Ssowmini 
17915940Ssowmini 	if (mdb_vread(&nw->nce_ip_ndp, sizeof (struct ndp_g_s),
17925940Ssowmini 	    wsp->walk_addr) == -1) {
17935940Ssowmini 		mdb_warn("failed to read 'ip_ndp' at %p",
17945940Ssowmini 		    wsp->walk_addr);
17955940Ssowmini 		mdb_free(nw, sizeof (nce_walk_data_t));
17965940Ssowmini 		return (WALK_ERR);
17975940Ssowmini 	}
17985940Ssowmini 
17995940Ssowmini 	nw->nce_hash_tbl_index = 0;
18005940Ssowmini 	wsp->walk_addr = nce_get_next_hash_tbl(NULL,
18015940Ssowmini 	    &nw->nce_hash_tbl_index, nw->nce_ip_ndp);
18025940Ssowmini 	wsp->walk_data = nw;
18035940Ssowmini 
18045940Ssowmini 	return (WALK_NEXT);
18055940Ssowmini }
18065940Ssowmini 
18075940Ssowmini static int
18085940Ssowmini nce_stack_walk_step(mdb_walk_state_t *wsp)
18095940Ssowmini {
18105940Ssowmini 	uintptr_t addr = wsp->walk_addr;
18115940Ssowmini 	nce_walk_data_t *nw = wsp->walk_data;
18125940Ssowmini 
18135940Ssowmini 	if (addr == NULL)
18145940Ssowmini 		return (WALK_DONE);
18155940Ssowmini 
18165940Ssowmini 	if (mdb_vread(&nw->nce, sizeof (nce_t), addr) == -1) {
18175940Ssowmini 		mdb_warn("failed to read nce_t at %p", addr);
18185940Ssowmini 		return (WALK_ERR);
18195940Ssowmini 	}
18205940Ssowmini 
18215940Ssowmini 	wsp->walk_addr = (uintptr_t)nw->nce.nce_next;
18225940Ssowmini 
18235940Ssowmini 	wsp->walk_addr = nce_get_next_hash_tbl(wsp->walk_addr,
18245940Ssowmini 	    &nw->nce_hash_tbl_index, nw->nce_ip_ndp);
18255940Ssowmini 
18265940Ssowmini 	return (wsp->walk_callback(addr, nw, wsp->walk_cbdata));
18275940Ssowmini }
18285940Ssowmini 
18295940Ssowmini static void
18305940Ssowmini nce_stack_walk_fini(mdb_walk_state_t *wsp)
18315940Ssowmini {
18325940Ssowmini 	mdb_free(wsp->walk_data, sizeof (nce_walk_data_t));
18335940Ssowmini }
18345940Ssowmini 
18355940Ssowmini /* ARGSUSED */
18365940Ssowmini static int
18375940Ssowmini nce_cb(uintptr_t addr, const nce_walk_data_t *iw, nce_cbdata_t *id)
18385940Ssowmini {
18395940Ssowmini 	nce_t nce;
18405940Ssowmini 
18415940Ssowmini 	if (mdb_vread(&nce, sizeof (nce_t), addr) == -1) {
18425940Ssowmini 		mdb_warn("failed to read nce at %p", addr);
18435940Ssowmini 		return (WALK_NEXT);
18445940Ssowmini 	}
18455940Ssowmini 	(void) nce_format(addr, &nce, id->nce_ipversion);
18465940Ssowmini 	return (WALK_NEXT);
18475940Ssowmini }
1848*9089SVasumathi.Sundaram@Sun.COM 
1849*9089SVasumathi.Sundaram@Sun.COM static int
1850*9089SVasumathi.Sundaram@Sun.COM ill_walk_init(mdb_walk_state_t *wsp)
1851*9089SVasumathi.Sundaram@Sun.COM {
1852*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_layered_walk("illif", wsp) == -1) {
1853*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't walk 'illif'");
1854*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
1855*9089SVasumathi.Sundaram@Sun.COM 	}
1856*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
1857*9089SVasumathi.Sundaram@Sun.COM }
1858*9089SVasumathi.Sundaram@Sun.COM 
1859*9089SVasumathi.Sundaram@Sun.COM static int
1860*9089SVasumathi.Sundaram@Sun.COM ill_walk_step(mdb_walk_state_t *wsp)
1861*9089SVasumathi.Sundaram@Sun.COM {
1862*9089SVasumathi.Sundaram@Sun.COM 	ill_if_t ill_if;
1863*9089SVasumathi.Sundaram@Sun.COM 
1864*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&ill_if, sizeof (ill_if_t), wsp->walk_addr) == -1) {
1865*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't read ill_if_t at %p", wsp->walk_addr);
1866*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
1867*9089SVasumathi.Sundaram@Sun.COM 	}
1868*9089SVasumathi.Sundaram@Sun.COM 	wsp->walk_addr = (uintptr_t)(wsp->walk_addr +
1869*9089SVasumathi.Sundaram@Sun.COM 	    offsetof(ill_if_t, illif_avl_by_ppa));
1870*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_pwalk("avl", wsp->walk_callback, wsp->walk_cbdata,
1871*9089SVasumathi.Sundaram@Sun.COM 	    wsp->walk_addr) == -1) {
1872*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't walk 'avl'");
1873*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
1874*9089SVasumathi.Sundaram@Sun.COM 	}
1875*9089SVasumathi.Sundaram@Sun.COM 
1876*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
1877*9089SVasumathi.Sundaram@Sun.COM }
1878*9089SVasumathi.Sundaram@Sun.COM 
1879*9089SVasumathi.Sundaram@Sun.COM /* ARGSUSED */
1880*9089SVasumathi.Sundaram@Sun.COM static int
1881*9089SVasumathi.Sundaram@Sun.COM ill_cb(uintptr_t addr, const ill_walk_data_t *iw, ill_cbdata_t *id)
1882*9089SVasumathi.Sundaram@Sun.COM {
1883*9089SVasumathi.Sundaram@Sun.COM 	ill_t ill;
1884*9089SVasumathi.Sundaram@Sun.COM 
1885*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&ill, sizeof (ill_t), (uintptr_t)addr) == -1) {
1886*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read ill at %p", addr);
1887*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
1888*9089SVasumathi.Sundaram@Sun.COM 	}
1889*9089SVasumathi.Sundaram@Sun.COM 	return (ill_format((uintptr_t)addr, &ill, id));
1890*9089SVasumathi.Sundaram@Sun.COM }
1891*9089SVasumathi.Sundaram@Sun.COM 
1892*9089SVasumathi.Sundaram@Sun.COM static void
1893*9089SVasumathi.Sundaram@Sun.COM ill_header(boolean_t verbose)
1894*9089SVasumathi.Sundaram@Sun.COM {
1895*9089SVasumathi.Sundaram@Sun.COM 	if (verbose) {
1896*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?s %-8s %3s %-10s %-?s %-?s %-10s%</u>\n",
1897*9089SVasumathi.Sundaram@Sun.COM 		    "ADDR", "NAME", "VER", "TYPE", "WQ", "IPST", "FLAGS");
1898*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?s %4s%4s %-?s\n",
1899*9089SVasumathi.Sundaram@Sun.COM 		    "PHYINT", "CNT", "", "GROUP");
1900*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%<u>%80s%</u>\n", "");
1901*9089SVasumathi.Sundaram@Sun.COM 	} else {
1902*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%<u>%-?s %-8s %-3s %-10s %4s %-?s %-10s%</u>\n",
1903*9089SVasumathi.Sundaram@Sun.COM 		    "ADDR", "NAME", "VER", "TYPE", "CNT", "WQ", "FLAGS");
1904*9089SVasumathi.Sundaram@Sun.COM 	}
1905*9089SVasumathi.Sundaram@Sun.COM }
1906*9089SVasumathi.Sundaram@Sun.COM 
1907*9089SVasumathi.Sundaram@Sun.COM static int
1908*9089SVasumathi.Sundaram@Sun.COM ill_format(uintptr_t addr, const void *illptr, void *ill_cb_arg)
1909*9089SVasumathi.Sundaram@Sun.COM {
1910*9089SVasumathi.Sundaram@Sun.COM 	ill_t *ill = (ill_t *)illptr;
1911*9089SVasumathi.Sundaram@Sun.COM 	ill_cbdata_t *illcb = ill_cb_arg;
1912*9089SVasumathi.Sundaram@Sun.COM 	boolean_t verbose = illcb->verbose;
1913*9089SVasumathi.Sundaram@Sun.COM 	phyint_t phyi;
1914*9089SVasumathi.Sundaram@Sun.COM 	static const mdb_bitmask_t fmasks[] = {
1915*9089SVasumathi.Sundaram@Sun.COM 		{ "R",		PHYI_RUNNING,		PHYI_RUNNING	},
1916*9089SVasumathi.Sundaram@Sun.COM 		{ "P",		PHYI_PROMISC,		PHYI_PROMISC	},
1917*9089SVasumathi.Sundaram@Sun.COM 		{ "V",		PHYI_VIRTUAL,		PHYI_VIRTUAL	},
1918*9089SVasumathi.Sundaram@Sun.COM 		{ "I",		PHYI_IPMP,		PHYI_IPMP	},
1919*9089SVasumathi.Sundaram@Sun.COM 		{ "f",		PHYI_FAILED,		PHYI_FAILED	},
1920*9089SVasumathi.Sundaram@Sun.COM 		{ "S",		PHYI_STANDBY,		PHYI_STANDBY	},
1921*9089SVasumathi.Sundaram@Sun.COM 		{ "i",		PHYI_INACTIVE,		PHYI_INACTIVE	},
1922*9089SVasumathi.Sundaram@Sun.COM 		{ "O",		PHYI_OFFLINE,		PHYI_OFFLINE	},
1923*9089SVasumathi.Sundaram@Sun.COM 		{ "T", 		ILLF_NOTRAILERS,	ILLF_NOTRAILERS },
1924*9089SVasumathi.Sundaram@Sun.COM 		{ "A",		ILLF_NOARP,		ILLF_NOARP	},
1925*9089SVasumathi.Sundaram@Sun.COM 		{ "M",		ILLF_MULTICAST,		ILLF_MULTICAST	},
1926*9089SVasumathi.Sundaram@Sun.COM 		{ "F",		ILLF_ROUTER,		ILLF_ROUTER	},
1927*9089SVasumathi.Sundaram@Sun.COM 		{ "D",		ILLF_NONUD,		ILLF_NONUD	},
1928*9089SVasumathi.Sundaram@Sun.COM 		{ "X",		ILLF_NORTEXCH,		ILLF_NORTEXCH	},
1929*9089SVasumathi.Sundaram@Sun.COM 		{ NULL,		0,			0		}
1930*9089SVasumathi.Sundaram@Sun.COM 	};
1931*9089SVasumathi.Sundaram@Sun.COM 	static const mdb_bitmask_t v_fmasks[] = {
1932*9089SVasumathi.Sundaram@Sun.COM 		{ "RUNNING",	PHYI_RUNNING,		PHYI_RUNNING	},
1933*9089SVasumathi.Sundaram@Sun.COM 		{ "PROMISC",	PHYI_PROMISC,		PHYI_PROMISC	},
1934*9089SVasumathi.Sundaram@Sun.COM 		{ "VIRTUAL",	PHYI_VIRTUAL,		PHYI_VIRTUAL	},
1935*9089SVasumathi.Sundaram@Sun.COM 		{ "IPMP",	PHYI_IPMP,		PHYI_IPMP	},
1936*9089SVasumathi.Sundaram@Sun.COM 		{ "FAILED",	PHYI_FAILED,		PHYI_FAILED	},
1937*9089SVasumathi.Sundaram@Sun.COM 		{ "STANDBY",	PHYI_STANDBY,		PHYI_STANDBY	},
1938*9089SVasumathi.Sundaram@Sun.COM 		{ "INACTIVE",	PHYI_INACTIVE,		PHYI_INACTIVE	},
1939*9089SVasumathi.Sundaram@Sun.COM 		{ "OFFLINE",	PHYI_OFFLINE,		PHYI_OFFLINE	},
1940*9089SVasumathi.Sundaram@Sun.COM 		{ "NOTRAILER",	ILLF_NOTRAILERS,	ILLF_NOTRAILERS },
1941*9089SVasumathi.Sundaram@Sun.COM 		{ "NOARP",	ILLF_NOARP,		ILLF_NOARP	},
1942*9089SVasumathi.Sundaram@Sun.COM 		{ "MULTICAST",	ILLF_MULTICAST,		ILLF_MULTICAST	},
1943*9089SVasumathi.Sundaram@Sun.COM 		{ "ROUTER",	ILLF_ROUTER,		ILLF_ROUTER	},
1944*9089SVasumathi.Sundaram@Sun.COM 		{ "NONUD",	ILLF_NONUD,		ILLF_NONUD	},
1945*9089SVasumathi.Sundaram@Sun.COM 		{ "NORTEXCH",	ILLF_NORTEXCH,		ILLF_NORTEXCH	},
1946*9089SVasumathi.Sundaram@Sun.COM 		{ NULL,		0,			0		}
1947*9089SVasumathi.Sundaram@Sun.COM 	};
1948*9089SVasumathi.Sundaram@Sun.COM 	char ill_name[LIFNAMSIZ];
1949*9089SVasumathi.Sundaram@Sun.COM 	int cnt;
1950*9089SVasumathi.Sundaram@Sun.COM 	char *typebuf;
1951*9089SVasumathi.Sundaram@Sun.COM 	char sbuf[DEFCOLS];
1952*9089SVasumathi.Sundaram@Sun.COM 	int ipver = illcb->ill_ipversion;
1953*9089SVasumathi.Sundaram@Sun.COM 
1954*9089SVasumathi.Sundaram@Sun.COM 	if (ipver != 0) {
1955*9089SVasumathi.Sundaram@Sun.COM 		if ((ipver == IPV4_VERSION && ill->ill_isv6) ||
1956*9089SVasumathi.Sundaram@Sun.COM 		    (ipver == IPV6_VERSION && !ill->ill_isv6)) {
1957*9089SVasumathi.Sundaram@Sun.COM 			return (WALK_NEXT);
1958*9089SVasumathi.Sundaram@Sun.COM 		}
1959*9089SVasumathi.Sundaram@Sun.COM 	}
1960*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&phyi, sizeof (phyint_t),
1961*9089SVasumathi.Sundaram@Sun.COM 	    (uintptr_t)ill->ill_phyint) == -1) {
1962*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read ill_phyint at %p",
1963*9089SVasumathi.Sundaram@Sun.COM 		    (uintptr_t)ill->ill_phyint);
1964*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
1965*9089SVasumathi.Sundaram@Sun.COM 	}
1966*9089SVasumathi.Sundaram@Sun.COM 	(void) mdb_readstr(ill_name, MIN(LIFNAMSIZ, ill->ill_name_length),
1967*9089SVasumathi.Sundaram@Sun.COM 	    (uintptr_t)ill->ill_name);
1968*9089SVasumathi.Sundaram@Sun.COM 
1969*9089SVasumathi.Sundaram@Sun.COM 	switch (ill->ill_type) {
1970*9089SVasumathi.Sundaram@Sun.COM 	case 0:
1971*9089SVasumathi.Sundaram@Sun.COM 		typebuf = "LOOPBACK";
1972*9089SVasumathi.Sundaram@Sun.COM 		break;
1973*9089SVasumathi.Sundaram@Sun.COM 	case IFT_ETHER:
1974*9089SVasumathi.Sundaram@Sun.COM 		typebuf = "ETHER";
1975*9089SVasumathi.Sundaram@Sun.COM 		break;
1976*9089SVasumathi.Sundaram@Sun.COM 	case IFT_OTHER:
1977*9089SVasumathi.Sundaram@Sun.COM 		typebuf = "OTHER";
1978*9089SVasumathi.Sundaram@Sun.COM 		break;
1979*9089SVasumathi.Sundaram@Sun.COM 	default:
1980*9089SVasumathi.Sundaram@Sun.COM 		typebuf = NULL;
1981*9089SVasumathi.Sundaram@Sun.COM 		break;
1982*9089SVasumathi.Sundaram@Sun.COM 	}
1983*9089SVasumathi.Sundaram@Sun.COM 	cnt = ill->ill_refcnt + ill->ill_ire_cnt + ill->ill_nce_cnt +
1984*9089SVasumathi.Sundaram@Sun.COM 	    ill->ill_ilm_walker_cnt + ill->ill_ilm_cnt;
1985*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%-?p %-8s %-3s ",
1986*9089SVasumathi.Sundaram@Sun.COM 	    addr, ill_name, ill->ill_isv6 ? "v6" : "v4");
1987*9089SVasumathi.Sundaram@Sun.COM 	if (typebuf != NULL)
1988*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-10s ", typebuf);
1989*9089SVasumathi.Sundaram@Sun.COM 	else
1990*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-10x ", ill->ill_type);
1991*9089SVasumathi.Sundaram@Sun.COM 	if (verbose) {
1992*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?p %-?p %-llb\n",
1993*9089SVasumathi.Sundaram@Sun.COM 		    ill->ill_wq, ill->ill_ipst,
1994*9089SVasumathi.Sundaram@Sun.COM 		    ill->ill_flags | phyi.phyint_flags, v_fmasks);
1995*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?p %4d%4s %-?p\n",
1996*9089SVasumathi.Sundaram@Sun.COM 		    ill->ill_phyint, cnt, "", ill->ill_grp);
1997*9089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(sbuf, sizeof (sbuf), "%*s %3s",
1998*9089SVasumathi.Sundaram@Sun.COM 		    sizeof (uintptr_t) * 2, "", "");
1999*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%s|\n%s+--> %3d %-18s "
2000*9089SVasumathi.Sundaram@Sun.COM 		    "references from active threads\n",
2001*9089SVasumathi.Sundaram@Sun.COM 		    sbuf, sbuf, ill->ill_refcnt, "ill_refcnt");
2002*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*s %7d %-18s ires referencing this ill\n",
2003*9089SVasumathi.Sundaram@Sun.COM 		    strlen(sbuf), "", ill->ill_ire_cnt, "ill_ire_cnt");
2004*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*s %7d %-18s nces referencing this ill\n",
2005*9089SVasumathi.Sundaram@Sun.COM 		    strlen(sbuf), "", ill->ill_nce_cnt, "ill_nce_cnt");
2006*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*s %7d %-18s ilms referencing this ill\n",
2007*9089SVasumathi.Sundaram@Sun.COM 		    strlen(sbuf), "", ill->ill_ilm_cnt, "ill_ilm_cnt");
2008*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*s %7d %-18s active ilm walkers\n\n",
2009*9089SVasumathi.Sundaram@Sun.COM 		    strlen(sbuf), "", ill->ill_ilm_walker_cnt,
2010*9089SVasumathi.Sundaram@Sun.COM 		    "ill_ilm_walker_cnt");
2011*9089SVasumathi.Sundaram@Sun.COM 	} else {
2012*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%4d %-?p %-llb\n",
2013*9089SVasumathi.Sundaram@Sun.COM 		    cnt, ill->ill_wq,
2014*9089SVasumathi.Sundaram@Sun.COM 		    ill->ill_flags | phyi.phyint_flags, fmasks);
2015*9089SVasumathi.Sundaram@Sun.COM 	}
2016*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
2017*9089SVasumathi.Sundaram@Sun.COM }
2018*9089SVasumathi.Sundaram@Sun.COM 
2019*9089SVasumathi.Sundaram@Sun.COM static int
2020*9089SVasumathi.Sundaram@Sun.COM ill(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2021*9089SVasumathi.Sundaram@Sun.COM {
2022*9089SVasumathi.Sundaram@Sun.COM 	ill_t ill_data;
2023*9089SVasumathi.Sundaram@Sun.COM 	ill_cbdata_t id;
2024*9089SVasumathi.Sundaram@Sun.COM 	int ipversion = 0;
2025*9089SVasumathi.Sundaram@Sun.COM 	const char *opt_P = NULL;
2026*9089SVasumathi.Sundaram@Sun.COM 	uint_t verbose = FALSE;
2027*9089SVasumathi.Sundaram@Sun.COM 
2028*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_getopts(argc, argv,
2029*9089SVasumathi.Sundaram@Sun.COM 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
2030*9089SVasumathi.Sundaram@Sun.COM 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
2031*9089SVasumathi.Sundaram@Sun.COM 		return (DCMD_USAGE);
2032*9089SVasumathi.Sundaram@Sun.COM 
2033*9089SVasumathi.Sundaram@Sun.COM 	if (opt_P != NULL) {
2034*9089SVasumathi.Sundaram@Sun.COM 		if (strcmp("v4", opt_P) == 0) {
2035*9089SVasumathi.Sundaram@Sun.COM 			ipversion = IPV4_VERSION;
2036*9089SVasumathi.Sundaram@Sun.COM 		} else if (strcmp("v6", opt_P) == 0) {
2037*9089SVasumathi.Sundaram@Sun.COM 			ipversion = IPV6_VERSION;
2038*9089SVasumathi.Sundaram@Sun.COM 		} else {
2039*9089SVasumathi.Sundaram@Sun.COM 			mdb_warn("invalid protocol '%s'\n", opt_P);
2040*9089SVasumathi.Sundaram@Sun.COM 			return (DCMD_USAGE);
2041*9089SVasumathi.Sundaram@Sun.COM 		}
2042*9089SVasumathi.Sundaram@Sun.COM 	}
2043*9089SVasumathi.Sundaram@Sun.COM 
2044*9089SVasumathi.Sundaram@Sun.COM 	id.verbose = verbose;
2045*9089SVasumathi.Sundaram@Sun.COM 	id.ill_addr = addr;
2046*9089SVasumathi.Sundaram@Sun.COM 	id.ill_ipversion = ipversion;
2047*9089SVasumathi.Sundaram@Sun.COM 
2048*9089SVasumathi.Sundaram@Sun.COM 	ill_header(verbose);
2049*9089SVasumathi.Sundaram@Sun.COM 	if (flags & DCMD_ADDRSPEC) {
2050*9089SVasumathi.Sundaram@Sun.COM 		if (mdb_vread(&ill_data, sizeof (ill_t), addr) == -1) {
2051*9089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to read ill at %p\n", addr);
2052*9089SVasumathi.Sundaram@Sun.COM 			return (DCMD_ERR);
2053*9089SVasumathi.Sundaram@Sun.COM 		}
2054*9089SVasumathi.Sundaram@Sun.COM 		(void) ill_format(addr, &ill_data, &id);
2055*9089SVasumathi.Sundaram@Sun.COM 	} else {
2056*9089SVasumathi.Sundaram@Sun.COM 		if (mdb_walk("ill", (mdb_walk_cb_t)ill_cb, &id) == -1) {
2057*9089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to walk ills\n");
2058*9089SVasumathi.Sundaram@Sun.COM 			return (DCMD_ERR);
2059*9089SVasumathi.Sundaram@Sun.COM 		}
2060*9089SVasumathi.Sundaram@Sun.COM 	}
2061*9089SVasumathi.Sundaram@Sun.COM 	return (DCMD_OK);
2062*9089SVasumathi.Sundaram@Sun.COM }
2063*9089SVasumathi.Sundaram@Sun.COM 
2064*9089SVasumathi.Sundaram@Sun.COM static void
2065*9089SVasumathi.Sundaram@Sun.COM ill_help(void)
2066*9089SVasumathi.Sundaram@Sun.COM {
2067*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("Prints the following fields: ill ptr, name, "
2068*9089SVasumathi.Sundaram@Sun.COM 	    "IP version, count, ill type and ill flags.\n"
2069*9089SVasumathi.Sundaram@Sun.COM 	    "The count field is a sum of individual refcnts and is expanded "
2070*9089SVasumathi.Sundaram@Sun.COM 	    "with the -v option.\n\n");
2071*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("Options:\n");
2072*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("\t-P v4 | v6"
2073*9089SVasumathi.Sundaram@Sun.COM 	    "\tfilter ill structures for the specified protocol\n");
2074*9089SVasumathi.Sundaram@Sun.COM }
2075*9089SVasumathi.Sundaram@Sun.COM 
2076*9089SVasumathi.Sundaram@Sun.COM static int
2077*9089SVasumathi.Sundaram@Sun.COM ip_list_walk_init(mdb_walk_state_t *wsp)
2078*9089SVasumathi.Sundaram@Sun.COM {
2079*9089SVasumathi.Sundaram@Sun.COM 	const ip_list_walk_arg_t *arg = wsp->walk_arg;
2080*9089SVasumathi.Sundaram@Sun.COM 	ip_list_walk_data_t *iw;
2081*9089SVasumathi.Sundaram@Sun.COM 	uintptr_t addr = (uintptr_t)(wsp->walk_addr + arg->off);
2082*9089SVasumathi.Sundaram@Sun.COM 
2083*9089SVasumathi.Sundaram@Sun.COM 	if (wsp->walk_addr == NULL) {
2084*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("only local walks supported\n");
2085*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
2086*9089SVasumathi.Sundaram@Sun.COM 	}
2087*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t),
2088*9089SVasumathi.Sundaram@Sun.COM 	    addr) == -1) {
2089*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read list head at %p", addr);
2090*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
2091*9089SVasumathi.Sundaram@Sun.COM 	}
2092*9089SVasumathi.Sundaram@Sun.COM 	iw = mdb_alloc(sizeof (ip_list_walk_data_t), UM_SLEEP);
2093*9089SVasumathi.Sundaram@Sun.COM 	iw->nextoff = arg->nextp_off;
2094*9089SVasumathi.Sundaram@Sun.COM 	wsp->walk_data = iw;
2095*9089SVasumathi.Sundaram@Sun.COM 
2096*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
2097*9089SVasumathi.Sundaram@Sun.COM }
2098*9089SVasumathi.Sundaram@Sun.COM 
2099*9089SVasumathi.Sundaram@Sun.COM static int
2100*9089SVasumathi.Sundaram@Sun.COM ip_list_walk_step(mdb_walk_state_t *wsp)
2101*9089SVasumathi.Sundaram@Sun.COM {
2102*9089SVasumathi.Sundaram@Sun.COM 	ip_list_walk_data_t *iw = wsp->walk_data;
2103*9089SVasumathi.Sundaram@Sun.COM 	uintptr_t addr = wsp->walk_addr;
2104*9089SVasumathi.Sundaram@Sun.COM 
2105*9089SVasumathi.Sundaram@Sun.COM 	if (addr == NULL)
2106*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_DONE);
2107*9089SVasumathi.Sundaram@Sun.COM 	wsp->walk_addr = addr + iw->nextoff;
2108*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t),
2109*9089SVasumathi.Sundaram@Sun.COM 	    wsp->walk_addr) == -1) {
2110*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read list node at %p", addr);
2111*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
2112*9089SVasumathi.Sundaram@Sun.COM 	}
2113*9089SVasumathi.Sundaram@Sun.COM 	return (wsp->walk_callback(addr, iw, wsp->walk_cbdata));
2114*9089SVasumathi.Sundaram@Sun.COM }
2115*9089SVasumathi.Sundaram@Sun.COM 
2116*9089SVasumathi.Sundaram@Sun.COM static void
2117*9089SVasumathi.Sundaram@Sun.COM ip_list_walk_fini(mdb_walk_state_t *wsp)
2118*9089SVasumathi.Sundaram@Sun.COM {
2119*9089SVasumathi.Sundaram@Sun.COM 	mdb_free(wsp->walk_data, sizeof (ip_list_walk_data_t));
2120*9089SVasumathi.Sundaram@Sun.COM }
2121*9089SVasumathi.Sundaram@Sun.COM 
2122*9089SVasumathi.Sundaram@Sun.COM static int
2123*9089SVasumathi.Sundaram@Sun.COM ipif_walk_init(mdb_walk_state_t *wsp)
2124*9089SVasumathi.Sundaram@Sun.COM {
2125*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_layered_walk("ill", wsp) == -1) {
2126*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't walk 'ills'");
2127*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
2128*9089SVasumathi.Sundaram@Sun.COM 	}
2129*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
2130*9089SVasumathi.Sundaram@Sun.COM }
2131*9089SVasumathi.Sundaram@Sun.COM 
2132*9089SVasumathi.Sundaram@Sun.COM static int
2133*9089SVasumathi.Sundaram@Sun.COM ipif_walk_step(mdb_walk_state_t *wsp)
2134*9089SVasumathi.Sundaram@Sun.COM {
2135*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_pwalk("ipif_list", wsp->walk_callback, wsp->walk_cbdata,
2136*9089SVasumathi.Sundaram@Sun.COM 	    wsp->walk_addr) == -1) {
2137*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't walk 'ipif_list'");
2138*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
2139*9089SVasumathi.Sundaram@Sun.COM 	}
2140*9089SVasumathi.Sundaram@Sun.COM 
2141*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
2142*9089SVasumathi.Sundaram@Sun.COM }
2143*9089SVasumathi.Sundaram@Sun.COM 
2144*9089SVasumathi.Sundaram@Sun.COM /* ARGSUSED */
2145*9089SVasumathi.Sundaram@Sun.COM static int
2146*9089SVasumathi.Sundaram@Sun.COM ipif_cb(uintptr_t addr, const ipif_walk_data_t *iw, ipif_cbdata_t *id)
2147*9089SVasumathi.Sundaram@Sun.COM {
2148*9089SVasumathi.Sundaram@Sun.COM 	ipif_t ipif;
2149*9089SVasumathi.Sundaram@Sun.COM 
2150*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&ipif, sizeof (ipif_t), (uintptr_t)addr) == -1) {
2151*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read ipif at %p", addr);
2152*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
2153*9089SVasumathi.Sundaram@Sun.COM 	}
2154*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&id->ill, sizeof (ill_t),
2155*9089SVasumathi.Sundaram@Sun.COM 	    (uintptr_t)ipif.ipif_ill) == -1) {
2156*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read ill at %p", ipif.ipif_ill);
2157*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
2158*9089SVasumathi.Sundaram@Sun.COM 	}
2159*9089SVasumathi.Sundaram@Sun.COM 	(void) ipif_format((uintptr_t)addr, &ipif, id);
2160*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
2161*9089SVasumathi.Sundaram@Sun.COM }
2162*9089SVasumathi.Sundaram@Sun.COM 
2163*9089SVasumathi.Sundaram@Sun.COM static void
2164*9089SVasumathi.Sundaram@Sun.COM ipif_header(boolean_t verbose)
2165*9089SVasumathi.Sundaram@Sun.COM {
2166*9089SVasumathi.Sundaram@Sun.COM 	if (verbose) {
2167*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?s %-10s %-3s %-?s %-8s %-30s\n",
2168*9089SVasumathi.Sundaram@Sun.COM 		    "ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS");
2169*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%s\n%s\n",
2170*9089SVasumathi.Sundaram@Sun.COM 		    "LCLADDR", "BROADCAST");
2171*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%<u>%80s%</u>\n", "");
2172*9089SVasumathi.Sundaram@Sun.COM 	} else {
2173*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?s %-10s %6s %-?s %-8s %-30s\n",
2174*9089SVasumathi.Sundaram@Sun.COM 		    "ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS");
2175*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%s\n%<u>%80s%</u>\n", "LCLADDR", "");
2176*9089SVasumathi.Sundaram@Sun.COM 	}
2177*9089SVasumathi.Sundaram@Sun.COM }
2178*9089SVasumathi.Sundaram@Sun.COM 
2179*9089SVasumathi.Sundaram@Sun.COM #ifdef _BIG_ENDIAN
2180*9089SVasumathi.Sundaram@Sun.COM #define	ip_ntohl_32(x)	((x) & 0xffffffff)
2181*9089SVasumathi.Sundaram@Sun.COM #else
2182*9089SVasumathi.Sundaram@Sun.COM #define	ip_ntohl_32(x)	(((uint32_t)(x) << 24) | \
2183*9089SVasumathi.Sundaram@Sun.COM 			(((uint32_t)(x) << 8) & 0xff0000) | \
2184*9089SVasumathi.Sundaram@Sun.COM 			(((uint32_t)(x) >> 8) & 0xff00) | \
2185*9089SVasumathi.Sundaram@Sun.COM 			((uint32_t)(x)  >> 24))
2186*9089SVasumathi.Sundaram@Sun.COM #endif
2187*9089SVasumathi.Sundaram@Sun.COM 
2188*9089SVasumathi.Sundaram@Sun.COM int
2189*9089SVasumathi.Sundaram@Sun.COM mask_to_prefixlen(int af, const in6_addr_t *addr)
2190*9089SVasumathi.Sundaram@Sun.COM {
2191*9089SVasumathi.Sundaram@Sun.COM 	int len = 0;
2192*9089SVasumathi.Sundaram@Sun.COM 	int i;
2193*9089SVasumathi.Sundaram@Sun.COM 	uint_t mask = 0;
2194*9089SVasumathi.Sundaram@Sun.COM 
2195*9089SVasumathi.Sundaram@Sun.COM 	if (af == AF_INET6) {
2196*9089SVasumathi.Sundaram@Sun.COM 		for (i = 0; i < 4; i++) {
2197*9089SVasumathi.Sundaram@Sun.COM 			if (addr->s6_addr32[i] == 0xffffffff) {
2198*9089SVasumathi.Sundaram@Sun.COM 				len += 32;
2199*9089SVasumathi.Sundaram@Sun.COM 			} else {
2200*9089SVasumathi.Sundaram@Sun.COM 				mask = addr->s6_addr32[i];
2201*9089SVasumathi.Sundaram@Sun.COM 				break;
2202*9089SVasumathi.Sundaram@Sun.COM 			}
2203*9089SVasumathi.Sundaram@Sun.COM 		}
2204*9089SVasumathi.Sundaram@Sun.COM 	} else {
2205*9089SVasumathi.Sundaram@Sun.COM 		mask = V4_PART_OF_V6((*addr));
2206*9089SVasumathi.Sundaram@Sun.COM 	}
2207*9089SVasumathi.Sundaram@Sun.COM 	if (mask > 0)
2208*9089SVasumathi.Sundaram@Sun.COM 		len += (33 - mdb_ffs(ip_ntohl_32(mask)));
2209*9089SVasumathi.Sundaram@Sun.COM 	return (len);
2210*9089SVasumathi.Sundaram@Sun.COM }
2211*9089SVasumathi.Sundaram@Sun.COM 
2212*9089SVasumathi.Sundaram@Sun.COM static int
2213*9089SVasumathi.Sundaram@Sun.COM ipif_format(uintptr_t addr, const void *ipifptr, void *ipif_cb_arg)
2214*9089SVasumathi.Sundaram@Sun.COM {
2215*9089SVasumathi.Sundaram@Sun.COM 	const ipif_t *ipif = ipifptr;
2216*9089SVasumathi.Sundaram@Sun.COM 	ipif_cbdata_t *ipifcb = ipif_cb_arg;
2217*9089SVasumathi.Sundaram@Sun.COM 	boolean_t verbose = ipifcb->verbose;
2218*9089SVasumathi.Sundaram@Sun.COM 	char ill_name[LIFNAMSIZ];
2219*9089SVasumathi.Sundaram@Sun.COM 	char buf[LIFNAMSIZ];
2220*9089SVasumathi.Sundaram@Sun.COM 	int cnt;
2221*9089SVasumathi.Sundaram@Sun.COM 	static const mdb_bitmask_t sfmasks[] = {
2222*9089SVasumathi.Sundaram@Sun.COM 		{ "CO",		IPIF_CONDEMNED,		IPIF_CONDEMNED},
2223*9089SVasumathi.Sundaram@Sun.COM 		{ "CH",		IPIF_CHANGING,		IPIF_CHANGING},
2224*9089SVasumathi.Sundaram@Sun.COM 		{ "SL",		IPIF_SET_LINKLOCAL,	IPIF_SET_LINKLOCAL},
2225*9089SVasumathi.Sundaram@Sun.COM 		{ "ZS",		IPIF_ZERO_SOURCE,	IPIF_ZERO_SOURCE},
2226*9089SVasumathi.Sundaram@Sun.COM 		{ NULL,		0,			0		}
2227*9089SVasumathi.Sundaram@Sun.COM 	};
2228*9089SVasumathi.Sundaram@Sun.COM 	static const mdb_bitmask_t fmasks[] = {
2229*9089SVasumathi.Sundaram@Sun.COM 		{ "UP",		IPIF_UP,		IPIF_UP		},
2230*9089SVasumathi.Sundaram@Sun.COM 		{ "UNN",	IPIF_UNNUMBERED,	IPIF_UNNUMBERED},
2231*9089SVasumathi.Sundaram@Sun.COM 		{ "DHCP",	IPIF_DHCPRUNNING,	IPIF_DHCPRUNNING},
2232*9089SVasumathi.Sundaram@Sun.COM 		{ "PRIV",	IPIF_PRIVATE,		IPIF_PRIVATE},
2233*9089SVasumathi.Sundaram@Sun.COM 		{ "NOXMT",	IPIF_NOXMIT,		IPIF_NOXMIT},
2234*9089SVasumathi.Sundaram@Sun.COM 		{ "NOLCL",	IPIF_NOLOCAL,		IPIF_NOLOCAL},
2235*9089SVasumathi.Sundaram@Sun.COM 		{ "DEPR",	IPIF_DEPRECATED,	IPIF_DEPRECATED},
2236*9089SVasumathi.Sundaram@Sun.COM 		{ "PREF",	IPIF_PREFERRED,		IPIF_PREFERRED},
2237*9089SVasumathi.Sundaram@Sun.COM 		{ "TEMP",	IPIF_TEMPORARY,		IPIF_TEMPORARY},
2238*9089SVasumathi.Sundaram@Sun.COM 		{ "ACONF",	IPIF_ADDRCONF,		IPIF_ADDRCONF},
2239*9089SVasumathi.Sundaram@Sun.COM 		{ "ANY",	IPIF_ANYCAST,		IPIF_ANYCAST},
2240*9089SVasumathi.Sundaram@Sun.COM 		{ "NFAIL",	IPIF_NOFAILOVER,	IPIF_NOFAILOVER},
2241*9089SVasumathi.Sundaram@Sun.COM 		{ NULL,		0,			0		}
2242*9089SVasumathi.Sundaram@Sun.COM 	};
2243*9089SVasumathi.Sundaram@Sun.COM 	char flagsbuf[2 * A_CNT(fmasks)];
2244*9089SVasumathi.Sundaram@Sun.COM 	char bitfields[A_CNT(fmasks)];
2245*9089SVasumathi.Sundaram@Sun.COM 	char sflagsbuf[A_CNT(sfmasks)];
2246*9089SVasumathi.Sundaram@Sun.COM 	char sbuf[DEFCOLS], addrstr[INET6_ADDRSTRLEN];
2247*9089SVasumathi.Sundaram@Sun.COM 	int ipver = ipifcb->ipif_ipversion;
2248*9089SVasumathi.Sundaram@Sun.COM 	int af;
2249*9089SVasumathi.Sundaram@Sun.COM 
2250*9089SVasumathi.Sundaram@Sun.COM 	if (ipver != 0) {
2251*9089SVasumathi.Sundaram@Sun.COM 		if ((ipver == IPV4_VERSION && ipifcb->ill.ill_isv6) ||
2252*9089SVasumathi.Sundaram@Sun.COM 		    (ipver == IPV6_VERSION && !ipifcb->ill.ill_isv6)) {
2253*9089SVasumathi.Sundaram@Sun.COM 			return (WALK_NEXT);
2254*9089SVasumathi.Sundaram@Sun.COM 		}
2255*9089SVasumathi.Sundaram@Sun.COM 	}
2256*9089SVasumathi.Sundaram@Sun.COM 	if ((mdb_readstr(ill_name, MIN(LIFNAMSIZ,
2257*9089SVasumathi.Sundaram@Sun.COM 	    ipifcb->ill.ill_name_length),
2258*9089SVasumathi.Sundaram@Sun.COM 	    (uintptr_t)ipifcb->ill.ill_name)) == -1) {
2259*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read ill_name of ill %p\n", ipifcb->ill);
2260*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_NEXT);
2261*9089SVasumathi.Sundaram@Sun.COM 	}
2262*9089SVasumathi.Sundaram@Sun.COM 	if (ipif->ipif_id != 0) {
2263*9089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(buf, LIFNAMSIZ, "%s:%d",
2264*9089SVasumathi.Sundaram@Sun.COM 		    ill_name, ipif->ipif_id);
2265*9089SVasumathi.Sundaram@Sun.COM 	} else {
2266*9089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(buf, LIFNAMSIZ, "%s", ill_name);
2267*9089SVasumathi.Sundaram@Sun.COM 	}
2268*9089SVasumathi.Sundaram@Sun.COM 	mdb_snprintf(bitfields, sizeof (bitfields), "%s",
2269*9089SVasumathi.Sundaram@Sun.COM 	    ipif->ipif_addr_ready ? ",ADR" : "",
2270*9089SVasumathi.Sundaram@Sun.COM 	    ipif->ipif_multicast_up ? ",MU" : "",
2271*9089SVasumathi.Sundaram@Sun.COM 	    ipif->ipif_was_up ? ",WU" : "",
2272*9089SVasumathi.Sundaram@Sun.COM 	    ipif->ipif_was_dup ? ",WD" : "",
2273*9089SVasumathi.Sundaram@Sun.COM 	    ipif->ipif_joined_allhosts ? ",JA" : "");
2274*9089SVasumathi.Sundaram@Sun.COM 	mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%llb%s",
2275*9089SVasumathi.Sundaram@Sun.COM 	    ipif->ipif_flags, fmasks, bitfields);
2276*9089SVasumathi.Sundaram@Sun.COM 	mdb_snprintf(sflagsbuf, sizeof (sflagsbuf), "%b",
2277*9089SVasumathi.Sundaram@Sun.COM 	    ipif->ipif_state_flags, sfmasks);
2278*9089SVasumathi.Sundaram@Sun.COM 
2279*9089SVasumathi.Sundaram@Sun.COM 	cnt = ipif->ipif_refcnt + ipif->ipif_ire_cnt + ipif->ipif_ilm_cnt;
2280*9089SVasumathi.Sundaram@Sun.COM 
2281*9089SVasumathi.Sundaram@Sun.COM 	if (ipifcb->ill.ill_isv6) {
2282*9089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(addrstr, sizeof (addrstr), "%N",
2283*9089SVasumathi.Sundaram@Sun.COM 		    &ipif->ipif_v6lcl_addr);
2284*9089SVasumathi.Sundaram@Sun.COM 		af = AF_INET6;
2285*9089SVasumathi.Sundaram@Sun.COM 	} else {
2286*9089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(addrstr, sizeof (addrstr), "%I",
2287*9089SVasumathi.Sundaram@Sun.COM 		    V4_PART_OF_V6((ipif->ipif_v6lcl_addr)));
2288*9089SVasumathi.Sundaram@Sun.COM 		af = AF_INET;
2289*9089SVasumathi.Sundaram@Sun.COM 	}
2290*9089SVasumathi.Sundaram@Sun.COM 
2291*9089SVasumathi.Sundaram@Sun.COM 	if (verbose) {
2292*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?p %-10s %3d %-?p %-8s %-30s\n",
2293*9089SVasumathi.Sundaram@Sun.COM 		    addr, buf, cnt, ipif->ipif_ill,
2294*9089SVasumathi.Sundaram@Sun.COM 		    sflagsbuf, flagsbuf);
2295*9089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(sbuf, sizeof (sbuf), "%*s %12s",
2296*9089SVasumathi.Sundaram@Sun.COM 		    sizeof (uintptr_t) * 2, "", "");
2297*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%s |\n%s +---> %4d %-15s "
2298*9089SVasumathi.Sundaram@Sun.COM 		    "Active consistent reader cnt\n",
2299*9089SVasumathi.Sundaram@Sun.COM 		    sbuf, sbuf, ipif->ipif_refcnt, "ipif_refcnt");
2300*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*s %10d %-15s "
2301*9089SVasumathi.Sundaram@Sun.COM 		    "Number of ire's referencing this ipif\n",
2302*9089SVasumathi.Sundaram@Sun.COM 		    strlen(sbuf), "", ipif->ipif_ire_cnt, "ipif_ire_cnt");
2303*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%*s %10d %-15s "
2304*9089SVasumathi.Sundaram@Sun.COM 		    "Number of ilm's referencing this ipif\n\n",
2305*9089SVasumathi.Sundaram@Sun.COM 		    strlen(sbuf), "", ipif->ipif_ilm_cnt, "ipif_ilm_cnt");
2306*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-s/%d\n",
2307*9089SVasumathi.Sundaram@Sun.COM 		    addrstr, mask_to_prefixlen(af, &ipif->ipif_v6net_mask));
2308*9089SVasumathi.Sundaram@Sun.COM 		if (ipifcb->ill.ill_isv6) {
2309*9089SVasumathi.Sundaram@Sun.COM 			mdb_printf("%-N\n", &ipif->ipif_v6brd_addr);
2310*9089SVasumathi.Sundaram@Sun.COM 		} else {
2311*9089SVasumathi.Sundaram@Sun.COM 			mdb_printf("%-I\n",
2312*9089SVasumathi.Sundaram@Sun.COM 			    V4_PART_OF_V6((ipif->ipif_v6brd_addr)));
2313*9089SVasumathi.Sundaram@Sun.COM 		}
2314*9089SVasumathi.Sundaram@Sun.COM 	} else {
2315*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-?p %-10s %6d %-?p %-8s %-30s\n",
2316*9089SVasumathi.Sundaram@Sun.COM 		    addr, buf, cnt, ipif->ipif_ill,
2317*9089SVasumathi.Sundaram@Sun.COM 		    sflagsbuf, flagsbuf);
2318*9089SVasumathi.Sundaram@Sun.COM 		mdb_printf("%-s/%d\n",
2319*9089SVasumathi.Sundaram@Sun.COM 		    addrstr, mask_to_prefixlen(af, &ipif->ipif_v6net_mask));
2320*9089SVasumathi.Sundaram@Sun.COM 	}
2321*9089SVasumathi.Sundaram@Sun.COM 
2322*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
2323*9089SVasumathi.Sundaram@Sun.COM }
2324*9089SVasumathi.Sundaram@Sun.COM 
2325*9089SVasumathi.Sundaram@Sun.COM static int
2326*9089SVasumathi.Sundaram@Sun.COM ipif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2327*9089SVasumathi.Sundaram@Sun.COM {
2328*9089SVasumathi.Sundaram@Sun.COM 	ipif_t ipif;
2329*9089SVasumathi.Sundaram@Sun.COM 	ipif_cbdata_t id;
2330*9089SVasumathi.Sundaram@Sun.COM 	int ipversion = 0;
2331*9089SVasumathi.Sundaram@Sun.COM 	const char *opt_P = NULL;
2332*9089SVasumathi.Sundaram@Sun.COM 	uint_t verbose = FALSE;
2333*9089SVasumathi.Sundaram@Sun.COM 
2334*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_getopts(argc, argv,
2335*9089SVasumathi.Sundaram@Sun.COM 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
2336*9089SVasumathi.Sundaram@Sun.COM 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
2337*9089SVasumathi.Sundaram@Sun.COM 		return (DCMD_USAGE);
2338*9089SVasumathi.Sundaram@Sun.COM 
2339*9089SVasumathi.Sundaram@Sun.COM 	if (opt_P != NULL) {
2340*9089SVasumathi.Sundaram@Sun.COM 		if (strcmp("v4", opt_P) == 0) {
2341*9089SVasumathi.Sundaram@Sun.COM 			ipversion = IPV4_VERSION;
2342*9089SVasumathi.Sundaram@Sun.COM 		} else if (strcmp("v6", opt_P) == 0) {
2343*9089SVasumathi.Sundaram@Sun.COM 			ipversion = IPV6_VERSION;
2344*9089SVasumathi.Sundaram@Sun.COM 		} else {
2345*9089SVasumathi.Sundaram@Sun.COM 			mdb_warn("invalid protocol '%s'\n", opt_P);
2346*9089SVasumathi.Sundaram@Sun.COM 			return (DCMD_USAGE);
2347*9089SVasumathi.Sundaram@Sun.COM 		}
2348*9089SVasumathi.Sundaram@Sun.COM 	}
2349*9089SVasumathi.Sundaram@Sun.COM 
2350*9089SVasumathi.Sundaram@Sun.COM 	id.verbose = verbose;
2351*9089SVasumathi.Sundaram@Sun.COM 	id.ipif_ipversion = ipversion;
2352*9089SVasumathi.Sundaram@Sun.COM 
2353*9089SVasumathi.Sundaram@Sun.COM 	if (flags & DCMD_ADDRSPEC) {
2354*9089SVasumathi.Sundaram@Sun.COM 		if (mdb_vread(&ipif, sizeof (ipif_t), addr) == -1) {
2355*9089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to read ipif at %p\n", addr);
2356*9089SVasumathi.Sundaram@Sun.COM 			return (DCMD_ERR);
2357*9089SVasumathi.Sundaram@Sun.COM 		}
2358*9089SVasumathi.Sundaram@Sun.COM 		ipif_header(verbose);
2359*9089SVasumathi.Sundaram@Sun.COM 		if (mdb_vread(&id.ill, sizeof (ill_t),
2360*9089SVasumathi.Sundaram@Sun.COM 		    (uintptr_t)ipif.ipif_ill) == -1) {
2361*9089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to read ill at %p", ipif.ipif_ill);
2362*9089SVasumathi.Sundaram@Sun.COM 			return (WALK_NEXT);
2363*9089SVasumathi.Sundaram@Sun.COM 		}
2364*9089SVasumathi.Sundaram@Sun.COM 		return (ipif_format(addr, &ipif, &id));
2365*9089SVasumathi.Sundaram@Sun.COM 	} else {
2366*9089SVasumathi.Sundaram@Sun.COM 		ipif_header(verbose);
2367*9089SVasumathi.Sundaram@Sun.COM 		if (mdb_walk("ipif", (mdb_walk_cb_t)ipif_cb, &id) == -1) {
2368*9089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to walk ipifs\n");
2369*9089SVasumathi.Sundaram@Sun.COM 			return (DCMD_ERR);
2370*9089SVasumathi.Sundaram@Sun.COM 		}
2371*9089SVasumathi.Sundaram@Sun.COM 	}
2372*9089SVasumathi.Sundaram@Sun.COM 	return (DCMD_OK);
2373*9089SVasumathi.Sundaram@Sun.COM }
2374*9089SVasumathi.Sundaram@Sun.COM 
2375*9089SVasumathi.Sundaram@Sun.COM static void
2376*9089SVasumathi.Sundaram@Sun.COM ipif_help(void)
2377*9089SVasumathi.Sundaram@Sun.COM {
2378*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("Prints the following fields: ipif ptr, name, "
2379*9089SVasumathi.Sundaram@Sun.COM 	    "count, ill ptr, state flags and ipif flags.\n"
2380*9089SVasumathi.Sundaram@Sun.COM 	    "The count field is a sum of individual refcnts and is expanded "
2381*9089SVasumathi.Sundaram@Sun.COM 	    "with the -v option.\n"
2382*9089SVasumathi.Sundaram@Sun.COM 	    "The flags field shows the following:"
2383*9089SVasumathi.Sundaram@Sun.COM 	    "\n\tUNN -> UNNUMBERED, DHCP -> DHCPRUNNING, PRIV -> PRIVATE, "
2384*9089SVasumathi.Sundaram@Sun.COM 	    "\n\tNOXMT -> NOXMIT, NOLCL -> NOLOCAL, DEPR -> DEPRECATED, "
2385*9089SVasumathi.Sundaram@Sun.COM 	    "\n\tPREF -> PREFERRED, TEMP -> TEMPORARY, ACONF -> ADDRCONF, "
2386*9089SVasumathi.Sundaram@Sun.COM 	    "\n\tANY -> ANYCAST, NFAIL -> NOFAILOVER, "
2387*9089SVasumathi.Sundaram@Sun.COM 	    "\n\tADR -> ipif_addr_ready, MU -> ipif_multicast_up, "
2388*9089SVasumathi.Sundaram@Sun.COM 	    "\n\tWU -> ipif_was_up, WD -> ipif_was_dup, "
2389*9089SVasumathi.Sundaram@Sun.COM 	    "JA -> ipif_joined_allhosts.\n\n");
2390*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("Options:\n");
2391*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("\t-P v4 | v6"
2392*9089SVasumathi.Sundaram@Sun.COM 	    "\tfilter ipif structures on ills for the specified protocol\n");
2393*9089SVasumathi.Sundaram@Sun.COM }
2394*9089SVasumathi.Sundaram@Sun.COM 
2395*9089SVasumathi.Sundaram@Sun.COM static int
2396*9089SVasumathi.Sundaram@Sun.COM conn_status_walk_fanout(uintptr_t addr, mdb_walk_state_t *wsp,
2397*9089SVasumathi.Sundaram@Sun.COM     const char *walkname)
2398*9089SVasumathi.Sundaram@Sun.COM {
2399*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_pwalk(walkname, wsp->walk_callback, wsp->walk_cbdata,
2400*9089SVasumathi.Sundaram@Sun.COM 	    addr) == -1) {
2401*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("couldn't walk '%s' at %p", walkname, addr);
2402*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
2403*9089SVasumathi.Sundaram@Sun.COM 	}
2404*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
2405*9089SVasumathi.Sundaram@Sun.COM }
2406*9089SVasumathi.Sundaram@Sun.COM 
2407*9089SVasumathi.Sundaram@Sun.COM static int
2408*9089SVasumathi.Sundaram@Sun.COM conn_status_walk_step(mdb_walk_state_t *wsp)
2409*9089SVasumathi.Sundaram@Sun.COM {
2410*9089SVasumathi.Sundaram@Sun.COM 	uintptr_t addr = wsp->walk_addr;
2411*9089SVasumathi.Sundaram@Sun.COM 
2412*9089SVasumathi.Sundaram@Sun.COM 	(void) conn_status_walk_fanout(addr, wsp, "udp_hash");
2413*9089SVasumathi.Sundaram@Sun.COM 	(void) conn_status_walk_fanout(addr, wsp, "conn_hash");
2414*9089SVasumathi.Sundaram@Sun.COM 	(void) conn_status_walk_fanout(addr, wsp, "bind_hash");
2415*9089SVasumathi.Sundaram@Sun.COM 	(void) conn_status_walk_fanout(addr, wsp, "proto_hash");
2416*9089SVasumathi.Sundaram@Sun.COM 	(void) conn_status_walk_fanout(addr, wsp, "proto_v6_hash");
2417*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
2418*9089SVasumathi.Sundaram@Sun.COM }
2419*9089SVasumathi.Sundaram@Sun.COM 
2420*9089SVasumathi.Sundaram@Sun.COM /* ARGSUSED */
2421*9089SVasumathi.Sundaram@Sun.COM static int
2422*9089SVasumathi.Sundaram@Sun.COM conn_status_cb(uintptr_t addr, const void *walk_data,
2423*9089SVasumathi.Sundaram@Sun.COM     void *private)
2424*9089SVasumathi.Sundaram@Sun.COM {
2425*9089SVasumathi.Sundaram@Sun.COM 	netstack_t nss;
2426*9089SVasumathi.Sundaram@Sun.COM 	char src_addrstr[INET6_ADDRSTRLEN];
2427*9089SVasumathi.Sundaram@Sun.COM 	char rem_addrstr[INET6_ADDRSTRLEN];
2428*9089SVasumathi.Sundaram@Sun.COM 	const ipcl_hash_walk_data_t *iw = walk_data;
2429*9089SVasumathi.Sundaram@Sun.COM 	conn_t *conn = iw->conn;
2430*9089SVasumathi.Sundaram@Sun.COM 
2431*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(conn, sizeof (conn_t), addr) == -1) {
2432*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read conn_t at %p", addr);
2433*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
2434*9089SVasumathi.Sundaram@Sun.COM 	}
2435*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&nss, sizeof (nss),
2436*9089SVasumathi.Sundaram@Sun.COM 	    (uintptr_t)conn->conn_netstack) == -1) {
2437*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read netstack_t %p",
2438*9089SVasumathi.Sundaram@Sun.COM 		    conn->conn_netstack);
2439*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
2440*9089SVasumathi.Sundaram@Sun.COM 	}
2441*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%-?p %-?p %?d %?d\n", addr, conn->conn_wq,
2442*9089SVasumathi.Sundaram@Sun.COM 	    nss.netstack_stackid, conn->conn_zoneid);
2443*9089SVasumathi.Sundaram@Sun.COM 
2444*9089SVasumathi.Sundaram@Sun.COM 	if (conn->conn_af_isv6) {
2445*9089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(src_addrstr, sizeof (rem_addrstr), "%N",
2446*9089SVasumathi.Sundaram@Sun.COM 		    &conn->conn_srcv6);
2447*9089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(rem_addrstr, sizeof (rem_addrstr), "%N",
2448*9089SVasumathi.Sundaram@Sun.COM 		    &conn->conn_remv6);
2449*9089SVasumathi.Sundaram@Sun.COM 	} else {
2450*9089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(src_addrstr, sizeof (src_addrstr), "%I",
2451*9089SVasumathi.Sundaram@Sun.COM 		    V4_PART_OF_V6((conn->conn_srcv6)));
2452*9089SVasumathi.Sundaram@Sun.COM 		mdb_snprintf(rem_addrstr, sizeof (rem_addrstr), "%I",
2453*9089SVasumathi.Sundaram@Sun.COM 		    V4_PART_OF_V6((conn->conn_remv6)));
2454*9089SVasumathi.Sundaram@Sun.COM 	}
2455*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%s:%-5d\n%s:%-5d\n",
2456*9089SVasumathi.Sundaram@Sun.COM 	    src_addrstr, conn->conn_lport, rem_addrstr, conn->conn_fport);
2457*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
2458*9089SVasumathi.Sundaram@Sun.COM }
2459*9089SVasumathi.Sundaram@Sun.COM 
2460*9089SVasumathi.Sundaram@Sun.COM static void
2461*9089SVasumathi.Sundaram@Sun.COM conn_header(void)
2462*9089SVasumathi.Sundaram@Sun.COM {
2463*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%-?s %-?s %?s %?s\n%s\n%s\n",
2464*9089SVasumathi.Sundaram@Sun.COM 	    "ADDR", "WQ", "STACK", "ZONE", "SRC:PORT", "DEST:PORT");
2465*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%<u>%80s%</u>\n", "");
2466*9089SVasumathi.Sundaram@Sun.COM }
2467*9089SVasumathi.Sundaram@Sun.COM 
2468*9089SVasumathi.Sundaram@Sun.COM /*ARGSUSED*/
2469*9089SVasumathi.Sundaram@Sun.COM static int
2470*9089SVasumathi.Sundaram@Sun.COM conn_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2471*9089SVasumathi.Sundaram@Sun.COM {
2472*9089SVasumathi.Sundaram@Sun.COM 	conn_header();
2473*9089SVasumathi.Sundaram@Sun.COM 	if (flags & DCMD_ADDRSPEC) {
2474*9089SVasumathi.Sundaram@Sun.COM 		(void) conn_status_cb(addr, NULL, NULL);
2475*9089SVasumathi.Sundaram@Sun.COM 	} else {
2476*9089SVasumathi.Sundaram@Sun.COM 		if (mdb_walk("conn_status", (mdb_walk_cb_t)conn_status_cb,
2477*9089SVasumathi.Sundaram@Sun.COM 		    NULL) == -1) {
2478*9089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to walk conn_fanout");
2479*9089SVasumathi.Sundaram@Sun.COM 			return (DCMD_ERR);
2480*9089SVasumathi.Sundaram@Sun.COM 		}
2481*9089SVasumathi.Sundaram@Sun.COM 	}
2482*9089SVasumathi.Sundaram@Sun.COM 	return (DCMD_OK);
2483*9089SVasumathi.Sundaram@Sun.COM }
2484*9089SVasumathi.Sundaram@Sun.COM 
2485*9089SVasumathi.Sundaram@Sun.COM static void
2486*9089SVasumathi.Sundaram@Sun.COM conn_status_help(void)
2487*9089SVasumathi.Sundaram@Sun.COM {
2488*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("Prints conn_t structures from the following hash tables: "
2489*9089SVasumathi.Sundaram@Sun.COM 	    "\n\tips_ipcl_udp_fanout\n\tips_ipcl_bind_fanout"
2490*9089SVasumathi.Sundaram@Sun.COM 	    "\n\tips_ipcl_conn_fanout\n\tips_ipcl_proto_fanout"
2491*9089SVasumathi.Sundaram@Sun.COM 	    "\n\tips_ipcl_proto_fanout_v6\n");
2492*9089SVasumathi.Sundaram@Sun.COM }
2493*9089SVasumathi.Sundaram@Sun.COM 
2494*9089SVasumathi.Sundaram@Sun.COM static int
2495*9089SVasumathi.Sundaram@Sun.COM srcid_walk_step(mdb_walk_state_t *wsp)
2496*9089SVasumathi.Sundaram@Sun.COM {
2497*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_pwalk("srcid_list", wsp->walk_callback, wsp->walk_cbdata,
2498*9089SVasumathi.Sundaram@Sun.COM 	    wsp->walk_addr) == -1) {
2499*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("can't walk 'srcid_list'");
2500*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
2501*9089SVasumathi.Sundaram@Sun.COM 	}
2502*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
2503*9089SVasumathi.Sundaram@Sun.COM }
2504*9089SVasumathi.Sundaram@Sun.COM 
2505*9089SVasumathi.Sundaram@Sun.COM /* ARGSUSED */
2506*9089SVasumathi.Sundaram@Sun.COM static int
2507*9089SVasumathi.Sundaram@Sun.COM srcid_status_cb(uintptr_t addr, const void *walk_data,
2508*9089SVasumathi.Sundaram@Sun.COM     void *private)
2509*9089SVasumathi.Sundaram@Sun.COM {
2510*9089SVasumathi.Sundaram@Sun.COM 	srcid_map_t smp;
2511*9089SVasumathi.Sundaram@Sun.COM 
2512*9089SVasumathi.Sundaram@Sun.COM 	if (mdb_vread(&smp, sizeof (srcid_map_t), addr) == -1) {
2513*9089SVasumathi.Sundaram@Sun.COM 		mdb_warn("failed to read srcid_map at %p", addr);
2514*9089SVasumathi.Sundaram@Sun.COM 		return (WALK_ERR);
2515*9089SVasumathi.Sundaram@Sun.COM 	}
2516*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%-?p %3d %4d %6d %N\n",
2517*9089SVasumathi.Sundaram@Sun.COM 	    addr, smp.sm_srcid, smp.sm_zoneid, smp.sm_refcnt,
2518*9089SVasumathi.Sundaram@Sun.COM 	    &smp.sm_addr);
2519*9089SVasumathi.Sundaram@Sun.COM 	return (WALK_NEXT);
2520*9089SVasumathi.Sundaram@Sun.COM }
2521*9089SVasumathi.Sundaram@Sun.COM 
2522*9089SVasumathi.Sundaram@Sun.COM static void
2523*9089SVasumathi.Sundaram@Sun.COM srcid_header(void)
2524*9089SVasumathi.Sundaram@Sun.COM {
2525*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%-?s %3s %4s %6s %s\n",
2526*9089SVasumathi.Sundaram@Sun.COM 	    "ADDR", "ID", "ZONE", "REFCNT", "IPADDR");
2527*9089SVasumathi.Sundaram@Sun.COM 	mdb_printf("%<u>%80s%</u>\n", "");
2528*9089SVasumathi.Sundaram@Sun.COM }
2529*9089SVasumathi.Sundaram@Sun.COM 
2530*9089SVasumathi.Sundaram@Sun.COM /*ARGSUSED*/
2531*9089SVasumathi.Sundaram@Sun.COM static int
2532*9089SVasumathi.Sundaram@Sun.COM srcid_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2533*9089SVasumathi.Sundaram@Sun.COM {
2534*9089SVasumathi.Sundaram@Sun.COM 	srcid_header();
2535*9089SVasumathi.Sundaram@Sun.COM 	if (flags & DCMD_ADDRSPEC) {
2536*9089SVasumathi.Sundaram@Sun.COM 		(void) srcid_status_cb(addr, NULL, NULL);
2537*9089SVasumathi.Sundaram@Sun.COM 	} else {
2538*9089SVasumathi.Sundaram@Sun.COM 		if (mdb_walk("srcid", (mdb_walk_cb_t)srcid_status_cb,
2539*9089SVasumathi.Sundaram@Sun.COM 		    NULL) == -1) {
2540*9089SVasumathi.Sundaram@Sun.COM 			mdb_warn("failed to walk srcid_map");
2541*9089SVasumathi.Sundaram@Sun.COM 			return (DCMD_ERR);
2542*9089SVasumathi.Sundaram@Sun.COM 		}
2543*9089SVasumathi.Sundaram@Sun.COM 	}
2544*9089SVasumathi.Sundaram@Sun.COM 	return (DCMD_OK);
2545*9089SVasumathi.Sundaram@Sun.COM }
2546