Home | History | Annotate | Download | only in ip
      1      0     stevel /*
      2      0     stevel  * CDDL HEADER START
      3      0     stevel  *
      4      0     stevel  * The contents of this file are subject to the terms of the
      5   2546   carlsonj  * Common Development and Distribution License (the "License").
      6   2546   carlsonj  * You may not use this file except in compliance with the License.
      7      0     stevel  *
      8      0     stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0     stevel  * or http://www.opensolaris.org/os/licensing.
     10      0     stevel  * See the License for the specific language governing permissions
     11      0     stevel  * and limitations under the License.
     12      0     stevel  *
     13      0     stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0     stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0     stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0     stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0     stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0     stevel  *
     19      0     stevel  * CDDL HEADER END
     20      0     stevel  */
     21      0     stevel /*
     22   8485      Peter  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23      0     stevel  * Use is subject to license terms.
     24      0     stevel  */
     25      0     stevel 
     26      0     stevel #include <sys/types.h>
     27      0     stevel #include <sys/stropts.h>
     28      0     stevel #include <sys/stream.h>
     29      0     stevel #include <sys/socket.h>
     30      0     stevel #include <sys/avl_impl.h>
     31   9089  Vasumathi #include <net/if_types.h>
     32      0     stevel #include <net/if.h>
     33      0     stevel #include <net/route.h>
     34      0     stevel #include <netinet/in.h>
     35      0     stevel #include <netinet/ip6.h>
     36      0     stevel #include <netinet/udp.h>
     37      0     stevel #include <netinet/sctp.h>
     38      0     stevel #include <inet/mib2.h>
     39      0     stevel #include <inet/common.h>
     40      0     stevel #include <inet/ip.h>
     41      0     stevel #include <inet/ip_ire.h>
     42      0     stevel #include <inet/ip6.h>
     43      0     stevel #include <inet/ipclassifier.h>
     44      0     stevel #include <inet/mi.h>
     45      0     stevel #include <sys/squeue_impl.h>
     46   5023   carlsonj #include <sys/modhash_impl.h>
     47   5940    sowmini #include <inet/ip_ndp.h>
     48   5940    sowmini #include <inet/ip_if.h>
     49  10946   Sangeeta #include <ilb.h>
     50  10946   Sangeeta #include <ilb/ilb_impl.h>
     51  10946   Sangeeta #include <ilb/ilb_stack.h>
     52  10946   Sangeeta #include <ilb/ilb_nat.h>
     53  10946   Sangeeta #include <ilb/ilb_conn.h>
     54   5940    sowmini #include <sys/dlpi.h>
     55  11042       Erik #include <sys/zone.h>
     56      0     stevel 
     57      0     stevel #include <mdb/mdb_modapi.h>
     58      0     stevel #include <mdb/mdb_ks.h>
     59      0     stevel 
     60      0     stevel #define	ADDR_WIDTH 11
     61   5940    sowmini #define	L2MAXADDRSTRLEN	255
     62   5940    sowmini #define	MAX_SAP_LEN	255
     63   9089  Vasumathi #define	DEFCOLS		80
     64      0     stevel 
     65      0     stevel typedef struct {
     66      0     stevel 	const char *bit_name;	/* name of bit */
     67      0     stevel 	const char *bit_descr;	/* description of bit's purpose */
     68      0     stevel } bitname_t;
     69      0     stevel 
     70      0     stevel static const bitname_t squeue_states[] = {
     71      0     stevel 	{ "SQS_PROC",		"being processed" },
     72      0     stevel 	{ "SQS_WORKER",		"... by a worker thread" },
     73      0     stevel 	{ "SQS_ENTER",		"... by an squeue_enter() thread" },
     74      0     stevel 	{ "SQS_FAST",		"... in fast-path mode" },
     75      0     stevel 	{ "SQS_USER", 		"A non interrupt user" },
     76      0     stevel 	{ "SQS_BOUND",		"worker thread bound to CPU" },
     77      0     stevel 	{ "SQS_PROFILE",	"profiling enabled" },
     78      0     stevel 	{ "SQS_REENTER",	"re-entered thred" },
     79      0     stevel 	{ NULL }
     80      0     stevel };
     81      0     stevel 
     82      0     stevel typedef struct illif_walk_data {
     83      0     stevel 	ill_g_head_t ill_g_heads[MAX_G_HEADS];
     84      0     stevel 	int ill_list;
     85      0     stevel 	ill_if_t ill_if;
     86      0     stevel } illif_walk_data_t;
     87   5023   carlsonj 
     88  11042       Erik typedef struct ncec_walk_data_s {
     89  11042       Erik 	struct ndp_g_s	ncec_ip_ndp;
     90  11042       Erik 	int		ncec_hash_tbl_index;
     91  11042       Erik 	ncec_t 		ncec;
     92  11042       Erik } ncec_walk_data_t;
     93  11042       Erik 
     94  11042       Erik typedef struct ncec_cbdata_s {
     95  11042       Erik 	uintptr_t ncec_addr;
     96  11042       Erik 	int	  ncec_ipversion;
     97  11042       Erik } ncec_cbdata_t;
     98   5940    sowmini 
     99   5940    sowmini typedef struct nce_cbdata_s {
    100  11042       Erik 	int		nce_ipversion;
    101  11042       Erik 	char		nce_ill_name[LIFNAMSIZ];
    102   5940    sowmini } nce_cbdata_t;
    103   5940    sowmini 
    104   5940    sowmini typedef struct ire_cbdata_s {
    105   5940    sowmini 	int		ire_ipversion;
    106   5940    sowmini 	boolean_t	verbose;
    107   5940    sowmini } ire_cbdata_t;
    108  11042       Erik 
    109  11042       Erik typedef struct zi_cbdata_s {
    110  11042       Erik 	const char	*zone_name;
    111  11042       Erik 	ip_stack_t	*ipst;
    112  11042       Erik 	boolean_t	shared_ip_zone;
    113  11042       Erik } zi_cbdata_t;
    114   5940    sowmini 
    115   5023   carlsonj typedef struct th_walk_data {
    116   5023   carlsonj 	uint_t		thw_non_zero_only;
    117   5023   carlsonj 	boolean_t	thw_match;
    118   5023   carlsonj 	uintptr_t	thw_matchkey;
    119   5023   carlsonj 	uintptr_t	thw_ipst;
    120   5023   carlsonj 	clock_t		thw_lbolt;
    121   5023   carlsonj } th_walk_data_t;
    122      0     stevel 
    123   9089  Vasumathi typedef struct ipcl_hash_walk_data_s {
    124   9089  Vasumathi 	conn_t		*conn;
    125   9089  Vasumathi 	int		connf_tbl_index;
    126   9089  Vasumathi 	uintptr_t	hash_tbl;
    127   9089  Vasumathi 	int		hash_tbl_size;
    128   9089  Vasumathi } ipcl_hash_walk_data_t;
    129   9089  Vasumathi 
    130   9089  Vasumathi typedef struct ill_walk_data_s {
    131   9089  Vasumathi 	ill_t 		ill;
    132   9089  Vasumathi } ill_walk_data_t;
    133   9089  Vasumathi 
    134   9089  Vasumathi typedef struct ill_cbdata_s {
    135   9089  Vasumathi 	uintptr_t ill_addr;
    136   9089  Vasumathi 	int	  ill_ipversion;
    137  11042       Erik 	ip_stack_t *ill_ipst;
    138   9089  Vasumathi 	boolean_t verbose;
    139   9089  Vasumathi } ill_cbdata_t;
    140   9089  Vasumathi 
    141   9089  Vasumathi typedef struct ipif_walk_data_s {
    142   9089  Vasumathi 	ipif_t 		ipif;
    143   9089  Vasumathi } ipif_walk_data_t;
    144   9089  Vasumathi 
    145   9089  Vasumathi typedef struct ipif_cbdata_s {
    146   9089  Vasumathi 	ill_t		ill;
    147   9089  Vasumathi 	int		ipif_ipversion;
    148   9089  Vasumathi 	boolean_t 	verbose;
    149   9089  Vasumathi } ipif_cbdata_t;
    150   9089  Vasumathi 
    151   9089  Vasumathi typedef struct hash_walk_arg_s {
    152   9089  Vasumathi 	off_t	tbl_off;
    153   9089  Vasumathi 	off_t	size_off;
    154   9089  Vasumathi } hash_walk_arg_t;
    155   9089  Vasumathi 
    156   9089  Vasumathi static hash_walk_arg_t udp_hash_arg = {
    157   9089  Vasumathi 	OFFSETOF(ip_stack_t, ips_ipcl_udp_fanout),
    158   9089  Vasumathi 	OFFSETOF(ip_stack_t, ips_ipcl_udp_fanout_size)
    159   9089  Vasumathi };
    160   9089  Vasumathi 
    161   9089  Vasumathi static hash_walk_arg_t conn_hash_arg = {
    162   9089  Vasumathi 	OFFSETOF(ip_stack_t, ips_ipcl_conn_fanout),
    163   9089  Vasumathi 	OFFSETOF(ip_stack_t, ips_ipcl_conn_fanout_size)
    164   9089  Vasumathi };
    165   9089  Vasumathi 
    166   9089  Vasumathi static hash_walk_arg_t bind_hash_arg = {
    167   9089  Vasumathi 	OFFSETOF(ip_stack_t, ips_ipcl_bind_fanout),
    168   9089  Vasumathi 	OFFSETOF(ip_stack_t, ips_ipcl_bind_fanout_size)
    169   9089  Vasumathi };
    170   9089  Vasumathi 
    171   9089  Vasumathi static hash_walk_arg_t proto_hash_arg = {
    172  11042       Erik 	OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v4),
    173   9089  Vasumathi 	0
    174   9089  Vasumathi };
    175   9089  Vasumathi 
    176   9089  Vasumathi static hash_walk_arg_t proto_v6_hash_arg = {
    177   9089  Vasumathi 	OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v6),
    178   9089  Vasumathi 	0
    179   9089  Vasumathi };
    180   9089  Vasumathi 
    181   9089  Vasumathi typedef struct ip_list_walk_data_s {
    182   9089  Vasumathi 	off_t 	nextoff;
    183   9089  Vasumathi } ip_list_walk_data_t;
    184   9089  Vasumathi 
    185   9089  Vasumathi typedef struct ip_list_walk_arg_s {
    186   9089  Vasumathi 	off_t	off;
    187   9089  Vasumathi 	size_t	size;
    188   9089  Vasumathi 	off_t	nextp_off;
    189   9089  Vasumathi } ip_list_walk_arg_t;
    190   9089  Vasumathi 
    191   9089  Vasumathi static ip_list_walk_arg_t ipif_walk_arg = {
    192   9089  Vasumathi 	OFFSETOF(ill_t, ill_ipif),
    193   9089  Vasumathi 	sizeof (ipif_t),
    194   9089  Vasumathi 	OFFSETOF(ipif_t, ipif_next)
    195   9089  Vasumathi };
    196   9089  Vasumathi 
    197   9089  Vasumathi static ip_list_walk_arg_t srcid_walk_arg = {
    198   9089  Vasumathi 	OFFSETOF(ip_stack_t, ips_srcid_head),
    199   9089  Vasumathi 	sizeof (srcid_map_t),
    200   9089  Vasumathi 	OFFSETOF(srcid_map_t, sm_next)
    201   9089  Vasumathi };
    202   9089  Vasumathi 
    203      0     stevel static int iphdr(uintptr_t, uint_t, int, const mdb_arg_t *);
    204      0     stevel static int ip6hdr(uintptr_t, uint_t, int, const mdb_arg_t *);
    205   9089  Vasumathi 
    206   9089  Vasumathi static int ill(uintptr_t, uint_t, int, const mdb_arg_t *);
    207   9089  Vasumathi static void ill_help(void);
    208   9089  Vasumathi static int ill_walk_init(mdb_walk_state_t *);
    209   9089  Vasumathi static int ill_walk_step(mdb_walk_state_t *);
    210   9089  Vasumathi static int ill_format(uintptr_t, const void *, void *);
    211   9089  Vasumathi static void ill_header(boolean_t);
    212   9089  Vasumathi 
    213   9089  Vasumathi static int ipif(uintptr_t, uint_t, int, const mdb_arg_t *);
    214   9089  Vasumathi static void ipif_help(void);
    215   9089  Vasumathi static int ipif_walk_init(mdb_walk_state_t *);
    216   9089  Vasumathi static int ipif_walk_step(mdb_walk_state_t *);
    217   9089  Vasumathi static int ipif_format(uintptr_t, const void *, void *);
    218   9089  Vasumathi static void ipif_header(boolean_t);
    219   9089  Vasumathi 
    220   9089  Vasumathi static int ip_list_walk_init(mdb_walk_state_t *);
    221   9089  Vasumathi static int ip_list_walk_step(mdb_walk_state_t *);
    222   9089  Vasumathi static void ip_list_walk_fini(mdb_walk_state_t *);
    223   9089  Vasumathi static int srcid_walk_step(mdb_walk_state_t *);
    224      0     stevel 
    225   5940    sowmini static int ire_format(uintptr_t addr, const void *, void *);
    226  11042       Erik static int ncec_format(uintptr_t addr, const ncec_t *ncec, int ipversion);
    227  11042       Erik static int ncec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv);
    228  11042       Erik static int ncec_walk_step(mdb_walk_state_t *wsp);
    229  11042       Erik static int ncec_stack_walk_init(mdb_walk_state_t *wsp);
    230  11042       Erik static int ncec_stack_walk_step(mdb_walk_state_t *wsp);
    231  11042       Erik static void ncec_stack_walk_fini(mdb_walk_state_t *wsp);
    232  11042       Erik static int ncec_cb(uintptr_t addr, const ncec_walk_data_t *iw,
    233  11042       Erik     ncec_cbdata_t *id);
    234  11042       Erik static char *nce_l2_addr(const nce_t *, const ill_t *);
    235   9089  Vasumathi 
    236   9089  Vasumathi static int ipcl_hash_walk_init(mdb_walk_state_t *);
    237   9089  Vasumathi static int ipcl_hash_walk_step(mdb_walk_state_t *);
    238   9089  Vasumathi static void ipcl_hash_walk_fini(mdb_walk_state_t *);
    239   9089  Vasumathi 
    240   9089  Vasumathi static int conn_status_walk_step(mdb_walk_state_t *);
    241   9089  Vasumathi static int conn_status(uintptr_t, uint_t, int, const mdb_arg_t *);
    242   9089  Vasumathi static void conn_status_help(void);
    243   9089  Vasumathi 
    244   9089  Vasumathi static int srcid_status(uintptr_t, uint_t, int, const mdb_arg_t *);
    245  10946   Sangeeta 
    246  10946   Sangeeta static int ilb_stacks_walk_step(mdb_walk_state_t *);
    247  10946   Sangeeta static int ilb_rules_walk_init(mdb_walk_state_t *);
    248  10946   Sangeeta static int ilb_rules_walk_step(mdb_walk_state_t *);
    249  10946   Sangeeta static int ilb_servers_walk_init(mdb_walk_state_t *);
    250  10946   Sangeeta static int ilb_servers_walk_step(mdb_walk_state_t *);
    251  10946   Sangeeta static int ilb_nat_src_walk_init(mdb_walk_state_t *);
    252  10946   Sangeeta static int ilb_nat_src_walk_step(mdb_walk_state_t *);
    253  10946   Sangeeta static int ilb_conn_walk_init(mdb_walk_state_t *);
    254  10946   Sangeeta static int ilb_conn_walk_step(mdb_walk_state_t *);
    255  10946   Sangeeta static int ilb_sticky_walk_init(mdb_walk_state_t *);
    256  10946   Sangeeta static int ilb_sticky_walk_step(mdb_walk_state_t *);
    257  10946   Sangeeta static void ilb_common_walk_fini(mdb_walk_state_t *);
    258   3448   dh155122 
    259   3448   dh155122 /*
    260   3448   dh155122  * Given the kernel address of an ip_stack_t, return the stackid
    261   3448   dh155122  */
    262   3448   dh155122 static int
    263   3448   dh155122 ips_to_stackid(uintptr_t kaddr)
    264   3448   dh155122 {
    265   3448   dh155122 	ip_stack_t ipss;
    266   3448   dh155122 	netstack_t nss;
    267   3448   dh155122 
    268   3448   dh155122 	if (mdb_vread(&ipss, sizeof (ipss), kaddr) == -1) {
    269   3448   dh155122 		mdb_warn("failed to read ip_stack_t %p", kaddr);
    270   3448   dh155122 		return (0);
    271   3448   dh155122 	}
    272   3448   dh155122 	kaddr = (uintptr_t)ipss.ips_netstack;
    273   3448   dh155122 	if (mdb_vread(&nss, sizeof (nss), kaddr) == -1) {
    274   3448   dh155122 		mdb_warn("failed to read netstack_t %p", kaddr);
    275   3448   dh155122 		return (0);
    276   3448   dh155122 	}
    277   3448   dh155122 	return (nss.netstack_stackid);
    278  11042       Erik }
    279  11042       Erik 
    280  11042       Erik /* ARGSUSED */
    281  11042       Erik static int
    282  11042       Erik zone_to_ips_cb(uintptr_t addr, const void *zi_arg, void *zi_cb_arg)
    283  11042       Erik {
    284  11042       Erik 	zi_cbdata_t *zi_cb = zi_cb_arg;
    285  11042       Erik 	zone_t zone;
    286  11042       Erik 	char zone_name[ZONENAME_MAX];
    287  11042       Erik 	netstack_t ns;
    288  11042       Erik 
    289  11042       Erik 	if (mdb_vread(&zone, sizeof (zone_t), addr) == -1) {
    290  11042       Erik 		mdb_warn("can't read zone at %p", addr);
    291  11042       Erik 		return (WALK_ERR);
    292  11042       Erik 	}
    293  11042       Erik 
    294  11042       Erik 	(void) mdb_readstr(zone_name, ZONENAME_MAX, (uintptr_t)zone.zone_name);
    295  11042       Erik 
    296  11042       Erik 	if (strcmp(zi_cb->zone_name, zone_name) != 0)
    297  11042       Erik 		return (WALK_NEXT);
    298  11042       Erik 
    299  11042       Erik 	zi_cb->shared_ip_zone = (!(zone.zone_flags & ZF_NET_EXCL) &&
    300  11042       Erik 	    (strcmp(zone_name, "global") != 0));
    301  11042       Erik 
    302  11042       Erik 	if (mdb_vread(&ns, sizeof (netstack_t), (uintptr_t)zone.zone_netstack)
    303  11042       Erik 	    == -1) {
    304  11042       Erik 		mdb_warn("can't read netstack at %p", zone.zone_netstack);
    305  11042       Erik 		return (WALK_ERR);
    306  11042       Erik 	}
    307  11042       Erik 
    308  11042       Erik 	zi_cb->ipst = ns.netstack_ip;
    309  11042       Erik 	return (WALK_DONE);
    310  11042       Erik }
    311  11042       Erik 
    312  11042       Erik static ip_stack_t *
    313  11042       Erik zone_to_ips(const char *zone_name)
    314  11042       Erik {
    315  11042       Erik 	zi_cbdata_t zi_cb;
    316  11042       Erik 
    317  11042       Erik 	if (zone_name == NULL)
    318  11042       Erik 		return (NULL);
    319  11042       Erik 
    320  11042       Erik 	zi_cb.zone_name = zone_name;
    321  11042       Erik 	zi_cb.ipst = NULL;
    322  11042       Erik 	zi_cb.shared_ip_zone = B_FALSE;
    323  11042       Erik 
    324  11042       Erik 	if (mdb_walk("zone", (mdb_walk_cb_t)zone_to_ips_cb, &zi_cb) == -1) {
    325  11042       Erik 		mdb_warn("failed to walk zone");
    326  11042       Erik 		return (NULL);
    327  11042       Erik 	}
    328  11042       Erik 
    329  11042       Erik 	if (zi_cb.shared_ip_zone) {
    330  11042       Erik 		mdb_warn("%s is a Shared-IP zone, try '-s global' instead\n",
    331  11042       Erik 		    zone_name);
    332  11042       Erik 		return (NULL);
    333  11042       Erik 	}
    334  11042       Erik 
    335  11042       Erik 	if (zi_cb.ipst == NULL) {
    336  11042       Erik 		mdb_warn("failed to find zone %s\n", zone_name);
    337  11042       Erik 		return (NULL);
    338  11042       Erik 	}
    339  11042       Erik 
    340  11042       Erik 	return (zi_cb.ipst);
    341   3448   dh155122 }
    342   3448   dh155122 
    343      0     stevel int
    344   3448   dh155122 ip_stacks_walk_init(mdb_walk_state_t *wsp)
    345   3448   dh155122 {
    346   3448   dh155122 	if (mdb_layered_walk("netstack", wsp) == -1) {
    347   3448   dh155122 		mdb_warn("can't walk 'netstack'");
    348   3448   dh155122 		return (WALK_ERR);
    349   3448   dh155122 	}
    350   3448   dh155122 	return (WALK_NEXT);
    351   3448   dh155122 }
    352   3448   dh155122 
    353   3448   dh155122 int
    354   3448   dh155122 ip_stacks_walk_step(mdb_walk_state_t *wsp)
    355   3448   dh155122 {
    356   3448   dh155122 	uintptr_t kaddr;
    357   3448   dh155122 	netstack_t nss;
    358   3448   dh155122 
    359   3448   dh155122 	if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
    360   3448   dh155122 		mdb_warn("can't read netstack at %p", wsp->walk_addr);
    361   3448   dh155122 		return (WALK_ERR);
    362   3448   dh155122 	}
    363   3448   dh155122 	kaddr = (uintptr_t)nss.netstack_modules[NS_IP];
    364   3448   dh155122 
    365   3448   dh155122 	return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
    366   5023   carlsonj }
    367   5023   carlsonj 
    368   5023   carlsonj int
    369   5023   carlsonj th_hash_walk_init(mdb_walk_state_t *wsp)
    370   5023   carlsonj {
    371   5023   carlsonj 	GElf_Sym sym;
    372   5023   carlsonj 	list_node_t *next;
    373   5023   carlsonj 
    374   5023   carlsonj 	if (wsp->walk_addr == NULL) {
    375   5023   carlsonj 		if (mdb_lookup_by_obj("ip", "ip_thread_list", &sym) == 0) {
    376   5023   carlsonj 			wsp->walk_addr = sym.st_value;
    377   5023   carlsonj 		} else {
    378   5023   carlsonj 			mdb_warn("unable to locate ip_thread_list\n");
    379   5023   carlsonj 			return (WALK_ERR);
    380   5023   carlsonj 		}
    381   5023   carlsonj 	}
    382   5023   carlsonj 
    383   5023   carlsonj 	if (mdb_vread(&next, sizeof (next),
    384   5023   carlsonj 	    wsp->walk_addr + offsetof(list_t, list_head) +
    385   5023   carlsonj 	    offsetof(list_node_t, list_next)) == -1 ||
    386   5023   carlsonj 	    next == NULL) {
    387   5023   carlsonj 		mdb_warn("non-DEBUG image; cannot walk th_hash list\n");
    388   5023   carlsonj 		return (WALK_ERR);
    389   5023   carlsonj 	}
    390   5023   carlsonj 
    391   5023   carlsonj 	if (mdb_layered_walk("list", wsp) == -1) {
    392   5023   carlsonj 		mdb_warn("can't walk 'list'");
    393   5023   carlsonj 		return (WALK_ERR);
    394   5023   carlsonj 	} else {
    395   5023   carlsonj 		return (WALK_NEXT);
    396   5023   carlsonj 	}
    397   5023   carlsonj }
    398   5023   carlsonj 
    399   5023   carlsonj int
    400   5023   carlsonj th_hash_walk_step(mdb_walk_state_t *wsp)
    401   5023   carlsonj {
    402   5023   carlsonj 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
    403   5023   carlsonj 	    wsp->walk_cbdata));
    404   3448   dh155122 }
    405   3448   dh155122 
    406   3448   dh155122 /*
    407   3448   dh155122  * Called with walk_addr being the address of ips_ill_g_heads
    408   3448   dh155122  */
    409   3448   dh155122 int
    410   3448   dh155122 illif_stack_walk_init(mdb_walk_state_t *wsp)
    411      0     stevel {
    412      0     stevel 	illif_walk_data_t *iw;
    413      0     stevel 
    414   3448   dh155122 	if (wsp->walk_addr == NULL) {
    415   3448   dh155122 		mdb_warn("illif_stack supports only local walks\n");
    416      0     stevel 		return (WALK_ERR);
    417      0     stevel 	}
    418      0     stevel 
    419      0     stevel 	iw = mdb_alloc(sizeof (illif_walk_data_t), UM_SLEEP);
    420      0     stevel 
    421   3448   dh155122 	if (mdb_vread(iw->ill_g_heads, MAX_G_HEADS * sizeof (ill_g_head_t),
    422   3448   dh155122 	    wsp->walk_addr) == -1) {
    423   3448   dh155122 		mdb_warn("failed to read 'ips_ill_g_heads' at %p",
    424   3448   dh155122 		    wsp->walk_addr);
    425      0     stevel 		mdb_free(iw, sizeof (illif_walk_data_t));
    426      0     stevel 		return (WALK_ERR);
    427      0     stevel 	}
    428      0     stevel 
    429      0     stevel 	iw->ill_list = 0;
    430   3448   dh155122 	wsp->walk_addr = (uintptr_t)iw->ill_g_heads[0].ill_g_list_head;
    431      0     stevel 	wsp->walk_data = iw;
    432      0     stevel 
    433      0     stevel 	return (WALK_NEXT);
    434      0     stevel }
    435      0     stevel 
    436      0     stevel int
    437   3448   dh155122 illif_stack_walk_step(mdb_walk_state_t *wsp)
    438      0     stevel {
    439      0     stevel 	uintptr_t addr = wsp->walk_addr;
    440      0     stevel 	illif_walk_data_t *iw = wsp->walk_data;
    441      0     stevel 	int list = iw->ill_list;
    442      0     stevel 
    443      0     stevel 	if (mdb_vread(&iw->ill_if, sizeof (ill_if_t), addr) == -1) {
    444      0     stevel 		mdb_warn("failed to read ill_if_t at %p", addr);
    445      0     stevel 		return (WALK_ERR);
    446      0     stevel 	}
    447      0     stevel 
    448      0     stevel 	wsp->walk_addr = (uintptr_t)iw->ill_if.illif_next;
    449      0     stevel 
    450   3448   dh155122 	if (wsp->walk_addr ==
    451   3448   dh155122 	    (uintptr_t)iw->ill_g_heads[list].ill_g_list_head) {
    452      0     stevel 
    453      0     stevel 		if (++list >= MAX_G_HEADS)
    454      0     stevel 			return (WALK_DONE);
    455      0     stevel 
    456      0     stevel 		iw->ill_list = list;
    457   3448   dh155122 		wsp->walk_addr =
    458   3448   dh155122 		    (uintptr_t)iw->ill_g_heads[list].ill_g_list_head;
    459      0     stevel 		return (WALK_NEXT);
    460      0     stevel 	}
    461      0     stevel 
    462      0     stevel 	return (wsp->walk_callback(addr, iw, wsp->walk_cbdata));
    463      0     stevel }
    464      0     stevel 
    465      0     stevel void
    466   3448   dh155122 illif_stack_walk_fini(mdb_walk_state_t *wsp)
    467      0     stevel {
    468      0     stevel 	mdb_free(wsp->walk_data, sizeof (illif_walk_data_t));
    469      0     stevel }
    470      0     stevel 
    471      0     stevel typedef struct illif_cbdata {
    472      0     stevel 	uint_t ill_flags;
    473      0     stevel 	uintptr_t ill_addr;
    474      0     stevel 	int ill_printlist;	/* list to be printed (MAX_G_HEADS for all) */
    475      0     stevel 	boolean_t ill_printed;
    476      0     stevel } illif_cbdata_t;
    477      0     stevel 
    478      0     stevel static int
    479      0     stevel illif_cb(uintptr_t addr, const illif_walk_data_t *iw, illif_cbdata_t *id)
    480      0     stevel {
    481      0     stevel 	const char *version;
    482      0     stevel 
    483      0     stevel 	if (id->ill_printlist < MAX_G_HEADS &&
    484      0     stevel 	    id->ill_printlist != iw->ill_list)
    485      0     stevel 		return (WALK_NEXT);
    486      0     stevel 
    487      0     stevel 	if (id->ill_flags & DCMD_ADDRSPEC && id->ill_addr != addr)
    488      0     stevel 		return (WALK_NEXT);
    489      0     stevel 
    490      0     stevel 	if (id->ill_flags & DCMD_PIPE_OUT) {
    491      0     stevel 		mdb_printf("%p\n", addr);
    492      0     stevel 		return (WALK_NEXT);
    493      0     stevel 	}
    494      0     stevel 
    495      0     stevel 	switch (iw->ill_list) {
    496      0     stevel 		case IP_V4_G_HEAD:	version = "v4";	break;
    497      0     stevel 		case IP_V6_G_HEAD:	version = "v6";	break;
    498      0     stevel 		default:		version = "??"; break;
    499      0     stevel 	}
    500      0     stevel 
    501      0     stevel 	mdb_printf("%?p %2s %?p %10d %?p %s\n",
    502      0     stevel 	    addr, version, addr + offsetof(ill_if_t, illif_avl_by_ppa),
    503      0     stevel 	    iw->ill_if.illif_avl_by_ppa.avl_numnodes,
    504      0     stevel 	    iw->ill_if.illif_ppa_arena, iw->ill_if.illif_name);
    505      0     stevel 
    506      0     stevel 	id->ill_printed = TRUE;
    507      0     stevel 
    508   3448   dh155122 	return (WALK_NEXT);
    509   3448   dh155122 }
    510   3448   dh155122 
    511   3448   dh155122 int
    512   5940    sowmini ip_stacks_common_walk_init(mdb_walk_state_t *wsp)
    513   3448   dh155122 {
    514   3448   dh155122 	if (mdb_layered_walk("ip_stacks", wsp) == -1) {
    515   3448   dh155122 		mdb_warn("can't walk 'ip_stacks'");
    516   3448   dh155122 		return (WALK_ERR);
    517   3448   dh155122 	}
    518   3448   dh155122 
    519   3448   dh155122 	return (WALK_NEXT);
    520   3448   dh155122 }
    521   3448   dh155122 
    522   3448   dh155122 int
    523   3448   dh155122 illif_walk_step(mdb_walk_state_t *wsp)
    524   3448   dh155122 {
    525   3448   dh155122 	uintptr_t kaddr;
    526   3448   dh155122 
    527   3448   dh155122 	kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ill_g_heads);
    528   3448   dh155122 
    529   3448   dh155122 	if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) {
    530   3448   dh155122 		mdb_warn("can't read ips_ip_cache_table at %p", kaddr);
    531   3448   dh155122 		return (WALK_ERR);
    532   3448   dh155122 	}
    533   3448   dh155122 
    534   3448   dh155122 	if (mdb_pwalk("illif_stack", wsp->walk_callback,
    535   5023   carlsonj 	    wsp->walk_cbdata, kaddr) == -1) {
    536   3448   dh155122 		mdb_warn("couldn't walk 'illif_stack' for ips_ill_g_heads %p",
    537   3448   dh155122 		    kaddr);
    538   3448   dh155122 		return (WALK_ERR);
    539   3448   dh155122 	}
    540      0     stevel 	return (WALK_NEXT);
    541      0     stevel }
    542      0     stevel 
    543      0     stevel int
    544      0     stevel illif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    545      0     stevel {
    546      0     stevel 	illif_cbdata_t id;
    547      0     stevel 	ill_if_t ill_if;
    548      0     stevel 	const char *opt_P = NULL;
    549      0     stevel 	int printlist = MAX_G_HEADS;
    550      0     stevel 
    551      0     stevel 	if (mdb_getopts(argc, argv,
    552      0     stevel 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
    553      0     stevel 		return (DCMD_USAGE);
    554      0     stevel 
    555      0     stevel 	if (opt_P != NULL) {
    556      0     stevel 		if (strcmp("v4", opt_P) == 0) {
    557      0     stevel 			printlist = IP_V4_G_HEAD;
    558      0     stevel 		} else if (strcmp("v6", opt_P) == 0) {
    559      0     stevel 			printlist = IP_V6_G_HEAD;
    560      0     stevel 		} else {
    561      0     stevel 			mdb_warn("invalid protocol '%s'\n", opt_P);
    562      0     stevel 			return (DCMD_USAGE);
    563      0     stevel 		}
    564      0     stevel 	}
    565      0     stevel 
    566      0     stevel 	if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) {
    567      0     stevel 		mdb_printf("%<u>%?s %2s %?s %10s %?s %-10s%</u>\n",
    568      0     stevel 		    "ADDR", "IP", "AVLADDR", "NUMNODES", "ARENA", "NAME");
    569      0     stevel 	}
    570      0     stevel 
    571      0     stevel 	id.ill_flags = flags;
    572      0     stevel 	id.ill_addr = addr;
    573      0     stevel 	id.ill_printlist = printlist;
    574      0     stevel 	id.ill_printed = FALSE;
    575      0     stevel 
    576      0     stevel 	if (mdb_walk("illif", (mdb_walk_cb_t)illif_cb, &id) == -1) {
    577      0     stevel 		mdb_warn("can't walk ill_if_t structures");
    578      0     stevel 		return (DCMD_ERR);
    579      0     stevel 	}
    580      0     stevel 
    581      0     stevel 	if (!(flags & DCMD_ADDRSPEC) || opt_P != NULL || id.ill_printed)
    582      0     stevel 		return (DCMD_OK);
    583      0     stevel 
    584      0     stevel 	/*
    585      0     stevel 	 * If an address is specified and the walk doesn't find it,
    586      0     stevel 	 * print it anyway.
    587      0     stevel 	 */
    588      0     stevel 	if (mdb_vread(&ill_if, sizeof (ill_if_t), addr) == -1) {
    589      0     stevel 		mdb_warn("failed to read ill_if_t at %p", addr);
    590      0     stevel 		return (DCMD_ERR);
    591      0     stevel 	}
    592      0     stevel 
    593      0     stevel 	mdb_printf("%?p %2s %?p %10d %?p %s\n",
    594      0     stevel 	    addr, "??", addr + offsetof(ill_if_t, illif_avl_by_ppa),
    595      0     stevel 	    ill_if.illif_avl_by_ppa.avl_numnodes,
    596      0     stevel 	    ill_if.illif_ppa_arena, ill_if.illif_name);
    597      0     stevel 
    598      0     stevel 	return (DCMD_OK);
    599      0     stevel }
    600      0     stevel 
    601      0     stevel static void
    602      0     stevel illif_help(void)
    603      0     stevel {
    604      0     stevel 	mdb_printf("Options:\n");
    605      0     stevel 	mdb_printf("\t-P v4 | v6"
    606      0     stevel 	    "\tfilter interface structures for the specified protocol\n");
    607      0     stevel }
    608      0     stevel 
    609      0     stevel int
    610  11042       Erik nce_walk_init(mdb_walk_state_t *wsp)
    611  11042       Erik {
    612  11042       Erik 	if (mdb_layered_walk("nce_cache", wsp) == -1) {
    613  11042       Erik 		mdb_warn("can't walk 'nce_cache'");
    614  11042       Erik 		return (WALK_ERR);
    615  11042       Erik 	}
    616  11042       Erik 
    617  11042       Erik 	return (WALK_NEXT);
    618  11042       Erik }
    619  11042       Erik 
    620  11042       Erik int
    621  11042       Erik nce_walk_step(mdb_walk_state_t *wsp)
    622  11042       Erik {
    623  11042       Erik 	nce_t nce;
    624  11042       Erik 
    625  11042       Erik 	if (mdb_vread(&nce, sizeof (nce), wsp->walk_addr) == -1) {
    626  11042       Erik 		mdb_warn("can't read nce at %p", wsp->walk_addr);
    627  11042       Erik 		return (WALK_ERR);
    628  11042       Erik 	}
    629  11042       Erik 
    630  11042       Erik 	return (wsp->walk_callback(wsp->walk_addr, &nce, wsp->walk_cbdata));
    631  11042       Erik }
    632  11042       Erik 
    633  11042       Erik static int
    634  11042       Erik nce_format(uintptr_t addr, const nce_t *ncep, void *nce_cb_arg)
    635  11042       Erik {
    636  11042       Erik 	nce_cbdata_t *nce_cb = nce_cb_arg;
    637  11042       Erik 	ill_t ill;
    638  11042       Erik 	char ill_name[LIFNAMSIZ];
    639  11042       Erik 	ncec_t ncec;
    640  11042       Erik 
    641  11042       Erik 	if (mdb_vread(&ncec, sizeof (ncec),
    642  11042       Erik 	    (uintptr_t)ncep->nce_common) == -1) {
    643  11042       Erik 		mdb_warn("can't read ncec at %p", ncep->nce_common);
    644  11042       Erik 		return (WALK_NEXT);
    645  11042       Erik 	}
    646  11042       Erik 	if (nce_cb->nce_ipversion != 0 &&
    647  11042       Erik 	    ncec.ncec_ipversion != nce_cb->nce_ipversion)
    648  11042       Erik 		return (WALK_NEXT);
    649  11042       Erik 
    650  11042       Erik 	if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ncep->nce_ill) == -1) {
    651  11042       Erik 		mdb_snprintf(ill_name, sizeof (ill_name), "--");
    652  11042       Erik 	} else {
    653  11042       Erik 		(void) mdb_readstr(ill_name,
    654  11042       Erik 		    MIN(LIFNAMSIZ, ill.ill_name_length),
    655  11042       Erik 		    (uintptr_t)ill.ill_name);
    656  11042       Erik 	}
    657  11042       Erik 
    658  11042       Erik 	if (nce_cb->nce_ill_name[0] != '\0' &&
    659  11042       Erik 	    strncmp(nce_cb->nce_ill_name, ill_name, LIFNAMSIZ) != 0)
    660  11042       Erik 		return (WALK_NEXT);
    661  11042       Erik 
    662  11042       Erik 	if (ncec.ncec_ipversion == IPV6_VERSION) {
    663  11042       Erik 
    664  11042       Erik 		mdb_printf("%?p %5s %-18s %?p %6d %N\n",
    665  11042       Erik 		    addr, ill_name,
    666  11042       Erik 		    nce_l2_addr(ncep, &ill),
    667  11042       Erik 		    ncep->nce_fp_mp,
    668  11042       Erik 		    ncep->nce_refcnt,
    669  11042       Erik 		    &ncep->nce_addr);
    670  11042       Erik 
    671  11042       Erik 	} else {
    672  11042       Erik 		struct in_addr nceaddr;
    673  11042       Erik 
    674  11042       Erik 		IN6_V4MAPPED_TO_INADDR(&ncep->nce_addr, &nceaddr);
    675  11042       Erik 		mdb_printf("%?p %5s %-18s %?p %6d %I\n",
    676  11042       Erik 		    addr, ill_name,
    677  11042       Erik 		    nce_l2_addr(ncep, &ill),
    678  11042       Erik 		    ncep->nce_fp_mp,
    679  11042       Erik 		    ncep->nce_refcnt,
    680  11042       Erik 		    nceaddr.s_addr);
    681  11042       Erik 	}
    682  11042       Erik 
    683  11042       Erik 	return (WALK_NEXT);
    684  11042       Erik }
    685  11042       Erik 
    686  11042       Erik int
    687  11042       Erik dce_walk_init(mdb_walk_state_t *wsp)
    688  11042       Erik {
    689  11042       Erik 	wsp->walk_data = (void *)wsp->walk_addr;
    690  11042       Erik 
    691  11042       Erik 	if (mdb_layered_walk("dce_cache", wsp) == -1) {
    692  11042       Erik 		mdb_warn("can't walk 'dce_cache'");
    693  11042       Erik 		return (WALK_ERR);
    694  11042       Erik 	}
    695  11042       Erik 
    696  11042       Erik 	return (WALK_NEXT);
    697  11042       Erik }
    698  11042       Erik 
    699  11042       Erik int
    700  11042       Erik dce_walk_step(mdb_walk_state_t *wsp)
    701  11042       Erik {
    702  11042       Erik 	dce_t dce;
    703  11042       Erik 
    704  11042       Erik 	if (mdb_vread(&dce, sizeof (dce), wsp->walk_addr) == -1) {
    705  11042       Erik 		mdb_warn("can't read dce at %p", wsp->walk_addr);
    706  11042       Erik 		return (WALK_ERR);
    707  11042       Erik 	}
    708  11042       Erik 
    709  11042       Erik 	/* If ip_stack_t is specified, skip DCEs that don't belong to it. */
    710  11042       Erik 	if ((wsp->walk_data != NULL) && (wsp->walk_data != dce.dce_ipst))
    711  11042       Erik 		return (WALK_NEXT);
    712  11042       Erik 
    713  11042       Erik 	return (wsp->walk_callback(wsp->walk_addr, &dce, wsp->walk_cbdata));
    714  11042       Erik }
    715  11042       Erik 
    716  11042       Erik int
    717      0     stevel ire_walk_init(mdb_walk_state_t *wsp)
    718      0     stevel {
    719  11042       Erik 	wsp->walk_data = (void *)wsp->walk_addr;
    720  11042       Erik 
    721      0     stevel 	if (mdb_layered_walk("ire_cache", wsp) == -1) {
    722      0     stevel 		mdb_warn("can't walk 'ire_cache'");
    723      0     stevel 		return (WALK_ERR);
    724      0     stevel 	}
    725      0     stevel 
    726      0     stevel 	return (WALK_NEXT);
    727      0     stevel }
    728      0     stevel 
    729      0     stevel int
    730      0     stevel ire_walk_step(mdb_walk_state_t *wsp)
    731      0     stevel {
    732      0     stevel 	ire_t ire;
    733      0     stevel 
    734      0     stevel 	if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) {
    735      0     stevel 		mdb_warn("can't read ire at %p", wsp->walk_addr);
    736      0     stevel 		return (WALK_ERR);
    737      0     stevel 	}
    738      0     stevel 
    739  11042       Erik 	/* If ip_stack_t is specified, skip IREs that don't belong to it. */
    740  11042       Erik 	if ((wsp->walk_data != NULL) && (wsp->walk_data != ire.ire_ipst))
    741  11042       Erik 		return (WALK_NEXT);
    742  11042       Erik 
    743      0     stevel 	return (wsp->walk_callback(wsp->walk_addr, &ire, wsp->walk_cbdata));
    744   3448   dh155122 }
    745   3448   dh155122 
    746   3448   dh155122 /* ARGSUSED */
    747   3448   dh155122 int
    748   3448   dh155122 ire_next_walk_init(mdb_walk_state_t *wsp)
    749   3448   dh155122 {
    750   3448   dh155122 	return (WALK_NEXT);
    751   3448   dh155122 }
    752   3448   dh155122 
    753   3448   dh155122 int
    754   3448   dh155122 ire_next_walk_step(mdb_walk_state_t *wsp)
    755   3448   dh155122 {
    756   3448   dh155122 	ire_t ire;
    757   3448   dh155122 	int status;
    758   3448   dh155122 
    759   3448   dh155122 
    760   3448   dh155122 	if (wsp->walk_addr == NULL)
    761   3448   dh155122 		return (WALK_DONE);
    762   3448   dh155122 
    763   3448   dh155122 	if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) {
    764   3448   dh155122 		mdb_warn("can't read ire at %p", wsp->walk_addr);
    765   3448   dh155122 		return (WALK_ERR);
    766   3448   dh155122 	}
    767   3448   dh155122 	status = wsp->walk_callback(wsp->walk_addr, &ire,
    768   3448   dh155122 	    wsp->walk_cbdata);
    769   3448   dh155122 
    770   3448   dh155122 	if (status != WALK_NEXT)
    771   3448   dh155122 		return (status);
    772   3448   dh155122 
    773   3448   dh155122 	wsp->walk_addr = (uintptr_t)ire.ire_next;
    774   3448   dh155122 	return (status);
    775   3448   dh155122 }
    776   3448   dh155122 
    777      0     stevel static int
    778   5940    sowmini ire_format(uintptr_t addr, const void *ire_arg, void *ire_cb_arg)
    779      0     stevel {
    780   5940    sowmini 	const ire_t *irep = ire_arg;
    781   5940    sowmini 	ire_cbdata_t *ire_cb = ire_cb_arg;
    782   5940    sowmini 	boolean_t verbose = ire_cb->verbose;
    783  11042       Erik 	ill_t ill;
    784  11042       Erik 	char ill_name[LIFNAMSIZ];
    785  11042       Erik 	boolean_t condemned = irep->ire_generation == IRE_GENERATION_CONDEMNED;
    786   5940    sowmini 
    787      0     stevel 	static const mdb_bitmask_t tmasks[] = {
    788      0     stevel 		{ "BROADCAST",	IRE_BROADCAST,		IRE_BROADCAST	},
    789      0     stevel 		{ "DEFAULT",	IRE_DEFAULT,		IRE_DEFAULT	},
    790      0     stevel 		{ "LOCAL",	IRE_LOCAL,		IRE_LOCAL	},
    791      0     stevel 		{ "LOOPBACK",	IRE_LOOPBACK,		IRE_LOOPBACK	},
    792      0     stevel 		{ "PREFIX",	IRE_PREFIX,		IRE_PREFIX	},
    793  11042       Erik 		{ "MULTICAST",	IRE_MULTICAST,		IRE_MULTICAST	},
    794  11042       Erik 		{ "NOROUTE",	IRE_NOROUTE,		IRE_NOROUTE	},
    795      0     stevel 		{ "IF_NORESOLVER", IRE_IF_NORESOLVER,	IRE_IF_NORESOLVER },
    796      0     stevel 		{ "IF_RESOLVER", IRE_IF_RESOLVER,	IRE_IF_RESOLVER	},
    797  11042       Erik 		{ "IF_CLONE",	IRE_IF_CLONE,		IRE_IF_CLONE	},
    798      0     stevel 		{ "HOST",	IRE_HOST,		IRE_HOST	},
    799      0     stevel 		{ NULL,		0,			0		}
    800      0     stevel 	};
    801      0     stevel 
    802      0     stevel 	static const mdb_bitmask_t fmasks[] = {
    803      0     stevel 		{ "UP",		RTF_UP,			RTF_UP		},
    804      0     stevel 		{ "GATEWAY",	RTF_GATEWAY,		RTF_GATEWAY	},
    805      0     stevel 		{ "HOST",	RTF_HOST,		RTF_HOST	},
    806      0     stevel 		{ "REJECT",	RTF_REJECT,		RTF_REJECT	},
    807      0     stevel 		{ "DYNAMIC",	RTF_DYNAMIC,		RTF_DYNAMIC	},
    808      0     stevel 		{ "MODIFIED",	RTF_MODIFIED,		RTF_MODIFIED	},
    809      0     stevel 		{ "DONE",	RTF_DONE,		RTF_DONE	},
    810      0     stevel 		{ "MASK",	RTF_MASK,		RTF_MASK	},
    811      0     stevel 		{ "CLONING",	RTF_CLONING,		RTF_CLONING	},
    812      0     stevel 		{ "XRESOLVE",	RTF_XRESOLVE,		RTF_XRESOLVE	},
    813      0     stevel 		{ "LLINFO",	RTF_LLINFO,		RTF_LLINFO	},
    814      0     stevel 		{ "STATIC",	RTF_STATIC,		RTF_STATIC	},
    815      0     stevel 		{ "BLACKHOLE",	RTF_BLACKHOLE,		RTF_BLACKHOLE	},
    816      0     stevel 		{ "PRIVATE",	RTF_PRIVATE,		RTF_PRIVATE	},
    817      0     stevel 		{ "PROTO2",	RTF_PROTO2,		RTF_PROTO2	},
    818      0     stevel 		{ "PROTO1",	RTF_PROTO1,		RTF_PROTO1	},
    819      0     stevel 		{ "MULTIRT",	RTF_MULTIRT,		RTF_MULTIRT	},
    820      0     stevel 		{ "SETSRC",	RTF_SETSRC,		RTF_SETSRC	},
    821  11042       Erik 		{ "INDIRECT",	RTF_INDIRECT,		RTF_INDIRECT	},
    822      0     stevel 		{ NULL,		0,			0		}
    823      0     stevel 	};
    824      0     stevel 
    825   5940    sowmini 	if (ire_cb->ire_ipversion != 0 &&
    826   5940    sowmini 	    irep->ire_ipversion != ire_cb->ire_ipversion)
    827   5940    sowmini 		return (WALK_NEXT);
    828   5940    sowmini 
    829  11042       Erik 	if (mdb_vread(&ill, sizeof (ill), (uintptr_t)irep->ire_ill) == -1) {
    830  11042       Erik 		mdb_snprintf(ill_name, sizeof (ill_name), "--");
    831  11042       Erik 	} else {
    832  11042       Erik 		(void) mdb_readstr(ill_name,
    833  11042       Erik 		    MIN(LIFNAMSIZ, ill.ill_name_length),
    834  11042       Erik 		    (uintptr_t)ill.ill_name);
    835  11042       Erik 	}
    836  11042       Erik 
    837   5940    sowmini 	if (irep->ire_ipversion == IPV6_VERSION && verbose) {
    838      0     stevel 
    839  11042       Erik 		mdb_printf("%<b>%?p%</b>%3s %40N <%hb%s>\n"
    840  11042       Erik 		    "%?s %40N\n"
    841  11042       Erik 		    "%?s %40d %4d <%hb> %s\n",
    842  11042       Erik 		    addr, condemned ? "(C)" : "", &irep->ire_setsrc_addr_v6,
    843  11042       Erik 		    irep->ire_type, tmasks,
    844  11042       Erik 		    (irep->ire_testhidden ? ", HIDDEN" : ""),
    845  11042       Erik 		    "", &irep->ire_addr_v6,
    846   3448   dh155122 		    "", ips_to_stackid((uintptr_t)irep->ire_ipst),
    847   3448   dh155122 		    irep->ire_zoneid,
    848  11042       Erik 		    irep->ire_flags, fmasks, ill_name);
    849      0     stevel 
    850   5940    sowmini 	} else if (irep->ire_ipversion == IPV6_VERSION) {
    851      0     stevel 
    852  11042       Erik 		mdb_printf("%?p%3s %30N %30N %5d %4d %s\n",
    853  11042       Erik 		    addr, condemned ? "(C)" : "", &irep->ire_setsrc_addr_v6,
    854   3448   dh155122 		    &irep->ire_addr_v6,
    855   3448   dh155122 		    ips_to_stackid((uintptr_t)irep->ire_ipst),
    856  11042       Erik 		    irep->ire_zoneid, ill_name);
    857      0     stevel 
    858   5940    sowmini 	} else if (verbose) {
    859      0     stevel 
    860  11042       Erik 		mdb_printf("%<b>%?p%</b>%3s %40I <%hb%s>\n"
    861  11042       Erik 		    "%?s %40I\n"
    862  11042       Erik 		    "%?s %40d %4d <%hb> %s\n",
    863  11042       Erik 		    addr, condemned ? "(C)" : "", irep->ire_setsrc_addr,
    864  11042       Erik 		    irep->ire_type, tmasks,
    865  11042       Erik 		    (irep->ire_testhidden ? ", HIDDEN" : ""),
    866  11042       Erik 		    "", irep->ire_addr,
    867   3448   dh155122 		    "", ips_to_stackid((uintptr_t)irep->ire_ipst),
    868  11042       Erik 		    irep->ire_zoneid, irep->ire_flags, fmasks, ill_name);
    869      0     stevel 
    870      0     stevel 	} else {
    871      0     stevel 
    872  11042       Erik 		mdb_printf("%?p%3s %30I %30I %5d %4d %s\n", addr,
    873  11042       Erik 		    condemned ? "(C)" : "", irep->ire_setsrc_addr,
    874   3448   dh155122 		    irep->ire_addr, ips_to_stackid((uintptr_t)irep->ire_ipst),
    875  11042       Erik 		    irep->ire_zoneid, ill_name);
    876      0     stevel 	}
    877      0     stevel 
    878      0     stevel 	return (WALK_NEXT);
    879      0     stevel }
    880      0     stevel 
    881      0     stevel /*
    882      0     stevel  * There are faster ways to do this.  Given the interactive nature of this
    883      0     stevel  * use I don't think its worth much effort.
    884      0     stevel  */
    885      0     stevel static unsigned short
    886      0     stevel ipcksum(void *p, int len)
    887      0     stevel {
    888      0     stevel 	int32_t	sum = 0;
    889      0     stevel 
    890      0     stevel 	while (len > 1) {
    891      0     stevel 		/* alignment */
    892      0     stevel 		sum += *(uint16_t *)p;
    893      0     stevel 		p = (char *)p + sizeof (uint16_t);
    894      0     stevel 		if (sum & 0x80000000)
    895      0     stevel 			sum = (sum & 0xFFFF) + (sum >> 16);
    896      0     stevel 		len -= 2;
    897      0     stevel 	}
    898      0     stevel 
    899      0     stevel 	if (len)
    900      0     stevel 		sum += (uint16_t)*(unsigned char *)p;
    901      0     stevel 
    902      0     stevel 	while (sum >> 16)
    903      0     stevel 		sum = (sum & 0xFFFF) + (sum >> 16);
    904      0     stevel 
    905      0     stevel 	return (~sum);
    906      0     stevel }
    907      0     stevel 
    908      0     stevel static const mdb_bitmask_t tcp_flags[] = {
    909      0     stevel 	{ "SYN",	TH_SYN,		TH_SYN	},
    910      0     stevel 	{ "ACK",	TH_ACK,		TH_ACK	},
    911      0     stevel 	{ "FIN",	TH_FIN,		TH_FIN	},
    912      0     stevel 	{ "RST",	TH_RST,		TH_RST	},
    913      0     stevel 	{ "PSH",	TH_PUSH,	TH_PUSH	},
    914      0     stevel 	{ "ECE",	TH_ECE,		TH_ECE	},
    915      0     stevel 	{ "CWR",	TH_CWR,		TH_CWR	},
    916      0     stevel 	{ NULL,		0,		0	}
    917      0     stevel };
    918      0     stevel 
    919      0     stevel static void
    920      0     stevel tcphdr_print(struct tcphdr *tcph)
    921      0     stevel {
    922      0     stevel 	in_port_t	sport, dport;
    923      0     stevel 	tcp_seq		seq, ack;
    924      0     stevel 	uint16_t	win, urp;
    925      0     stevel 
    926      0     stevel 	mdb_printf("%<b>TCP header%</b>\n");
    927      0     stevel 
    928      0     stevel 	mdb_nhconvert(&sport, &tcph->th_sport, sizeof (sport));
    929      0     stevel 	mdb_nhconvert(&dport, &tcph->th_dport, sizeof (dport));
    930      0     stevel 	mdb_nhconvert(&seq, &tcph->th_seq, sizeof (seq));
    931      0     stevel 	mdb_nhconvert(&ack, &tcph->th_ack, sizeof (ack));
    932      0     stevel 	mdb_nhconvert(&win, &tcph->th_win, sizeof (win));
    933      0     stevel 	mdb_nhconvert(&urp, &tcph->th_urp, sizeof (urp));
    934      0     stevel 
    935      0     stevel 	mdb_printf("%<u>%6s %6s %10s %10s %4s %5s %5s %5s %-15s%</u>\n",
    936      0     stevel 	    "SPORT", "DPORT", "SEQ", "ACK", "HLEN", "WIN", "CSUM", "URP",
    937      0     stevel 	    "FLAGS");
    938      0     stevel 	mdb_printf("%6hu %6hu %10u %10u %4d %5hu %5hu %5hu <%b>\n",
    939      0     stevel 	    sport, dport, seq, ack, tcph->th_off << 2, win,
    940      0     stevel 	    tcph->th_sum, urp, tcph->th_flags, tcp_flags);
    941      0     stevel 	mdb_printf("0x%04x 0x%04x 0x%08x 0x%08x\n\n",
    942      0     stevel 	    sport, dport, seq, ack);
    943      0     stevel }
    944      0     stevel 
    945      0     stevel /* ARGSUSED */
    946      0     stevel static int
    947      0     stevel tcphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av)
    948      0     stevel {
    949      0     stevel 	struct tcphdr	tcph;
    950      0     stevel 
    951      0     stevel 	if (!(flags & DCMD_ADDRSPEC))
    952      0     stevel 		return (DCMD_USAGE);
    953      0     stevel 
    954      0     stevel 	if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) {
    955      0     stevel 		mdb_warn("failed to read TCP header at %p", addr);
    956      0     stevel 		return (DCMD_ERR);
    957      0     stevel 	}
    958      0     stevel 	tcphdr_print(&tcph);
    959      0     stevel 	return (DCMD_OK);
    960      0     stevel }
    961      0     stevel 
    962      0     stevel static void
    963      0     stevel udphdr_print(struct udphdr *udph)
    964      0     stevel {
    965      0     stevel 	in_port_t	sport, dport;
    966      0     stevel 	uint16_t	hlen;
    967      0     stevel 
    968      0     stevel 	mdb_printf("%<b>UDP header%</b>\n");
    969      0     stevel 
    970      0     stevel 	mdb_nhconvert(&sport, &udph->uh_sport, sizeof (sport));
    971      0     stevel 	mdb_nhconvert(&dport, &udph->uh_dport, sizeof (dport));
    972      0     stevel 	mdb_nhconvert(&hlen, &udph->uh_ulen, sizeof (hlen));
    973      0     stevel 
    974      0     stevel 	mdb_printf("%<u>%14s %14s %5s %6s%</u>\n",
    975      0     stevel 	    "SPORT", "DPORT", "LEN", "CSUM");
    976      0     stevel 	mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %5hu 0x%04hx\n\n", sport, sport,
    977      0     stevel 	    dport, dport, hlen, udph->uh_sum);
    978      0     stevel }
    979      0     stevel 
    980      0     stevel /* ARGSUSED */
    981      0     stevel static int
    982      0     stevel udphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av)
    983      0     stevel {
    984      0     stevel 	struct udphdr	udph;
    985      0     stevel 
    986      0     stevel 	if (!(flags & DCMD_ADDRSPEC))
    987      0     stevel 		return (DCMD_USAGE);
    988      0     stevel 
    989      0     stevel 	if (mdb_vread(&udph, sizeof (udph), addr) == -1) {
    990      0     stevel 		mdb_warn("failed to read UDP header at %p", addr);
    991      0     stevel 		return (DCMD_ERR);
    992      0     stevel 	}
    993      0     stevel 	udphdr_print(&udph);
    994      0     stevel 	return (DCMD_OK);
    995      0     stevel }
    996      0     stevel 
    997      0     stevel static void
    998      0     stevel sctphdr_print(sctp_hdr_t *sctph)
    999      0     stevel {
   1000      0     stevel 	in_port_t sport, dport;
   1001      0     stevel 
   1002      0     stevel 	mdb_printf("%<b>SCTP header%</b>\n");
   1003      0     stevel 	mdb_nhconvert(&sport, &sctph->sh_sport, sizeof (sport));
   1004      0     stevel 	mdb_nhconvert(&dport, &sctph->sh_dport, sizeof (dport));
   1005      0     stevel 
   1006      0     stevel 	mdb_printf("%<u>%14s %14s %10s %10s%</u>\n",
   1007      0     stevel 	    "SPORT", "DPORT", "VTAG", "CHKSUM");
   1008      0     stevel 	mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %10u 0x%08x\n\n", sport, sport,
   1009      0     stevel 	    dport, dport, sctph->sh_verf, sctph->sh_chksum);
   1010      0     stevel }
   1011      0     stevel 
   1012      0     stevel /* ARGSUSED */
   1013      0     stevel static int
   1014      0     stevel sctphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av)
   1015      0     stevel {
   1016      0     stevel 	sctp_hdr_t sctph;
   1017      0     stevel 
   1018      0     stevel 	if (!(flags & DCMD_ADDRSPEC))
   1019      0     stevel 		return (DCMD_USAGE);
   1020      0     stevel 
   1021      0     stevel 	if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) {
   1022      0     stevel 		mdb_warn("failed to read SCTP header at %p", addr);
   1023      0     stevel 		return (DCMD_ERR);
   1024      0     stevel 	}
   1025      0     stevel 
   1026      0     stevel 	sctphdr_print(&sctph);
   1027      0     stevel 	return (DCMD_OK);
   1028      0     stevel }
   1029      0     stevel 
   1030      0     stevel static int
   1031      0     stevel transport_hdr(int proto, uintptr_t addr)
   1032      0     stevel {
   1033      0     stevel 	mdb_printf("\n");
   1034      0     stevel 	switch (proto) {
   1035      0     stevel 	case IPPROTO_TCP: {
   1036      0     stevel 		struct tcphdr tcph;
   1037      0     stevel 
   1038      0     stevel 		if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) {
   1039      0     stevel 			mdb_warn("failed to read TCP header at %p", addr);
   1040      0     stevel 			return (DCMD_ERR);
   1041      0     stevel 		}
   1042      0     stevel 		tcphdr_print(&tcph);
   1043      0     stevel 		break;
   1044      0     stevel 	}
   1045      0     stevel 	case IPPROTO_UDP:  {
   1046      0     stevel 		struct udphdr udph;
   1047      0     stevel 
   1048      0     stevel 		if (mdb_vread(&udph, sizeof (udph), addr) == -1) {
   1049      0     stevel 			mdb_warn("failed to read UDP header at %p", addr);
   1050      0     stevel 			return (DCMD_ERR);
   1051      0     stevel 		}
   1052      0     stevel 		udphdr_print(&udph);
   1053      0     stevel 		break;
   1054      0     stevel 	}
   1055      0     stevel 	case IPPROTO_SCTP: {
   1056      0     stevel 		sctp_hdr_t sctph;
   1057      0     stevel 
   1058      0     stevel 		if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) {
   1059      0     stevel 			mdb_warn("failed to read SCTP header at %p", addr);
   1060      0     stevel 			return (DCMD_ERR);
   1061      0     stevel 		}
   1062      0     stevel 		sctphdr_print(&sctph);
   1063      0     stevel 		break;
   1064      0     stevel 	}
   1065      0     stevel 	default:
   1066      0     stevel 		break;
   1067      0     stevel 	}
   1068      0     stevel 
   1069      0     stevel 	return (DCMD_OK);
   1070      0     stevel }
   1071      0     stevel 
   1072      0     stevel static const mdb_bitmask_t ip_flags[] = {
   1073      0     stevel 	{ "DF",	IPH_DF, IPH_DF	},
   1074      0     stevel 	{ "MF", IPH_MF,	IPH_MF	},
   1075      0     stevel 	{ NULL, 0,	0	}
   1076      0     stevel };
   1077      0     stevel 
   1078      0     stevel /* ARGSUSED */
   1079      0     stevel static int
   1080      0     stevel iphdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1081      0     stevel {
   1082      0     stevel 	uint_t		verbose = FALSE, force = FALSE;
   1083      0     stevel 	ipha_t		iph[1];
   1084      0     stevel 	uint16_t	ver, totlen, hdrlen, ipid, off, csum;
   1085      0     stevel 	uintptr_t	nxt_proto;
   1086      0     stevel 	char		exp_csum[8];
   1087      0     stevel 
   1088      0     stevel 	if (mdb_getopts(argc, argv,
   1089      0     stevel 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
   1090      0     stevel 	    'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc)
   1091      0     stevel 		return (DCMD_USAGE);
   1092      0     stevel 
   1093      0     stevel 	if (mdb_vread(iph, sizeof (*iph), addr) == -1) {
   1094      0     stevel 		mdb_warn("failed to read IPv4 header at %p", addr);
   1095      0     stevel 		return (DCMD_ERR);
   1096      0     stevel 	}
   1097      0     stevel 
   1098      0     stevel 	ver = (iph->ipha_version_and_hdr_length & 0xf0) >> 4;
   1099      0     stevel 	if (ver != IPV4_VERSION) {
   1100      0     stevel 		if (ver == IPV6_VERSION) {
   1101      0     stevel 			return (ip6hdr(addr, flags, argc, argv));
   1102      0     stevel 		} else if (!force) {
   1103      0     stevel 			mdb_warn("unknown IP version: %d\n", ver);
   1104      0     stevel 			return (DCMD_ERR);
   1105      0     stevel 		}
   1106      0     stevel 	}
   1107      0     stevel 
   1108      0     stevel 	mdb_printf("%<b>IPv4 header%</b>\n");
   1109      0     stevel 	mdb_printf("%-34s %-34s\n"
   1110      0     stevel 	    "%<u>%-4s %-4s %-5s %-5s %-6s %-5s %-5s %-6s %-8s %-6s%</u>\n",
   1111      0     stevel 	    "SRC", "DST",
   1112      0     stevel 	    "HLEN", "TOS", "LEN", "ID", "OFFSET", "TTL", "PROTO", "CHKSUM",
   1113      0     stevel 	    "EXP-CSUM", "FLGS");
   1114      0     stevel 
   1115      0     stevel 	hdrlen = (iph->ipha_version_and_hdr_length & 0x0f) << 2;
   1116      0     stevel 	mdb_nhconvert(&totlen, &iph->ipha_length, sizeof (totlen));
   1117      0     stevel 	mdb_nhconvert(&ipid, &iph->ipha_ident, sizeof (ipid));
   1118      0     stevel 	mdb_nhconvert(&off, &iph->ipha_fragment_offset_and_flags, sizeof (off));
   1119      0     stevel 	if (hdrlen == IP_SIMPLE_HDR_LENGTH) {
   1120      0     stevel 		if ((csum = ipcksum(iph, sizeof (*iph))) != 0)
   1121      0     stevel 			csum = ~(~csum + ~iph->ipha_hdr_checksum);
   1122      0     stevel 		else
   1123      0     stevel 			csum = iph->ipha_hdr_checksum;
   1124      0     stevel 		mdb_snprintf(exp_csum, 8, "%u", csum);
   1125      0     stevel 	} else {
   1126      0     stevel 		mdb_snprintf(exp_csum, 8, "<n/a>");
   1127      0     stevel 	}
   1128      0     stevel 
   1129      0     stevel 	mdb_printf("%-34I %-34I%\n"
   1130      0     stevel 	    "%-4d %-4d %-5hu %-5hu %-6hu %-5hu %-5hu %-6u %-8s <%5hb>\n",
   1131      0     stevel 	    iph->ipha_src, iph->ipha_dst,
   1132      0     stevel 	    hdrlen, iph->ipha_type_of_service, totlen, ipid,
   1133      0     stevel 	    (off << 3) & 0xffff, iph->ipha_ttl, iph->ipha_protocol,
   1134      0     stevel 	    iph->ipha_hdr_checksum, exp_csum, off, ip_flags);
   1135      0     stevel 
   1136      0     stevel 	if (verbose) {
   1137      0     stevel 		nxt_proto = addr + hdrlen;
   1138      0     stevel 		return (transport_hdr(iph->ipha_protocol, nxt_proto));
   1139      0     stevel 	} else {
   1140      0     stevel 		return (DCMD_OK);
   1141      0     stevel 	}
   1142      0     stevel }
   1143      0     stevel 
   1144      0     stevel /* ARGSUSED */
   1145      0     stevel static int
   1146      0     stevel ip6hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1147      0     stevel {
   1148      0     stevel 	uint_t		verbose = FALSE, force = FALSE;
   1149      0     stevel 	ip6_t		iph[1];
   1150      0     stevel 	int		ver, class, flow;
   1151      0     stevel 	uint16_t	plen;
   1152      0     stevel 	uintptr_t	nxt_proto;
   1153      0     stevel 
   1154      0     stevel 	if (mdb_getopts(argc, argv,
   1155      0     stevel 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
   1156      0     stevel 	    'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc)
   1157      0     stevel 		return (DCMD_USAGE);
   1158      0     stevel 
   1159      0     stevel 	if (mdb_vread(iph, sizeof (*iph), addr) == -1) {
   1160      0     stevel 		mdb_warn("failed to read IPv6 header at %p", addr);
   1161      0     stevel 		return (DCMD_ERR);
   1162      0     stevel 	}
   1163      0     stevel 
   1164      0     stevel 	ver = (iph->ip6_vfc & 0xf0) >> 4;
   1165      0     stevel 	if (ver != IPV6_VERSION) {
   1166      0     stevel 		if (ver == IPV4_VERSION) {
   1167      0     stevel 			return (iphdr(addr, flags, argc, argv));
   1168      0     stevel 		} else if (!force) {
   1169      0     stevel 			mdb_warn("unknown IP version: %d\n", ver);
   1170      0     stevel 			return (DCMD_ERR);
   1171      0     stevel 		}
   1172      0     stevel 	}
   1173      0     stevel 
   1174      0     stevel 	mdb_printf("%<b>IPv6 header%</b>\n");
   1175      0     stevel 	mdb_printf("%<u>%-26s %-26s %4s %7s %5s %3s %3s%</u>\n",
   1176      0     stevel 	    "SRC", "DST", "TCLS", "FLOW-ID", "PLEN", "NXT", "HOP");
   1177      0     stevel 
   1178      0     stevel 	class = (iph->ip6_vcf & IPV6_FLOWINFO_TCLASS) >> 20;
   1179      0     stevel 	mdb_nhconvert(&class, &class, sizeof (class));
   1180      0     stevel 	flow = iph->ip6_vcf & IPV6_FLOWINFO_FLOWLABEL;
   1181      0     stevel 	mdb_nhconvert(&flow, &flow, sizeof (flow));
   1182      0     stevel 	mdb_nhconvert(&plen, &iph->ip6_plen, sizeof (plen));
   1183      0     stevel 
   1184      0     stevel 	mdb_printf("%-26N %-26N %4d %7d %5hu %3d %3d\n",
   1185      0     stevel 	    &iph->ip6_src, &iph->ip6_dst,
   1186      0     stevel 	    class, flow, plen, iph->ip6_nxt, iph->ip6_hlim);
   1187      0     stevel 
   1188      0     stevel 	if (verbose) {
   1189      0     stevel 		nxt_proto = addr + sizeof (ip6_t);
   1190      0     stevel 		return (transport_hdr(iph->ip6_nxt, nxt_proto));
   1191      0     stevel 	} else {
   1192      0     stevel 		return (DCMD_OK);
   1193      0     stevel 	}
   1194      0     stevel }
   1195      0     stevel 
   1196      0     stevel int
   1197  11042       Erik nce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1198  11042       Erik {
   1199  11042       Erik 	nce_t nce;
   1200  11042       Erik 	nce_cbdata_t nce_cb;
   1201  11042       Erik 	int ipversion = 0;
   1202  11042       Erik 	const char *opt_P = NULL, *opt_ill;
   1203  11042       Erik 
   1204  11042       Erik 	if (mdb_getopts(argc, argv,
   1205  11042       Erik 	    'i', MDB_OPT_STR, &opt_ill,
   1206  11042       Erik 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
   1207  11042       Erik 		return (DCMD_USAGE);
   1208  11042       Erik 
   1209  11042       Erik 	if (opt_P != NULL) {
   1210  11042       Erik 		if (strcmp("v4", opt_P) == 0) {
   1211  11042       Erik 			ipversion = IPV4_VERSION;
   1212  11042       Erik 		} else if (strcmp("v6", opt_P) == 0) {
   1213  11042       Erik 			ipversion = IPV6_VERSION;
   1214  11042       Erik 		} else {
   1215  11042       Erik 			mdb_warn("invalid protocol '%s'\n", opt_P);
   1216  11042       Erik 			return (DCMD_USAGE);
   1217  11042       Erik 		}
   1218  11042       Erik 	}
   1219  11042       Erik 
   1220  11042       Erik 	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
   1221  11042       Erik 		mdb_printf("%<u>%?s %5s %18s %?s %s %s %</u>\n",
   1222  11042       Erik 		    "ADDR", "INTF", "LLADDR", "FP_MP", "REFCNT",
   1223  11042       Erik 		    "NCE_ADDR");
   1224  11042       Erik 	}
   1225  11042       Erik 
   1226  11042       Erik 	bzero(&nce_cb, sizeof (nce_cb));
   1227  11042       Erik 	if (opt_ill != NULL) {
   1228  11042       Erik 		strcpy(nce_cb.nce_ill_name, opt_ill);
   1229  11042       Erik 	}
   1230  11042       Erik 	nce_cb.nce_ipversion = ipversion;
   1231  11042       Erik 
   1232  11042       Erik 	if (flags & DCMD_ADDRSPEC) {
   1233  11042       Erik 		(void) mdb_vread(&nce, sizeof (nce_t), addr);
   1234  11042       Erik 		(void) nce_format(addr, &nce, &nce_cb);
   1235  11042       Erik 	} else if (mdb_walk("nce", (mdb_walk_cb_t)nce_format, &nce_cb) == -1) {
   1236  11042       Erik 		mdb_warn("failed to walk ire table");
   1237  11042       Erik 		return (DCMD_ERR);
   1238  11042       Erik 	}
   1239  11042       Erik 
   1240  11042       Erik 	return (DCMD_OK);
   1241  11042       Erik }
   1242  11042       Erik 
   1243  11042       Erik /* ARGSUSED */
   1244  11042       Erik static int
   1245  11042       Erik dce_format(uintptr_t addr, const dce_t *dcep, void *dce_cb_arg)
   1246  11042       Erik {
   1247  11042       Erik 	static const mdb_bitmask_t dmasks[] = {
   1248  11042       Erik 		{ "D",	DCEF_DEFAULT,		DCEF_DEFAULT },
   1249  11042       Erik 		{ "P",	DCEF_PMTU,		DCEF_PMTU },
   1250  11042       Erik 		{ "U",	DCEF_UINFO,		DCEF_UINFO },
   1251  11042       Erik 		{ "S",	DCEF_TOO_SMALL_PMTU,	DCEF_TOO_SMALL_PMTU },
   1252  11042       Erik 		{ NULL,	0,			0		}
   1253  11042       Erik 	};
   1254  11042       Erik 	char flagsbuf[2 * A_CNT(dmasks)];
   1255  11042       Erik 	int ipversion = *(int *)dce_cb_arg;
   1256  11042       Erik 	boolean_t condemned = dcep->dce_generation == DCE_GENERATION_CONDEMNED;
   1257  11042       Erik 
   1258  11042       Erik 	if (ipversion != 0 && ipversion != dcep->dce_ipversion)
   1259  11042       Erik 		return (WALK_NEXT);
   1260  11042       Erik 
   1261  11042       Erik 	mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%b", dcep->dce_flags,
   1262  11042       Erik 	    dmasks);
   1263  11042       Erik 
   1264  11042       Erik 	switch (dcep->dce_ipversion) {
   1265  11042       Erik 	case IPV4_VERSION:
   1266  11042       Erik 		mdb_printf("%<u>%?p%3s %8s %8d %30I %</u>\n", addr, condemned ?
   1267  11042       Erik 		    "(C)" : "", flagsbuf, dcep->dce_pmtu, &dcep->dce_v4addr);
   1268  11042       Erik 		break;
   1269  11042       Erik 	case IPV6_VERSION:
   1270  11042       Erik 		mdb_printf("%<u>%?p%3s %8s %8d %30N %</u>\n", addr, condemned ?
   1271  11042       Erik 		    "(C)" : "", flagsbuf, dcep->dce_pmtu, &dcep->dce_v6addr);
   1272  11042       Erik 		break;
   1273  11042       Erik 	default:
   1274  11042       Erik 		mdb_printf("%<u>%?p%3s %8s %8d %30s %</u>\n", addr, condemned ?
   1275  11042       Erik 		    "(C)" : "", flagsbuf, dcep->dce_pmtu, "");
   1276  11042       Erik 	}
   1277  11042       Erik 
   1278  11042       Erik 	return (WALK_NEXT);
   1279  11042       Erik }
   1280  11042       Erik 
   1281  11042       Erik int
   1282  11042       Erik dce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1283  11042       Erik {
   1284  11042       Erik 	dce_t dce;
   1285  11042       Erik 	const char *opt_P = NULL;
   1286  11042       Erik 	const char *zone_name = NULL;
   1287  11042       Erik 	ip_stack_t *ipst = NULL;
   1288  11042       Erik 	int ipversion = 0;
   1289  11042       Erik 
   1290  11042       Erik 	if (mdb_getopts(argc, argv,
   1291  11042       Erik 	    's', MDB_OPT_STR, &zone_name,
   1292  11042       Erik 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
   1293  11042       Erik 		return (DCMD_USAGE);
   1294  11042       Erik 
   1295  11042       Erik 	/* Follow the specified zone name to find a ip_stack_t*. */
   1296  11042       Erik 	if (zone_name != NULL) {
   1297  11042       Erik 		ipst = zone_to_ips(zone_name);
   1298  11042       Erik 		if (ipst == NULL)
   1299  11042       Erik 			return (DCMD_USAGE);
   1300  11042       Erik 	}
   1301  11042       Erik 
   1302  11042       Erik 	if (opt_P != NULL) {
   1303  11042       Erik 		if (strcmp("v4", opt_P) == 0) {
   1304  11042       Erik 			ipversion = IPV4_VERSION;
   1305  11042       Erik 		} else if (strcmp("v6", opt_P) == 0) {
   1306  11042       Erik 			ipversion = IPV6_VERSION;
   1307  11042       Erik 		} else {
   1308  11042       Erik 			mdb_warn("invalid protocol '%s'\n", opt_P);
   1309  11042       Erik 			return (DCMD_USAGE);
   1310  11042       Erik 		}
   1311  11042       Erik 	}
   1312  11042       Erik 
   1313  11042       Erik 	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
   1314  11042       Erik 		mdb_printf("%<u>%?s%3s %8s %8s %30s %</u>\n",
   1315  11042       Erik 		    "ADDR", "", "FLAGS", "PMTU", "DST_ADDR");
   1316  11042       Erik 	}
   1317  11042       Erik 
   1318  11042       Erik 	if (flags & DCMD_ADDRSPEC) {
   1319  11042       Erik 		(void) mdb_vread(&dce, sizeof (dce_t), addr);
   1320  11042       Erik 		(void) dce_format(addr, &dce, &ipversion);
   1321  11042       Erik 	} else if (mdb_pwalk("dce", (mdb_walk_cb_t)dce_format, &ipversion,
   1322  11042       Erik 	    (uintptr_t)ipst) == -1) {
   1323  11042       Erik 		mdb_warn("failed to walk dce cache");
   1324  11042       Erik 		return (DCMD_ERR);
   1325  11042       Erik 	}
   1326  11042       Erik 
   1327  11042       Erik 	return (DCMD_OK);
   1328  11042       Erik }
   1329  11042       Erik 
   1330  11042       Erik int
   1331      0     stevel ire(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1332      0     stevel {
   1333      0     stevel 	uint_t verbose = FALSE;
   1334      0     stevel 	ire_t ire;
   1335   5940    sowmini 	ire_cbdata_t ire_cb;
   1336   5940    sowmini 	int ipversion = 0;
   1337   5940    sowmini 	const char *opt_P = NULL;
   1338  11042       Erik 	const char *zone_name = NULL;
   1339  11042       Erik 	ip_stack_t *ipst = NULL;
   1340      0     stevel 
   1341      0     stevel 	if (mdb_getopts(argc, argv,
   1342   5940    sowmini 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
   1343  11042       Erik 	    's', MDB_OPT_STR, &zone_name,
   1344   5940    sowmini 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
   1345      0     stevel 		return (DCMD_USAGE);
   1346  11042       Erik 
   1347  11042       Erik 	/* Follow the specified zone name to find a ip_stack_t*. */
   1348  11042       Erik 	if (zone_name != NULL) {
   1349  11042       Erik 		ipst = zone_to_ips(zone_name);
   1350  11042       Erik 		if (ipst == NULL)
   1351  11042       Erik 			return (DCMD_USAGE);
   1352  11042       Erik 	}
   1353   5940    sowmini 
   1354   5940    sowmini 	if (opt_P != NULL) {
   1355   5940    sowmini 		if (strcmp("v4", opt_P) == 0) {
   1356   5940    sowmini 			ipversion = IPV4_VERSION;
   1357   5940    sowmini 		} else if (strcmp("v6", opt_P) == 0) {
   1358   5940    sowmini 			ipversion = IPV6_VERSION;
   1359   5940    sowmini 		} else {
   1360   5940    sowmini 			mdb_warn("invalid protocol '%s'\n", opt_P);
   1361   5940    sowmini 			return (DCMD_USAGE);
   1362   5940    sowmini 		}
   1363   5940    sowmini 	}
   1364      0     stevel 
   1365      0     stevel 	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
   1366      0     stevel 
   1367      0     stevel 		if (verbose) {
   1368      0     stevel 			mdb_printf("%?s %40s %-20s%\n"
   1369      0     stevel 			    "%?s %40s %-20s%\n"
   1370  11042       Erik 			    "%<u>%?s %40s %4s %-20s %s%</u>\n",
   1371      0     stevel 			    "ADDR", "SRC", "TYPE",
   1372      0     stevel 			    "", "DST", "MARKS",
   1373  11042       Erik 			    "", "STACK", "ZONE", "FLAGS", "INTF");
   1374      0     stevel 		} else {
   1375  11042       Erik 			mdb_printf("%<u>%?s %30s %30s %5s %4s %s%</u>\n",
   1376  11042       Erik 			    "ADDR", "SRC", "DST", "STACK", "ZONE", "INTF");
   1377      0     stevel 		}
   1378      0     stevel 	}
   1379      0     stevel 
   1380   5940    sowmini 	ire_cb.verbose = (verbose == TRUE);
   1381   5940    sowmini 	ire_cb.ire_ipversion = ipversion;
   1382   5940    sowmini 
   1383      0     stevel 	if (flags & DCMD_ADDRSPEC) {
   1384      0     stevel 		(void) mdb_vread(&ire, sizeof (ire_t), addr);
   1385   5940    sowmini 		(void) ire_format(addr, &ire, &ire_cb);
   1386  11042       Erik 	} else if (mdb_pwalk("ire", (mdb_walk_cb_t)ire_format, &ire_cb,
   1387  11042       Erik 	    (uintptr_t)ipst) == -1) {
   1388      0     stevel 		mdb_warn("failed to walk ire table");
   1389      0     stevel 		return (DCMD_ERR);
   1390      0     stevel 	}
   1391      0     stevel 
   1392      0     stevel 	return (DCMD_OK);
   1393      0     stevel }
   1394      0     stevel 
   1395      0     stevel static size_t
   1396      0     stevel mi_osize(const queue_t *q)
   1397      0     stevel {
   1398      0     stevel 	/*
   1399      0     stevel 	 * The code in common/inet/mi.c allocates an extra word to store the
   1400      0     stevel 	 * size of the allocation.  An mi_o_s is thus a size_t plus an mi_o_s.
   1401      0     stevel 	 */
   1402      0     stevel 	struct mi_block {
   1403      0     stevel 		size_t mi_nbytes;
   1404      0     stevel 		struct mi_o_s mi_o;
   1405      0     stevel 	} m;
   1406      0     stevel 
   1407      0     stevel 	if (mdb_vread(&m, sizeof (m), (uintptr_t)q->q_ptr -
   1408      0     stevel 	    sizeof (m)) == sizeof (m))
   1409      0     stevel 		return (m.mi_nbytes - sizeof (m));
   1410      0     stevel 
   1411      0     stevel 	return (0);
   1412      0     stevel }
   1413      0     stevel 
   1414      0     stevel static void
   1415      0     stevel ip_ill_qinfo(const queue_t *q, char *buf, size_t nbytes)
   1416      0     stevel {
   1417      0     stevel 	char name[32];
   1418      0     stevel 	ill_t ill;
   1419      0     stevel 
   1420      0     stevel 	if (mdb_vread(&ill, sizeof (ill),
   1421      0     stevel 	    (uintptr_t)q->q_ptr) == sizeof (ill) &&
   1422      0     stevel 	    mdb_readstr(name, sizeof (name), (uintptr_t)ill.ill_name) > 0)
   1423      0     stevel 		(void) mdb_snprintf(buf, nbytes, "if: %s", name);
   1424      0     stevel }
   1425      0     stevel 
   1426      0     stevel void
   1427      0     stevel ip_qinfo(const queue_t *q, char *buf, size_t nbytes)
   1428      0     stevel {
   1429      0     stevel 	size_t size = mi_osize(q);
   1430      0     stevel 
   1431      0     stevel 	if (size == sizeof (ill_t))
   1432      0     stevel 		ip_ill_qinfo(q, buf, nbytes);
   1433      0     stevel }
   1434      0     stevel 
   1435      0     stevel uintptr_t
   1436      0     stevel ip_rnext(const queue_t *q)
   1437      0     stevel {
   1438      0     stevel 	size_t size = mi_osize(q);
   1439      0     stevel 	ill_t ill;
   1440      0     stevel 
   1441      0     stevel 	if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill),
   1442      0     stevel 	    (uintptr_t)q->q_ptr) == sizeof (ill))
   1443      0     stevel 		return ((uintptr_t)ill.ill_rq);
   1444      0     stevel 
   1445      0     stevel 	return (NULL);
   1446      0     stevel }
   1447      0     stevel 
   1448      0     stevel uintptr_t
   1449      0     stevel ip_wnext(const queue_t *q)
   1450      0     stevel {
   1451      0     stevel 	size_t size = mi_osize(q);
   1452      0     stevel 	ill_t ill;
   1453      0     stevel 
   1454      0     stevel 	if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill),
   1455      0     stevel 	    (uintptr_t)q->q_ptr) == sizeof (ill))
   1456      0     stevel 		return ((uintptr_t)ill.ill_wq);
   1457      0     stevel 
   1458      0     stevel 	return (NULL);
   1459      0     stevel }
   1460      0     stevel 
   1461      0     stevel /*
   1462      0     stevel  * Print the core fields in an squeue_t.  With the "-v" argument,
   1463      0     stevel  * provide more verbose output.
   1464      0     stevel  */
   1465      0     stevel static int
   1466      0     stevel squeue(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1467      0     stevel {
   1468      0     stevel 	unsigned int	i;
   1469      0     stevel 	unsigned int	verbose = FALSE;
   1470      0     stevel 	const int	SQUEUE_STATEDELT = (int)(sizeof (uintptr_t) + 9);
   1471      0     stevel 	boolean_t	arm;
   1472      0     stevel 	squeue_t	squeue;
   1473      0     stevel 
   1474      0     stevel 	if (!(flags & DCMD_ADDRSPEC)) {
   1475      0     stevel 		if (mdb_walk_dcmd("genunix`squeue_cache", "ip`squeue",
   1476      0     stevel 		    argc, argv) == -1) {
   1477      0     stevel 			mdb_warn("failed to walk squeue cache");
   1478      0     stevel 			return (DCMD_ERR);
   1479      0     stevel 		}
   1480      0     stevel 		return (DCMD_OK);
   1481      0     stevel 	}
   1482      0     stevel 
   1483      0     stevel 	if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL)
   1484      0     stevel 	    != argc)
   1485      0     stevel 		return (DCMD_USAGE);
   1486      0     stevel 
   1487      0     stevel 	if (!DCMD_HDRSPEC(flags) && verbose)
   1488      0     stevel 		mdb_printf("\n\n");
   1489      0     stevel 
   1490      0     stevel 	if (DCMD_HDRSPEC(flags) || verbose) {
   1491      0     stevel 		mdb_printf("%?s %-5s %-3s %?s %?s %?s\n",
   1492      0     stevel 		    "ADDR", "STATE", "CPU",
   1493      0     stevel 		    "FIRST", "LAST", "WORKER");
   1494      0     stevel 	}
   1495      0     stevel 
   1496      0     stevel 	if (mdb_vread(&squeue, sizeof (squeue_t), addr) == -1) {
   1497      0     stevel 		mdb_warn("cannot read squeue_t at %p", addr);
   1498      0     stevel 		return (DCMD_ERR);
   1499      0     stevel 	}
   1500      0     stevel 
   1501      0     stevel 	mdb_printf("%0?p %05x %3d %0?p %0?p %0?p\n",
   1502      0     stevel 	    addr, squeue.sq_state, squeue.sq_bind,
   1503      0     stevel 	    squeue.sq_first, squeue.sq_last, squeue.sq_worker);
   1504      0     stevel 
   1505      0     stevel 	if (!verbose)
   1506      0     stevel 		return (DCMD_OK);
   1507      0     stevel 
   1508      0     stevel 	arm = B_TRUE;
   1509      0     stevel 	for (i = 0; squeue_states[i].bit_name != NULL; i++) {
   1510      0     stevel 		if (((squeue.sq_state) & (1 << i)) == 0)
   1511      0     stevel 			continue;
   1512      0     stevel 
   1513      0     stevel 		if (arm) {
   1514      0     stevel 			mdb_printf("%*s|\n", SQUEUE_STATEDELT, "");
   1515      0     stevel 			mdb_printf("%*s+-->  ", SQUEUE_STATEDELT, "");
   1516      0     stevel 			arm = B_FALSE;
   1517      0     stevel 		} else
   1518      0     stevel 			mdb_printf("%*s      ", SQUEUE_STATEDELT, "");
   1519      0     stevel 
   1520      0     stevel 		mdb_printf("%-12s %s\n", squeue_states[i].bit_name,
   1521      0     stevel 		    squeue_states[i].bit_descr);
   1522      0     stevel 	}
   1523      0     stevel 
   1524      0     stevel 	return (DCMD_OK);
   1525      0     stevel }
   1526      0     stevel 
   1527      0     stevel static void
   1528      0     stevel ip_squeue_help(void)
   1529      0     stevel {
   1530      0     stevel 	mdb_printf("Print the core information for a given NCA squeue_t.\n\n");
   1531      0     stevel 	mdb_printf("Options:\n");
   1532      0     stevel 	mdb_printf("\t-v\tbe verbose (more descriptive)\n");
   1533      0     stevel }
   1534      0     stevel 
   1535   5023   carlsonj /*
   1536   5023   carlsonj  * This is called by ::th_trace (via a callback) when walking the th_hash
   1537   5023   carlsonj  * list.  It calls modent to find the entries.
   1538   5023   carlsonj  */
   1539   5023   carlsonj /* ARGSUSED */
   1540   5023   carlsonj static int
   1541   5023   carlsonj modent_summary(uintptr_t addr, const void *data, void *private)
   1542   5023   carlsonj {
   1543   5023   carlsonj 	th_walk_data_t *thw = private;
   1544   5023   carlsonj 	const struct mod_hash_entry *mhe = data;
   1545   5023   carlsonj 	th_trace_t th;
   1546   5023   carlsonj 
   1547   5023   carlsonj 	if (mdb_vread(&th, sizeof (th), (uintptr_t)mhe->mhe_val) == -1) {
   1548   5023   carlsonj 		mdb_warn("failed to read th_trace_t %p", mhe->mhe_val);
   1549   5023   carlsonj 		return (WALK_ERR);
   1550   5023   carlsonj 	}
   1551   5023   carlsonj 
   1552   5023   carlsonj 	if (th.th_refcnt == 0 && thw->thw_non_zero_only)
   1553   5023   carlsonj 		return (WALK_NEXT);
   1554   5023   carlsonj 
   1555   5023   carlsonj 	if (!thw->thw_match) {
   1556   5023   carlsonj 		mdb_printf("%?p %?p %?p %8d %?p\n", thw->thw_ipst, mhe->mhe_key,
   1557   5023   carlsonj 		    mhe->mhe_val, th.th_refcnt, th.th_id);
   1558   5023   carlsonj 	} else if (thw->thw_matchkey == (uintptr_t)mhe->mhe_key) {
   1559   5023   carlsonj 		int i, j, k;
   1560   5023   carlsonj 		tr_buf_t *tr;
   1561   5023   carlsonj 
   1562   5023   carlsonj 		mdb_printf("Object %p in IP stack %p:\n", mhe->mhe_key,
   1563   5023   carlsonj 		    thw->thw_ipst);
   1564   5023   carlsonj 		i = th.th_trace_lastref;
   1565   5023   carlsonj 		mdb_printf("\tThread %p refcnt %d:\n", th.th_id,
   1566   5023   carlsonj 		    th.th_refcnt);
   1567   5023   carlsonj 		for (j = TR_BUF_MAX; j > 0; j--) {
   1568   5023   carlsonj 			tr = th.th_trbuf + i;
   1569   5023   carlsonj 			if (tr->tr_depth == 0 || tr->tr_depth > TR_STACK_DEPTH)
   1570   5023   carlsonj 				break;
   1571   5023   carlsonj 			mdb_printf("\t  T%+ld:\n", tr->tr_time -
   1572   5023   carlsonj 			    thw->thw_lbolt);
   1573   5023   carlsonj 			for (k = 0; k < tr->tr_depth; k++)
   1574   5023   carlsonj 				mdb_printf("\t\t%a\n", tr->tr_stack[k]);
   1575   5023   carlsonj 			if (--i < 0)
   1576   5023   carlsonj 				i = TR_BUF_MAX - 1;
   1577   5023   carlsonj 		}
   1578   5023   carlsonj 	}
   1579   5023   carlsonj 	return (WALK_NEXT);
   1580   5023   carlsonj }
   1581   5023   carlsonj 
   1582   5023   carlsonj /*
   1583   5023   carlsonj  * This is called by ::th_trace (via a callback) when walking the th_hash
   1584   5023   carlsonj  * list.  It calls modent to find the entries.
   1585   5023   carlsonj  */
   1586   5023   carlsonj /* ARGSUSED */
   1587   5023   carlsonj static int
   1588   5023   carlsonj th_hash_summary(uintptr_t addr, const void *data, void *private)
   1589   5023   carlsonj {
   1590   5023   carlsonj 	const th_hash_t *thh = data;
   1591   5023   carlsonj 	th_walk_data_t *thw = private;
   1592   5023   carlsonj 
   1593   5023   carlsonj 	thw->thw_ipst = (uintptr_t)thh->thh_ipst;
   1594   5023   carlsonj 	return (mdb_pwalk("modent", modent_summary, private,
   1595   5023   carlsonj 	    (uintptr_t)thh->thh_hash));
   1596   5023   carlsonj }
   1597   5023   carlsonj 
   1598   5023   carlsonj /*
   1599   5023   carlsonj  * Print or summarize the th_trace_t structures.
   1600   5023   carlsonj  */
   1601   5023   carlsonj static int
   1602   5023   carlsonj th_trace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1603   5023   carlsonj {
   1604   5023   carlsonj 	th_walk_data_t thw;
   1605   5023   carlsonj 
   1606   5023   carlsonj 	(void) memset(&thw, 0, sizeof (thw));
   1607   5023   carlsonj 
   1608   5023   carlsonj 	if (mdb_getopts(argc, argv,
   1609   5023   carlsonj 	    'n', MDB_OPT_SETBITS, TRUE, &thw.thw_non_zero_only,
   1610   5023   carlsonj 	    NULL) != argc)
   1611   5023   carlsonj 		return (DCMD_USAGE);
   1612   5023   carlsonj 
   1613   5023   carlsonj 	if (!(flags & DCMD_ADDRSPEC)) {
   1614   5023   carlsonj 		/*
   1615   5023   carlsonj 		 * No address specified.  Walk all of the th_hash_t in the
   1616   5023   carlsonj 		 * system, and summarize the th_trace_t entries in each.
   1617   5023   carlsonj 		 */
   1618   5023   carlsonj 		mdb_printf("%?s %?s %?s %8s %?s\n",
   1619   5023   carlsonj 		    "IPSTACK", "OBJECT", "TRACE", "REFCNT", "THREAD");
   1620   5023   carlsonj 		thw.thw_match = B_FALSE;
   1621   5023   carlsonj 	} else {
   1622   5023   carlsonj 		thw.thw_match = B_TRUE;
   1623   5023   carlsonj 		thw.thw_matchkey = addr;
   1624  11066     rafael 
   1625  11066     rafael 		if ((thw.thw_lbolt = (clock_t)mdb_get_lbolt()) == -1) {
   1626   5023   carlsonj 			mdb_warn("failed to read lbolt");
   1627   5023   carlsonj 			return (DCMD_ERR);
   1628   5023   carlsonj 		}
   1629   5023   carlsonj 	}
   1630   5023   carlsonj 	if (mdb_pwalk("th_hash", th_hash_summary, &thw, NULL) == -1) {
   1631   5023   carlsonj 		mdb_warn("can't walk th_hash entries");
   1632   5023   carlsonj 		return (DCMD_ERR);
   1633   5023   carlsonj 	}
   1634   5023   carlsonj 	return (DCMD_OK);
   1635   5023   carlsonj }
   1636   5023   carlsonj 
   1637   5023   carlsonj static void
   1638   5023   carlsonj th_trace_help(void)
   1639   5023   carlsonj {
   1640  11042       Erik 	mdb_printf("If given an address of an ill_t, ipif_t, ire_t, or ncec_t, "
   1641   5023   carlsonj 	    "print the\n"
   1642   5023   carlsonj 	    "corresponding th_trace_t structure in detail.  Otherwise, if no "
   1643   5023   carlsonj 	    "address is\n"
   1644   5023   carlsonj 	    "given, then summarize all th_trace_t structures.\n\n");
   1645   5023   carlsonj 	mdb_printf("Options:\n"
   1646   5023   carlsonj 	    "\t-n\tdisplay only entries with non-zero th_refcnt\n");
   1647   5023   carlsonj }
   1648   5023   carlsonj 
   1649      0     stevel static const mdb_dcmd_t dcmds[] = {
   1650   9089  Vasumathi 	{ "conn_status", ":",
   1651   9089  Vasumathi 	    "display connection structures from ipcl hash tables",
   1652   9089  Vasumathi 	    conn_status, conn_status_help },
   1653   9089  Vasumathi 	{ "srcid_status", ":",
   1654   9089  Vasumathi 	    "display connection structures from ipcl hash tables",
   1655   9089  Vasumathi 	    srcid_status },
   1656  11042       Erik 	{ "ill", "?[-v] [-P v4 | v6] [-s exclusive-ip-zone-name]",
   1657  11042       Erik 	    "display ill_t structures", ill, ill_help },
   1658      0     stevel 	{ "illif", "?[-P v4 | v6]",
   1659      0     stevel 	    "display or filter IP Lower Level InterFace structures", illif,
   1660      0     stevel 	    illif_help },
   1661      0     stevel 	{ "iphdr", ":[-vf]", "display an IPv4 header", iphdr },
   1662      0     stevel 	{ "ip6hdr", ":[-vf]", "display an IPv6 header", ip6hdr },
   1663   9089  Vasumathi 	{ "ipif", "?[-v] [-P v4 | v6]", "display ipif structures",
   1664   9089  Vasumathi 	    ipif, ipif_help },
   1665  11042       Erik 	{ "ire", "?[-v] [-P v4|v6] [-s exclusive-ip-zone-name]",
   1666   5940    sowmini 	    "display Internet Route Entry structures", ire },
   1667  11042       Erik 	{ "nce", "?[-P v4|v6] [-i <interface>]",
   1668  11042       Erik 	    "display interface-specific Neighbor Cache structures", nce },
   1669  11042       Erik 	{ "ncec", "?[-P v4 | v6]", "display Neighbor Cache Entry structures",
   1670  11042       Erik 	    ncec },
   1671  11042       Erik 	{ "dce", "?[-P v4|v6] [-s exclusive-ip-zone-name]",
   1672  11042       Erik 	    "display Destination Cache Entry structures", dce },
   1673      0     stevel 	{ "squeue", ":[-v]", "print core squeue_t info", squeue,
   1674      0     stevel 	    ip_squeue_help },
   1675      0     stevel 	{ "tcphdr", ":", "display a TCP header", tcphdr },
   1676      0     stevel 	{ "udphdr", ":", "display an UDP header", udphdr },
   1677      0     stevel 	{ "sctphdr", ":", "display an SCTP header", sctphdr },
   1678   5023   carlsonj 	{ "th_trace", "?[-n]", "display th_trace_t structures", th_trace,
   1679   5023   carlsonj 	    th_trace_help },
   1680      0     stevel 	{ NULL }
   1681      0     stevel };
   1682      0     stevel 
   1683      0     stevel static const mdb_walker_t walkers[] = {
   1684   9089  Vasumathi 	{ "conn_status", "walk list of conn_t structures",
   1685   9089  Vasumathi 		ip_stacks_common_walk_init, conn_status_walk_step, NULL },
   1686   3448   dh155122 	{ "illif", "walk list of ill interface types for all stacks",
   1687   5940    sowmini 		ip_stacks_common_walk_init, illif_walk_step, NULL },
   1688   3448   dh155122 	{ "illif_stack", "walk list of ill interface types",
   1689   3448   dh155122 		illif_stack_walk_init, illif_stack_walk_step,
   1690   3448   dh155122 		illif_stack_walk_fini },
   1691  11042       Erik 	{ "ill", "walk active ill_t structures for all stacks",
   1692   9089  Vasumathi 		ill_walk_init, ill_walk_step, NULL },
   1693   9089  Vasumathi 	{ "ipif", "walk list of ipif structures for all stacks",
   1694   9089  Vasumathi 		ipif_walk_init, ipif_walk_step, NULL },
   1695   9089  Vasumathi 	{ "ipif_list", "walk the linked list of ipif structures "
   1696   9089  Vasumathi 		"for a given ill",
   1697   9089  Vasumathi 		ip_list_walk_init, ip_list_walk_step,
   1698   9089  Vasumathi 		ip_list_walk_fini, &ipif_walk_arg },
   1699   9089  Vasumathi 	{ "srcid", "walk list of srcid_map structures for all stacks",
   1700   9089  Vasumathi 		ip_stacks_common_walk_init, srcid_walk_step, NULL },
   1701   9089  Vasumathi 	{ "srcid_list", "walk list of srcid_map structures for a stack",
   1702   9089  Vasumathi 		ip_list_walk_init, ip_list_walk_step, ip_list_walk_fini,
   1703   9089  Vasumathi 		&srcid_walk_arg },
   1704      0     stevel 	{ "ire", "walk active ire_t structures",
   1705      0     stevel 		ire_walk_init, ire_walk_step, NULL },
   1706   3448   dh155122 	{ "ire_next", "walk ire_t structures in the ctable",
   1707   3448   dh155122 		ire_next_walk_init, ire_next_walk_step, NULL },
   1708  11042       Erik 	{ "nce", "walk active nce_t structures",
   1709  11042       Erik 		nce_walk_init, nce_walk_step, NULL },
   1710  11042       Erik 	{ "dce", "walk active dce_t structures",
   1711  11042       Erik 		dce_walk_init, dce_walk_step, NULL },
   1712   3448   dh155122 	{ "ip_stacks", "walk all the ip_stack_t",
   1713   3448   dh155122 		ip_stacks_walk_init, ip_stacks_walk_step, NULL },
   1714   5023   carlsonj 	{ "th_hash", "walk all the th_hash_t entries",
   1715   5023   carlsonj 		th_hash_walk_init, th_hash_walk_step, NULL },
   1716  11042       Erik 	{ "ncec", "walk list of ncec structures for all stacks",
   1717  11042       Erik 		ip_stacks_common_walk_init, ncec_walk_step, NULL },
   1718  11042       Erik 	{ "ncec_stack", "walk list of ncec structures",
   1719  11042       Erik 		ncec_stack_walk_init, ncec_stack_walk_step,
   1720  11042       Erik 		ncec_stack_walk_fini},
   1721   9089  Vasumathi 	{ "udp_hash", "walk list of conn_t structures in ips_ipcl_udp_fanout",
   1722   9089  Vasumathi 		ipcl_hash_walk_init, ipcl_hash_walk_step,
   1723   9089  Vasumathi 		ipcl_hash_walk_fini, &udp_hash_arg},
   1724   9089  Vasumathi 	{ "conn_hash", "walk list of conn_t structures in ips_ipcl_conn_fanout",
   1725   9089  Vasumathi 		ipcl_hash_walk_init, ipcl_hash_walk_step,
   1726   9089  Vasumathi 		ipcl_hash_walk_fini, &conn_hash_arg},
   1727   9089  Vasumathi 	{ "bind_hash", "walk list of conn_t structures in ips_ipcl_bind_fanout",
   1728   9089  Vasumathi 		ipcl_hash_walk_init, ipcl_hash_walk_step,
   1729   9089  Vasumathi 		ipcl_hash_walk_fini, &bind_hash_arg},
   1730   9089  Vasumathi 	{ "proto_hash", "walk list of conn_t structures in "
   1731   9089  Vasumathi 	    "ips_ipcl_proto_fanout",
   1732   9089  Vasumathi 		ipcl_hash_walk_init, ipcl_hash_walk_step,
   1733   9089  Vasumathi 		ipcl_hash_walk_fini, &proto_hash_arg},
   1734   9089  Vasumathi 	{ "proto_v6_hash", "walk list of conn_t structures in "
   1735   9089  Vasumathi 	    "ips_ipcl_proto_fanout_v6",
   1736   9089  Vasumathi 		ipcl_hash_walk_init, ipcl_hash_walk_step,
   1737   9089  Vasumathi 		ipcl_hash_walk_fini, &proto_v6_hash_arg},
   1738  10946   Sangeeta 	{ "ilb_stacks", "walk ilb_stack_t",
   1739  10946   Sangeeta 		ip_stacks_walk_init, ilb_stacks_walk_step, NULL },
   1740  10946   Sangeeta 	{ "ilb_rules", "walk ilb rules in a given ilb_stack_t",
   1741  10946   Sangeeta 		ilb_rules_walk_init, ilb_rules_walk_step, NULL },
   1742  10946   Sangeeta 	{ "ilb_servers", "walk server in a given ilb_rule_t",
   1743  10946   Sangeeta 		ilb_servers_walk_init, ilb_servers_walk_step, NULL },
   1744  10946   Sangeeta 	{ "ilb_nat_src", "walk NAT source table of a given ilb_stack_t",
   1745  10946   Sangeeta 		ilb_nat_src_walk_init, ilb_nat_src_walk_step,
   1746  10946   Sangeeta 		ilb_common_walk_fini },
   1747  10946   Sangeeta 	{ "ilb_conns", "walk NAT table of a given ilb_stack_t",
   1748  10946   Sangeeta 		ilb_conn_walk_init, ilb_conn_walk_step, ilb_common_walk_fini },
   1749  10946   Sangeeta 	{ "ilb_stickys", "walk sticky table of a given ilb_stack_t",
   1750  10946   Sangeeta 		ilb_sticky_walk_init, ilb_sticky_walk_step,
   1751  10946   Sangeeta 		ilb_common_walk_fini },
   1752      0     stevel 	{ NULL }
   1753      0     stevel };
   1754      0     stevel 
   1755      0     stevel static const mdb_qops_t ip_qops = { ip_qinfo, ip_rnext, ip_wnext };
   1756      0     stevel static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
   1757      0     stevel 
   1758      0     stevel const mdb_modinfo_t *
   1759      0     stevel _mdb_init(void)
   1760      0     stevel {
   1761      0     stevel 	GElf_Sym sym;
   1762      0     stevel 
   1763   2546   carlsonj 	if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0)
   1764      0     stevel 		mdb_qops_install(&ip_qops, (uintptr_t)sym.st_value);
   1765      0     stevel 
   1766      0     stevel 	return (&modinfo);
   1767      0     stevel }
   1768      0     stevel 
   1769      0     stevel void
   1770      0     stevel _mdb_fini(void)
   1771      0     stevel {
   1772      0     stevel 	GElf_Sym sym;
   1773      0     stevel 
   1774   2546   carlsonj 	if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0)
   1775      0     stevel 		mdb_qops_remove(&ip_qops, (uintptr_t)sym.st_value);
   1776      0     stevel }
   1777   5940    sowmini 
   1778   5940    sowmini static char *
   1779  11042       Erik ncec_state(int ncec_state)
   1780   5940    sowmini {
   1781  11042       Erik 	switch (ncec_state) {
   1782   5940    sowmini 	case ND_UNCHANGED:
   1783   5940    sowmini 		return ("unchanged");
   1784   5940    sowmini 	case ND_INCOMPLETE:
   1785   5940    sowmini 		return ("incomplete");
   1786   5940    sowmini 	case ND_REACHABLE:
   1787   5940    sowmini 		return ("reachable");
   1788   5940    sowmini 	case ND_STALE:
   1789   5940    sowmini 		return ("stale");
   1790   5940    sowmini 	case ND_DELAY:
   1791   5940    sowmini 		return ("delay");
   1792   5940    sowmini 	case ND_PROBE:
   1793   5940    sowmini 		return ("probe");
   1794   5940    sowmini 	case ND_UNREACHABLE:
   1795   5940    sowmini 		return ("unreach");
   1796   5940    sowmini 	case ND_INITIAL:
   1797   5940    sowmini 		return ("initial");
   1798   5940    sowmini 	default:
   1799   5940    sowmini 		return ("??");
   1800   5940    sowmini 	}
   1801   5940    sowmini }
   1802   5940    sowmini 
   1803   5940    sowmini static char *
   1804  11042       Erik ncec_l2_addr(const ncec_t *ncec, const ill_t *ill)
   1805  11042       Erik {
   1806  11042       Erik 	uchar_t *h;
   1807  11042       Erik 	static char addr_buf[L2MAXADDRSTRLEN];
   1808  11042       Erik 
   1809  11042       Erik 	if (ncec->ncec_lladdr == NULL) {
   1810  11042       Erik 		return ("None");
   1811  11042       Erik 	}
   1812  11042       Erik 
   1813  11042       Erik 	if (ill->ill_net_type == IRE_IF_RESOLVER) {
   1814  11042       Erik 
   1815  11042       Erik 		if (ill->ill_phys_addr_length == 0)
   1816  11042       Erik 			return ("None");
   1817  11042       Erik 		h = mdb_zalloc(ill->ill_phys_addr_length, UM_SLEEP);
   1818  11042       Erik 		if (mdb_vread(h, ill->ill_phys_addr_length,
   1819  11042       Erik 		    (uintptr_t)ncec->ncec_lladdr) == -1) {
   1820  11042       Erik 			mdb_warn("failed to read hwaddr at %p",
   1821  11042       Erik 			    ncec->ncec_lladdr);
   1822  11042       Erik 			return ("Unknown");
   1823  11042       Erik 		}
   1824  11042       Erik 		mdb_mac_addr(h, ill->ill_phys_addr_length,
   1825  11042       Erik 		    addr_buf, sizeof (addr_buf));
   1826  11042       Erik 	} else {
   1827  11042       Erik 		return ("None");
   1828  11042       Erik 	}
   1829  11042       Erik 	mdb_free(h, ill->ill_phys_addr_length);
   1830  11042       Erik 	return (addr_buf);
   1831  11042       Erik }
   1832  11042       Erik 
   1833  11042       Erik static char *
   1834   5940    sowmini nce_l2_addr(const nce_t *nce, const ill_t *ill)
   1835   5940    sowmini {
   1836   5940    sowmini 	uchar_t *h;
   1837   5940    sowmini 	static char addr_buf[L2MAXADDRSTRLEN];
   1838   5940    sowmini 	mblk_t mp;
   1839   5940    sowmini 	size_t mblen;
   1840   5940    sowmini 
   1841  11042       Erik 	if (nce->nce_dlur_mp == NULL)
   1842   5940    sowmini 		return ("None");
   1843   5940    sowmini 
   1844   5940    sowmini 	if (ill->ill_net_type == IRE_IF_RESOLVER) {
   1845   5940    sowmini 		if (mdb_vread(&mp, sizeof (mblk_t),
   1846  11042       Erik 		    (uintptr_t)nce->nce_dlur_mp) == -1) {
   1847  11042       Erik 			mdb_warn("failed to read nce_dlur_mp at %p",
   1848  11042       Erik 			    nce->nce_dlur_mp);
   1849  11042       Erik 			return ("None");
   1850   5940    sowmini 		}
   1851  11042       Erik 		if (ill->ill_phys_addr_length == 0)
   1852   5940    sowmini 			return ("None");
   1853   5940    sowmini 		mblen = mp.b_wptr - mp.b_rptr;
   1854   5940    sowmini 		if (mblen > (sizeof (dl_unitdata_req_t) + MAX_SAP_LEN) ||
   1855  11042       Erik 		    ill->ill_phys_addr_length > MAX_SAP_LEN ||
   1856  11042       Erik 		    (NCE_LL_ADDR_OFFSET(ill) +
   1857  11042       Erik 		    ill->ill_phys_addr_length) > mblen) {
   1858  11042       Erik 			return ("Unknown");
   1859   5940    sowmini 		}
   1860   5940    sowmini 		h = mdb_zalloc(mblen, UM_SLEEP);
   1861   5940    sowmini 		if (mdb_vread(h, mblen, (uintptr_t)(mp.b_rptr)) == -1) {
   1862   5940    sowmini 			mdb_warn("failed to read hwaddr at %p",
   1863   5940    sowmini 			    mp.b_rptr + NCE_LL_ADDR_OFFSET(ill));
   1864   5940    sowmini 			return ("Unknown");
   1865   5940    sowmini 		}
   1866  11042       Erik 		mdb_mac_addr(h + NCE_LL_ADDR_OFFSET(ill),
   1867  11042       Erik 		    ill->ill_phys_addr_length, addr_buf, sizeof (addr_buf));
   1868   5940    sowmini 	} else {
   1869   5940    sowmini 		return ("None");
   1870   5940    sowmini 	}
   1871   5940    sowmini 	mdb_free(h, mblen);
   1872   5940    sowmini 	return (addr_buf);
   1873   5940    sowmini }
   1874   5940    sowmini 
   1875   5940    sowmini static void
   1876  11042       Erik ncec_header(uint_t flags)
   1877   5940    sowmini {
   1878   5940    sowmini 	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) {
   1879   5940    sowmini 
   1880   5940    sowmini 		mdb_printf("%<u>%?s %-20s %-10s %-8s %-5s %s%</u>\n",
   1881   5940    sowmini 		    "ADDR", "HW_ADDR", "STATE", "FLAGS", "ILL", "IP ADDR");
   1882   5940    sowmini 	}
   1883   5940    sowmini }
   1884   5940    sowmini 
   1885   5940    sowmini int
   1886  11042       Erik ncec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1887   5940    sowmini {
   1888  11042       Erik 	ncec_t ncec;
   1889  11042       Erik 	ncec_cbdata_t id;
   1890   5940    sowmini 	int ipversion = 0;
   1891   5940    sowmini 	const char *opt_P = NULL;
   1892   5940    sowmini 
   1893   5940    sowmini 	if (mdb_getopts(argc, argv,
   1894   5940    sowmini 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
   1895   5940    sowmini 		return (DCMD_USAGE);
   1896   5940    sowmini 
   1897   5940    sowmini 	if (opt_P != NULL) {
   1898   5940    sowmini 		if (strcmp("v4", opt_P) == 0) {
   1899   5940    sowmini 			ipversion = IPV4_VERSION;
   1900   5940    sowmini 		} else if (strcmp("v6", opt_P) == 0) {
   1901   5940    sowmini 			ipversion = IPV6_VERSION;
   1902   5940    sowmini 		} else {
   1903   5940    sowmini 			mdb_warn("invalid protocol '%s'\n", opt_P);
   1904   5940    sowmini 			return (DCMD_USAGE);
   1905   5940    sowmini 		}
   1906   5940    sowmini 	}
   1907   5940    sowmini 
   1908   5940    sowmini 	if (flags & DCMD_ADDRSPEC) {
   1909   5940    sowmini 
   1910  11042       Erik 		if (mdb_vread(&ncec, sizeof (ncec_t), addr) == -1) {
   1911  11042       Erik 			mdb_warn("failed to read ncec at %p\n", addr);
   1912   5940    sowmini 			return (DCMD_ERR);
   1913   5940    sowmini 		}
   1914  11042       Erik 		if (ipversion != 0 && ncec.ncec_ipversion != ipversion) {
   1915   5940    sowmini 			mdb_printf("IP Version mismatch\n");
   1916   5940    sowmini 			return (DCMD_ERR);
   1917   5940    sowmini 		}
   1918  11042       Erik 		ncec_header(flags);
   1919  11042       Erik 		return (ncec_format(addr, &ncec, ipversion));
   1920   5940    sowmini 
   1921   5940    sowmini 	} else {
   1922  11042       Erik 		id.ncec_addr = addr;
   1923  11042       Erik 		id.ncec_ipversion = ipversion;
   1924  11042       Erik 		ncec_header(flags);
   1925  11042       Erik 		if (mdb_walk("ncec", (mdb_walk_cb_t)ncec_cb, &id) == -1) {
   1926  11042       Erik 			mdb_warn("failed to walk ncec table\n");
   1927   5940    sowmini 			return (DCMD_ERR);
   1928   5940    sowmini 		}
   1929   5940    sowmini 	}
   1930   5940    sowmini 	return (DCMD_OK);
   1931   5940    sowmini }
   1932   5940    sowmini 
   1933   5940    sowmini static int
   1934  11042       Erik ncec_format(uintptr_t addr, const ncec_t *ncec, int ipversion)
   1935   5940    sowmini {
   1936  11042       Erik 	static const mdb_bitmask_t ncec_flags[] = {
   1937  11042       Erik 		{ "P",	NCE_F_NONUD,		NCE_F_NONUD },
   1938   5940    sowmini 		{ "R",	NCE_F_ISROUTER,		NCE_F_ISROUTER	},
   1939   5940    sowmini 		{ "N",	NCE_F_NONUD,		NCE_F_NONUD	},
   1940   5940    sowmini 		{ "A",	NCE_F_ANYCAST,		NCE_F_ANYCAST	},
   1941   5940    sowmini 		{ "C",	NCE_F_CONDEMNED,	NCE_F_CONDEMNED	},
   1942   5940    sowmini 		{ "U",	NCE_F_UNSOL_ADV,	NCE_F_UNSOL_ADV },
   1943   5940    sowmini 		{ "B",	NCE_F_BCAST,		NCE_F_BCAST	},
   1944   5940    sowmini 		{ NULL,	0,			0		}
   1945   5940    sowmini 	};
   1946  11042       Erik #define	NCE_MAX_FLAGS	(sizeof (ncec_flags) / sizeof (mdb_bitmask_t))
   1947   5940    sowmini 	struct in_addr nceaddr;
   1948   5940    sowmini 	ill_t ill;
   1949   5940    sowmini 	char ill_name[LIFNAMSIZ];
   1950   5940    sowmini 	char flagsbuf[NCE_MAX_FLAGS];
   1951   5940    sowmini 
   1952  11042       Erik 	if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ncec->ncec_ill) == -1) {
   1953  11042       Erik 		mdb_warn("failed to read ncec_ill at %p",
   1954  11042       Erik 		    ncec->ncec_ill);
   1955   5940    sowmini 		return (DCMD_ERR);
   1956   5940    sowmini 	}
   1957   5940    sowmini 
   1958   5940    sowmini 	(void) mdb_readstr(ill_name, MIN(LIFNAMSIZ, ill.ill_name_length),
   1959   5940    sowmini 	    (uintptr_t)ill.ill_name);
   1960   5940    sowmini 
   1961   5940    sowmini 	mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%hb",
   1962  11042       Erik 	    ncec->ncec_flags, ncec_flags);
   1963   5940    sowmini 
   1964  11042       Erik 	if (ipversion != 0 && ncec->ncec_ipversion != ipversion)
   1965   5940    sowmini 		return (DCMD_OK);
   1966   5940    sowmini 
   1967  11042       Erik 	if (ncec->ncec_ipversion == IPV4_VERSION) {
   1968  11042       Erik 		IN6_V4MAPPED_TO_INADDR(&ncec->ncec_addr, &nceaddr);
   1969   5940    sowmini 		mdb_printf("%?p %-20s %-10s "
   1970   5940    sowmini 		    "%-8s "
   1971   5940    sowmini 		    "%-5s %I\n",
   1972  11042       Erik 		    addr, ncec_l2_addr(ncec, &ill),
   1973  11042       Erik 		    ncec_state(ncec->ncec_state),
   1974   5940    sowmini 		    flagsbuf,
   1975   5940    sowmini 		    ill_name, nceaddr.s_addr);
   1976   5940    sowmini 	} else {
   1977   5940    sowmini 		mdb_printf("%?p %-20s %-10s %-8s %-5s %N\n",
   1978  11042       Erik 		    addr,  ncec_l2_addr(ncec, &ill),
   1979  11042       Erik 		    ncec_state(ncec->ncec_state),
   1980   5940    sowmini 		    flagsbuf,
   1981  11042       Erik 		    ill_name, &ncec->ncec_addr);
   1982   5940    sowmini 	}
   1983   5940    sowmini 
   1984   5940    sowmini 	return (DCMD_OK);
   1985   5940    sowmini }
   1986   5940    sowmini 
   1987   5940    sowmini static uintptr_t
   1988  11042       Erik ncec_get_next_hash_tbl(uintptr_t start, int *index, struct ndp_g_s ndp)
   1989   5940    sowmini {
   1990   5940    sowmini 	uintptr_t addr = start;
   1991   5940    sowmini 	int i = *index;
   1992   5940    sowmini 
   1993   5940    sowmini 	while (addr == NULL) {
   1994   5940    sowmini 
   1995   5940    sowmini 		if (++i >= NCE_TABLE_SIZE)
   1996   5940    sowmini 			break;
   1997   5940    sowmini 		addr = (uintptr_t)ndp.nce_hash_tbl[i];
   1998   5940    sowmini 	}
   1999   5940    sowmini 	*index = i;
   2000   5940    sowmini 	return (addr);
   2001   5940    sowmini }
   2002   5940    sowmini 
   2003   5940    sowmini static int
   2004  11042       Erik ncec_walk_step(mdb_walk_state_t *wsp)
   2005   5940    sowmini {
   2006   5940    sowmini 	uintptr_t kaddr4, kaddr6;
   2007   5940    sowmini 
   2008   5940    sowmini 	kaddr4 = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ndp4);
   2009   5940    sowmini 	kaddr6 = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ndp6);
   2010   5940    sowmini 
   2011   5940    sowmini 	if (mdb_vread(&kaddr4, sizeof (kaddr4), kaddr4) == -1) {
   2012   5940    sowmini 		mdb_warn("can't read ips_ip_cache_table at %p", kaddr4);
   2013   5940    sowmini 		return (WALK_ERR);
   2014   5940    sowmini 	}
   2015   5940    sowmini 	if (mdb_vread(&kaddr6, sizeof (kaddr6), kaddr6) == -1) {
   2016   5940    sowmini 		mdb_warn("can't read ips_ip_cache_table at %p", kaddr6);
   2017   5940    sowmini 		return (WALK_ERR);
   2018   5940    sowmini 	}
   2019  11042       Erik 	if (mdb_pwalk("ncec_stack", wsp->walk_callback, wsp->walk_cbdata,
   2020   5940    sowmini 	    kaddr4) == -1) {
   2021  11042       Erik 		mdb_warn("couldn't walk 'ncec_stack' for ips_ndp4 %p",
   2022   5940    sowmini 		    kaddr4);
   2023   5940    sowmini 		return (WALK_ERR);
   2024   5940    sowmini 	}
   2025  11042       Erik 	if (mdb_pwalk("ncec_stack", wsp->walk_callback,
   2026   5940    sowmini 	    wsp->walk_cbdata, kaddr6) == -1) {
   2027  11042       Erik 		mdb_warn("couldn't walk 'ncec_stack' for ips_ndp6 %p",
   2028   5940    sowmini 		    kaddr6);
   2029   5940    sowmini 		return (WALK_ERR);
   2030   5940    sowmini 	}
   2031   5940    sowmini 	return (WALK_NEXT);
   2032   5940    sowmini }
   2033   5940    sowmini 
   2034   9089  Vasumathi static uintptr_t
   2035   9089  Vasumathi ipcl_hash_get_next_connf_tbl(ipcl_hash_walk_data_t *iw)
   2036   9089  Vasumathi {
   2037   9089  Vasumathi 	struct connf_s connf;
   2038   9089  Vasumathi 	uintptr_t addr = NULL, next;
   2039   9089  Vasumathi 	int index = iw->connf_tbl_index;
   2040   9089  Vasumathi 
   2041   9089  Vasumathi 	do {
   2042   9089  Vasumathi 		next = iw->hash_tbl + index * sizeof (struct connf_s);
   2043   9089  Vasumathi 		if (++index >= iw->hash_tbl_size) {
   2044   9089  Vasumathi 			addr = NULL;
   2045   9089  Vasumathi 			break;
   2046   9089  Vasumathi 		}
   2047   9089  Vasumathi 		if (mdb_vread(&connf, sizeof (struct connf_s), next) == -1)  {
   2048   9089  Vasumathi 			mdb_warn("failed to read conn_t at %p", next);
   2049   9089  Vasumathi 			return (NULL);
   2050   9089  Vasumathi 		}
   2051   9089  Vasumathi 		addr = (uintptr_t)connf.connf_head;
   2052   9089  Vasumathi 	} while (addr == NULL);
   2053   9089  Vasumathi 	iw->connf_tbl_index = index;
   2054   9089  Vasumathi 	return (addr);
   2055   9089  Vasumathi }
   2056   9089  Vasumathi 
   2057   9089  Vasumathi static int
   2058   9089  Vasumathi ipcl_hash_walk_init(mdb_walk_state_t *wsp)
   2059   9089  Vasumathi {
   2060   9089  Vasumathi 	const hash_walk_arg_t *arg = wsp->walk_arg;
   2061   9089  Vasumathi 	ipcl_hash_walk_data_t *iw;
   2062   9089  Vasumathi 	uintptr_t tbladdr;
   2063   9089  Vasumathi 	uintptr_t sizeaddr;
   2064   9089  Vasumathi 
   2065   9089  Vasumathi 	iw = mdb_alloc(sizeof (ipcl_hash_walk_data_t), UM_SLEEP);
   2066   9089  Vasumathi 	iw->conn = mdb_alloc(sizeof (conn_t), UM_SLEEP);
   2067   9089  Vasumathi 	tbladdr = wsp->walk_addr + arg->tbl_off;
   2068   9089  Vasumathi 	sizeaddr = wsp->walk_addr + arg->size_off;
   2069   9089  Vasumathi 
   2070   9089  Vasumathi 	if (mdb_vread(&iw->hash_tbl, sizeof (uintptr_t), tbladdr) == -1) {
   2071   9089  Vasumathi 		mdb_warn("can't read fanout table addr at %p", tbladdr);
   2072   9089  Vasumathi 		mdb_free(iw->conn, sizeof (conn_t));
   2073   9089  Vasumathi 		mdb_free(iw, sizeof (ipcl_hash_walk_data_t));
   2074   9089  Vasumathi 		return (WALK_ERR);
   2075   9089  Vasumathi 	}
   2076  11042       Erik 	if (arg->tbl_off == OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v4) ||
   2077   9089  Vasumathi 	    arg->tbl_off == OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v6)) {
   2078   9089  Vasumathi 		iw->hash_tbl_size = IPPROTO_MAX;
   2079   9089  Vasumathi 	} else {
   2080   9089  Vasumathi 		if (mdb_vread(&iw->hash_tbl_size, sizeof (int),
   2081   9089  Vasumathi 		    sizeaddr) == -1) {
   2082   9089  Vasumathi 			mdb_warn("can't read fanout table size addr at %p",
   2083   9089  Vasumathi 			    sizeaddr);
   2084   9089  Vasumathi 			mdb_free(iw->conn, sizeof (conn_t));
   2085   9089  Vasumathi 			mdb_free(iw, sizeof (ipcl_hash_walk_data_t));
   2086   9089  Vasumathi 			return (WALK_ERR);
   2087   9089  Vasumathi 		}
   2088   9089  Vasumathi 	}
   2089   9089  Vasumathi 	iw->connf_tbl_index = 0;
   2090   9089  Vasumathi 	wsp->walk_addr = ipcl_hash_get_next_connf_tbl(iw);
   2091   9089  Vasumathi 	wsp->walk_data = iw;
   2092   9089  Vasumathi 
   2093   9089  Vasumathi 	if (wsp->walk_addr != NULL)
   2094   9089  Vasumathi 		return (WALK_NEXT);
   2095   9089  Vasumathi 	else
   2096   9089  Vasumathi 		return (WALK_DONE);
   2097   9089  Vasumathi }
   2098   9089  Vasumathi 
   2099   9089  Vasumathi static int
   2100   9089  Vasumathi ipcl_hash_walk_step(mdb_walk_state_t *wsp)
   2101   9089  Vasumathi {
   2102   9089  Vasumathi 	uintptr_t addr = wsp->walk_addr;
   2103   9089  Vasumathi 	ipcl_hash_walk_data_t *iw = wsp->walk_data;
   2104   9089  Vasumathi 	conn_t *conn = iw->conn;
   2105   9089  Vasumathi 	int ret = WALK_DONE;
   2106   9089  Vasumathi 
   2107   9089  Vasumathi 	while (addr != NULL) {
   2108   9089  Vasumathi 		if (mdb_vread(conn, sizeof (conn_t), addr) == -1) {
   2109   9089  Vasumathi 			mdb_warn("failed to read conn_t at %p", addr);
   2110   9089  Vasumathi 			return (WALK_ERR);
   2111   9089  Vasumathi 		}
   2112   9089  Vasumathi 		ret = wsp->walk_callback(addr, iw, wsp->walk_cbdata);
   2113   9089  Vasumathi 		if (ret != WALK_NEXT)
   2114   9089  Vasumathi 			break;
   2115   9089  Vasumathi 		addr = (uintptr_t)conn->conn_next;
   2116   9089  Vasumathi 	}
   2117   9089  Vasumathi 	if (ret == WALK_NEXT) {
   2118   9089  Vasumathi 		wsp->walk_addr = ipcl_hash_get_next_connf_tbl(iw);
   2119   9089  Vasumathi 
   2120   9089  Vasumathi 		if (wsp->walk_addr != NULL)
   2121   9089  Vasumathi 			return (WALK_NEXT);
   2122   9089  Vasumathi 		else
   2123   9089  Vasumathi 			return (WALK_DONE);
   2124   9089  Vasumathi 	}
   2125   9089  Vasumathi 
   2126   9089  Vasumathi 	return (ret);
   2127   9089  Vasumathi }
   2128   9089  Vasumathi 
   2129   9089  Vasumathi static void
   2130   9089  Vasumathi ipcl_hash_walk_fini(mdb_walk_state_t *wsp)
   2131   9089  Vasumathi {
   2132   9089  Vasumathi 	ipcl_hash_walk_data_t *iw = wsp->walk_data;
   2133   9089  Vasumathi 
   2134   9089  Vasumathi 	mdb_free(iw->conn, sizeof (conn_t));
   2135   9089  Vasumathi 	mdb_free(iw, sizeof (ipcl_hash_walk_data_t));
   2136   9089  Vasumathi }
   2137   9089  Vasumathi 
   2138   5940    sowmini /*
   2139   5940    sowmini  * Called with walk_addr being the address of ips_ndp{4,6}
   2140   5940    sowmini  */
   2141   5940    sowmini static int
   2142  11042       Erik ncec_stack_walk_init(mdb_walk_state_t *wsp)
   2143   5940    sowmini {
   2144  11042       Erik 	ncec_walk_data_t *nw;
   2145   5940    sowmini 
   2146   5940    sowmini 	if (wsp->walk_addr == NULL) {
   2147  11042       Erik 		mdb_warn("ncec_stack requires ndp_g_s address\n");
   2148   5940    sowmini 		return (WALK_ERR);
   2149   5940    sowmini 	}
   2150   5940    sowmini 
   2151  11042       Erik 	nw = mdb_alloc(sizeof (ncec_walk_data_t), UM_SLEEP);
   2152   5940    sowmini 
   2153  11042       Erik 	if (mdb_vread(&nw->ncec_ip_ndp, sizeof (struct ndp_g_s),
   2154   5940    sowmini 	    wsp->walk_addr) == -1) {
   2155   5940    sowmini 		mdb_warn("failed to read 'ip_ndp' at %p",
   2156   5940    sowmini 		    wsp->walk_addr);
   2157  11042       Erik 		mdb_free(nw, sizeof (ncec_walk_data_t));
   2158   5940    sowmini 		return (WALK_ERR);
   2159   5940    sowmini 	}
   2160   5940    sowmini 
   2161  11042       Erik 	/*
   2162  11042       Erik 	 * ncec_get_next_hash_tbl() starts at ++i , so initialize index to -1
   2163  11042       Erik 	 */
   2164  11042       Erik 	nw->ncec_hash_tbl_index = -1;
   2165  11042       Erik 	wsp->walk_addr = ncec_get_next_hash_tbl(NULL,
   2166  11042       Erik 	    &nw->ncec_hash_tbl_index, nw->ncec_ip_ndp);
   2167   5940    sowmini 	wsp->walk_data = nw;
   2168   5940    sowmini 
   2169   5940    sowmini 	return (WALK_NEXT);
   2170   5940    sowmini }
   2171   5940    sowmini 
   2172   5940    sowmini static int
   2173  11042       Erik ncec_stack_walk_step(mdb_walk_state_t *wsp)
   2174   5940    sowmini {
   2175   5940    sowmini 	uintptr_t addr = wsp->walk_addr;
   2176  11042       Erik 	ncec_walk_data_t *nw = wsp->walk_data;
   2177   5940    sowmini 
   2178   5940    sowmini 	if (addr == NULL)
   2179   5940    sowmini 		return (WALK_DONE);
   2180   5940    sowmini 
   2181  11042       Erik 	if (mdb_vread(&nw->ncec, sizeof (ncec_t), addr) == -1) {
   2182  11042       Erik 		mdb_warn("failed to read ncec_t at %p", addr);
   2183   5940    sowmini 		return (WALK_ERR);
   2184   5940    sowmini 	}
   2185   5940    sowmini 
   2186  11042       Erik 	wsp->walk_addr = (uintptr_t)nw->ncec.ncec_next;
   2187   5940    sowmini 
   2188  11042       Erik 	wsp->walk_addr = ncec_get_next_hash_tbl(wsp->walk_addr,
   2189  11042       Erik 	    &nw->ncec_hash_tbl_index, nw->ncec_ip_ndp);
   2190   5940    sowmini 
   2191   5940    sowmini 	return (wsp->walk_callback(addr, nw, wsp->walk_cbdata));
   2192   5940    sowmini }
   2193   5940    sowmini 
   2194   5940    sowmini static void
   2195  11042       Erik ncec_stack_walk_fini(mdb_walk_state_t *wsp)
   2196   5940    sowmini {
   2197  11042       Erik 	mdb_free(wsp->walk_data, sizeof (ncec_walk_data_t));
   2198   5940    sowmini }
   2199   5940    sowmini 
   2200   5940    sowmini /* ARGSUSED */
   2201   5940    sowmini static int
   2202  11042       Erik ncec_cb(uintptr_t addr, const ncec_walk_data_t *iw, ncec_cbdata_t *id)
   2203   5940    sowmini {
   2204  11042       Erik 	ncec_t ncec;
   2205   5940    sowmini 
   2206  11042       Erik 	if (mdb_vread(&ncec, sizeof (ncec_t), addr) == -1) {
   2207  11042       Erik 		mdb_warn("failed to read ncec at %p", addr);
   2208   5940    sowmini 		return (WALK_NEXT);
   2209   5940    sowmini 	}
   2210  11042       Erik 	(void) ncec_format(addr, &ncec, id->ncec_ipversion);
   2211   5940    sowmini 	return (WALK_NEXT);
   2212   5940    sowmini }
   2213   9089  Vasumathi 
   2214   9089  Vasumathi static int
   2215   9089  Vasumathi ill_walk_init(mdb_walk_state_t *wsp)
   2216   9089  Vasumathi {
   2217   9089  Vasumathi 	if (mdb_layered_walk("illif", wsp) == -1) {
   2218   9089  Vasumathi 		mdb_warn("can't walk 'illif'");
   2219   9089  Vasumathi 		return (WALK_ERR);
   2220   9089  Vasumathi 	}
   2221   9089  Vasumathi 	return (WALK_NEXT);
   2222   9089  Vasumathi }
   2223   9089  Vasumathi 
   2224   9089  Vasumathi static int
   2225   9089  Vasumathi ill_walk_step(mdb_walk_state_t *wsp)
   2226   9089  Vasumathi {
   2227   9089  Vasumathi 	ill_if_t ill_if;
   2228   9089  Vasumathi 
   2229   9089  Vasumathi 	if (mdb_vread(&ill_if, sizeof (ill_if_t), wsp->walk_addr) == -1) {
   2230   9089  Vasumathi 		mdb_warn("can't read ill_if_t at %p", wsp->walk_addr);
   2231   9089  Vasumathi 		return (WALK_ERR);
   2232   9089  Vasumathi 	}
   2233   9089  Vasumathi 	wsp->walk_addr = (uintptr_t)(wsp->walk_addr +
   2234   9089  Vasumathi 	    offsetof(ill_if_t, illif_avl_by_ppa));
   2235   9089  Vasumathi 	if (mdb_pwalk("avl", wsp->walk_callback, wsp->walk_cbdata,
   2236   9089  Vasumathi 	    wsp->walk_addr) == -1) {
   2237   9089  Vasumathi 		mdb_warn("can't walk 'avl'");
   2238   9089  Vasumathi 		return (WALK_ERR);
   2239   9089  Vasumathi 	}
   2240   9089  Vasumathi 
   2241   9089  Vasumathi 	return (WALK_NEXT);
   2242   9089  Vasumathi }
   2243   9089  Vasumathi 
   2244   9089  Vasumathi /* ARGSUSED */
   2245   9089  Vasumathi static int
   2246   9089  Vasumathi ill_cb(uintptr_t addr, const ill_walk_data_t *iw, ill_cbdata_t *id)
   2247   9089  Vasumathi {
   2248   9089  Vasumathi 	ill_t ill;
   2249   9089  Vasumathi 
   2250   9089  Vasumathi 	if (mdb_vread(&ill, sizeof (ill_t), (uintptr_t)addr) == -1) {
   2251   9089  Vasumathi 		mdb_warn("failed to read ill at %p", addr);
   2252   9089  Vasumathi 		return (WALK_NEXT);
   2253   9089  Vasumathi 	}
   2254  11042       Erik 
   2255  11042       Erik 	/* If ip_stack_t is specified, skip ILLs that don't belong to it. */
   2256  11042       Erik 	if (id->ill_ipst != NULL && ill.ill_ipst != id->ill_ipst)
   2257  11042       Erik 		return (WALK_NEXT);
   2258  11042       Erik 
   2259   9089  Vasumathi 	return (ill_format((uintptr_t)addr, &ill, id));
   2260   9089  Vasumathi }
   2261   9089  Vasumathi 
   2262   9089  Vasumathi static void
   2263   9089  Vasumathi ill_header(boolean_t verbose)
   2264   9089  Vasumathi {
   2265   9089  Vasumathi 	if (verbose) {
   2266   9089  Vasumathi 		mdb_printf("%-?s %-8s %3s %-10s %-?s %-?s %-10s%</u>\n",
   2267   9089  Vasumathi 		    "ADDR", "NAME", "VER", "TYPE", "WQ", "IPST", "FLAGS");
   2268   9089  Vasumathi 		mdb_printf("%-?s %4s%4s %-?s\n",
   2269   9089  Vasumathi 		    "PHYINT", "CNT", "", "GROUP");
   2270   9089  Vasumathi 		mdb_printf("%<u>%80s%</u>\n", "");
   2271   9089  Vasumathi 	} else {
   2272   9089  Vasumathi 		mdb_printf("%<u>%-?s %-8s %-3s %-10s %4s %-?s %-10s%</u>\n",
   2273   9089  Vasumathi 		    "ADDR", "NAME", "VER", "TYPE", "CNT", "WQ", "FLAGS");
   2274   9089  Vasumathi 	}
   2275   9089  Vasumathi }
   2276   9089  Vasumathi 
   2277   9089  Vasumathi static int
   2278   9089  Vasumathi ill_format(uintptr_t addr, const void *illptr, void *ill_cb_arg)
   2279   9089  Vasumathi {
   2280   9089  Vasumathi 	ill_t *ill = (ill_t *)illptr;
   2281   9089  Vasumathi 	ill_cbdata_t *illcb = ill_cb_arg;
   2282   9089  Vasumathi 	boolean_t verbose = illcb->verbose;
   2283   9089  Vasumathi 	phyint_t phyi;
   2284   9089  Vasumathi 	static const mdb_bitmask_t fmasks[] = {
   2285   9089  Vasumathi 		{ "R",		PHYI_RUNNING,		PHYI_RUNNING	},
   2286   9089  Vasumathi 		{ "P",		PHYI_PROMISC,		PHYI_PROMISC	},
   2287   9089  Vasumathi 		{ "V",		PHYI_VIRTUAL,		PHYI_VIRTUAL	},
   2288   9089  Vasumathi 		{ "I",		PHYI_IPMP,		PHYI_IPMP	},
   2289   9089  Vasumathi 		{ "f",		PHYI_FAILED,		PHYI_FAILED	},
   2290   9089  Vasumathi 		{ "S",		PHYI_STANDBY,		PHYI_STANDBY	},
   2291   9089  Vasumathi 		{ "i",		PHYI_INACTIVE,		PHYI_INACTIVE	},
   2292   9089  Vasumathi 		{ "O",		PHYI_OFFLINE,		PHYI_OFFLINE	},
   2293   9089  Vasumathi 		{ "T", 		ILLF_NOTRAILERS,	ILLF_NOTRAILERS },
   2294   9089  Vasumathi 		{ "A",		ILLF_NOARP,		ILLF_NOARP	},
   2295   9089  Vasumathi 		{ "M",		ILLF_MULTICAST,		ILLF_MULTICAST	},
   2296   9089  Vasumathi 		{ "F",		ILLF_ROUTER,		ILLF_ROUTER	},
   2297   9089  Vasumathi 		{ "D",		ILLF_NONUD,		ILLF_NONUD	},
   2298   9089  Vasumathi 		{ "X",		ILLF_NORTEXCH,		ILLF_NORTEXCH	},
   2299   9089  Vasumathi 		{ NULL,		0,			0		}
   2300   9089  Vasumathi 	};
   2301   9089  Vasumathi 	static const mdb_bitmask_t v_fmasks[] = {
   2302   9089  Vasumathi 		{ "RUNNING",	PHYI_RUNNING,		PHYI_RUNNING	},
   2303   9089  Vasumathi 		{ "PROMISC",	PHYI_PROMISC,		PHYI_PROMISC	},
   2304   9089  Vasumathi 		{ "VIRTUAL",	PHYI_VIRTUAL,		PHYI_VIRTUAL	},
   2305   9089  Vasumathi 		{ "IPMP",	PHYI_IPMP,		PHYI_IPMP	},
   2306   9089  Vasumathi 		{ "FAILED",	PHYI_FAILED,		PHYI_FAILED	},
   2307   9089  Vasumathi 		{ "STANDBY",	PHYI_STANDBY,		PHYI_STANDBY	},
   2308   9089  Vasumathi 		{ "INACTIVE",	PHYI_INACTIVE,		PHYI_INACTIVE	},
   2309   9089  Vasumathi 		{ "OFFLINE",	PHYI_OFFLINE,		PHYI_OFFLINE	},
   2310   9089  Vasumathi 		{ "NOTRAILER",	ILLF_NOTRAILERS,	ILLF_NOTRAILERS },
   2311   9089  Vasumathi 		{ "NOARP",	ILLF_NOARP,		ILLF_NOARP	},
   2312   9089  Vasumathi 		{ "MULTICAST",	ILLF_MULTICAST,		ILLF_MULTICAST	},
   2313   9089  Vasumathi 		{ "ROUTER",	ILLF_ROUTER,		ILLF_ROUTER	},
   2314   9089  Vasumathi 		{ "NONUD",	ILLF_NONUD,		ILLF_NONUD	},
   2315   9089  Vasumathi 		{ "NORTEXCH",	ILLF_NORTEXCH,		ILLF_NORTEXCH	},
   2316   9089  Vasumathi 		{ NULL,		0,			0		}
   2317   9089  Vasumathi 	};
   2318   9089  Vasumathi 	char ill_name[LIFNAMSIZ];
   2319   9089  Vasumathi 	int cnt;
   2320   9089  Vasumathi 	char *typebuf;
   2321   9089  Vasumathi 	char sbuf[DEFCOLS];
   2322   9089  Vasumathi 	int ipver = illcb->ill_ipversion;
   2323   9089  Vasumathi 
   2324   9089  Vasumathi 	if (ipver != 0) {
   2325   9089  Vasumathi 		if ((ipver == IPV4_VERSION && ill->ill_isv6) ||
   2326   9089  Vasumathi 		    (ipver == IPV6_VERSION && !ill->ill_isv6)) {
   2327   9089  Vasumathi 			return (WALK_NEXT);
   2328   9089  Vasumathi 		}
   2329   9089  Vasumathi 	}
   2330   9089  Vasumathi 	if (mdb_vread(&phyi, sizeof (phyint_t),
   2331   9089  Vasumathi 	    (uintptr_t)ill->ill_phyint) == -1) {
   2332   9089  Vasumathi 		mdb_warn("failed to read ill_phyint at %p",
   2333   9089  Vasumathi 		    (uintptr_t)ill->ill_phyint);
   2334   9089  Vasumathi 		return (WALK_NEXT);
   2335   9089  Vasumathi 	}
   2336   9089  Vasumathi 	(void) mdb_readstr(ill_name, MIN(LIFNAMSIZ, ill->ill_name_length),
   2337   9089  Vasumathi 	    (uintptr_t)ill->ill_name);
   2338   9089  Vasumathi 
   2339   9089  Vasumathi 	switch (ill->ill_type) {
   2340   9089  Vasumathi 	case 0:
   2341   9089  Vasumathi 		typebuf = "LOOPBACK";
   2342   9089  Vasumathi 		break;
   2343   9089  Vasumathi 	case IFT_ETHER:
   2344   9089  Vasumathi 		typebuf = "ETHER";
   2345   9089  Vasumathi 		break;
   2346   9089  Vasumathi 	case IFT_OTHER:
   2347   9089  Vasumathi 		typebuf = "OTHER";
   2348   9089  Vasumathi 		break;
   2349   9089  Vasumathi 	default:
   2350   9089  Vasumathi 		typebuf = NULL;
   2351   9089  Vasumathi 		break;
   2352   9089  Vasumathi 	}
   2353   9089  Vasumathi 	cnt = ill->ill_refcnt + ill->ill_ire_cnt + ill->ill_nce_cnt +
   2354  11042       Erik 	    ill->ill_ilm_cnt + ill->ill_ncec_cnt;
   2355   9089  Vasumathi 	mdb_printf("%-?p %-8s %-3s ",
   2356   9089  Vasumathi 	    addr, ill_name, ill->ill_isv6 ? "v6" : "v4");
   2357   9089  Vasumathi 	if (typebuf != NULL)
   2358   9089  Vasumathi 		mdb_printf("%-10s ", typebuf);
   2359   9089  Vasumathi 	else
   2360   9089  Vasumathi 		mdb_printf("%-10x ", ill->ill_type);
   2361   9089  Vasumathi 	if (verbose) {
   2362   9089  Vasumathi 		mdb_printf("%-?p %-?p %-llb\n",
   2363   9089  Vasumathi 		    ill->ill_wq, ill->ill_ipst,
   2364   9089  Vasumathi 		    ill->ill_flags | phyi.phyint_flags, v_fmasks);
   2365   9089  Vasumathi 		mdb_printf("%-?p %4d%4s %-?p\n",
   2366   9089  Vasumathi 		    ill->ill_phyint, cnt, "", ill->ill_grp);
   2367   9089  Vasumathi 		mdb_snprintf(sbuf, sizeof (sbuf), "%*s %3s",
   2368   9089  Vasumathi 		    sizeof (uintptr_t) * 2, "", "");
   2369   9089  Vasumathi 		mdb_printf("%s|\n%s+--> %3d %-18s "
   2370   9089  Vasumathi 		    "references from active threads\n",
   2371   9089  Vasumathi 		    sbuf, sbuf, ill->ill_refcnt, "ill_refcnt");
   2372   9089  Vasumathi 		mdb_printf("%*s %7d %-18s ires referencing this ill\n",
   2373   9089  Vasumathi 		    strlen(sbuf), "", ill->ill_ire_cnt, "ill_ire_cnt");
   2374   9089  Vasumathi 		mdb_printf("%*s %7d %-18s nces referencing this ill\n",
   2375   9089  Vasumathi 		    strlen(sbuf), "", ill->ill_nce_cnt, "ill_nce_cnt");
   2376  11042       Erik 		mdb_printf("%*s %7d %-18s ncecs referencing this ill\n",
   2377  11042       Erik 		    strlen(sbuf), "", ill->ill_ncec_cnt, "ill_ncec_cnt");
   2378   9089  Vasumathi 		mdb_printf("%*s %7d %-18s ilms referencing this ill\n",
   2379   9089  Vasumathi 		    strlen(sbuf), "", ill->ill_ilm_cnt, "ill_ilm_cnt");
   2380   9089  Vasumathi 	} else {
   2381   9089  Vasumathi 		mdb_printf("%4d %-?p %-llb\n",
   2382   9089  Vasumathi 		    cnt, ill->ill_wq,
   2383   9089  Vasumathi 		    ill->ill_flags | phyi.phyint_flags, fmasks);
   2384   9089  Vasumathi 	}
   2385   9089  Vasumathi 	return (WALK_NEXT);
   2386   9089  Vasumathi }
   2387   9089  Vasumathi 
   2388   9089  Vasumathi static int
   2389   9089  Vasumathi ill(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   2390   9089  Vasumathi {
   2391   9089  Vasumathi 	ill_t ill_data;
   2392   9089  Vasumathi 	ill_cbdata_t id;
   2393   9089  Vasumathi 	int ipversion = 0;
   2394  11042       Erik 	const char *zone_name = NULL;
   2395   9089  Vasumathi 	const char *opt_P = NULL;
   2396   9089  Vasumathi 	uint_t verbose = FALSE;
   2397  11042       Erik 	ip_stack_t *ipst = NULL;
   2398   9089  Vasumathi 
   2399   9089  Vasumathi 	if (mdb_getopts(argc, argv,
   2400   9089  Vasumathi 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
   2401  11042       Erik 	    's', MDB_OPT_STR, &zone_name,
   2402   9089  Vasumathi 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
   2403   9089  Vasumathi 		return (DCMD_USAGE);
   2404  11042       Erik 
   2405  11042       Erik 	/* Follow the specified zone name to find a ip_stack_t*. */
   2406  11042       Erik 	if (zone_name != NULL) {
   2407  11042       Erik 		ipst = zone_to_ips(zone_name);
   2408  11042       Erik 		if (ipst == NULL)
   2409  11042       Erik 			return (DCMD_USAGE);
   2410  11042       Erik 	}
   2411   9089  Vasumathi 
   2412   9089  Vasumathi 	if (opt_P != NULL) {
   2413   9089  Vasumathi 		if (strcmp("v4", opt_P) == 0) {
   2414   9089  Vasumathi 			ipversion = IPV4_VERSION;
   2415   9089  Vasumathi 		} else if (strcmp("v6", opt_P) == 0) {
   2416   9089  Vasumathi 			ipversion = IPV6_VERSION;
   2417   9089  Vasumathi 		} else {
   2418   9089  Vasumathi 			mdb_warn("invalid protocol '%s'\n", opt_P);
   2419   9089  Vasumathi 			return (DCMD_USAGE);
   2420   9089  Vasumathi 		}
   2421   9089  Vasumathi 	}
   2422   9089  Vasumathi 
   2423   9089  Vasumathi 	id.verbose = verbose;
   2424   9089  Vasumathi 	id.ill_addr = addr;
   2425   9089  Vasumathi 	id.ill_ipversion = ipversion;
   2426  11042       Erik 	id.ill_ipst = ipst;
   2427   9089  Vasumathi 
   2428   9089  Vasumathi 	ill_header(verbose);
   2429   9089  Vasumathi 	if (flags & DCMD_ADDRSPEC) {
   2430   9089  Vasumathi 		if (mdb_vread(&ill_data, sizeof (ill_t), addr) == -1) {
   2431   9089  Vasumathi 			mdb_warn("failed to read ill at %p\n", addr);
   2432   9089  Vasumathi 			return (DCMD_ERR);
   2433   9089  Vasumathi 		}
   2434   9089  Vasumathi 		(void) ill_format(addr, &ill_data, &id);
   2435   9089  Vasumathi 	} else {
   2436   9089  Vasumathi 		if (mdb_walk("ill", (mdb_walk_cb_t)ill_cb, &id) == -1) {
   2437   9089  Vasumathi 			mdb_warn("failed to walk ills\n");
   2438   9089  Vasumathi 			return (DCMD_ERR);
   2439   9089  Vasumathi 		}
   2440   9089  Vasumathi 	}
   2441   9089  Vasumathi 	return (DCMD_OK);
   2442   9089  Vasumathi }
   2443   9089  Vasumathi 
   2444   9089  Vasumathi static void
   2445   9089  Vasumathi ill_help(void)
   2446   9089  Vasumathi {
   2447   9089  Vasumathi 	mdb_printf("Prints the following fields: ill ptr, name, "
   2448   9089  Vasumathi 	    "IP version, count, ill type and ill flags.\n"
   2449   9089  Vasumathi 	    "The count field is a sum of individual refcnts and is expanded "
   2450   9089  Vasumathi 	    "with the -v option.\n\n");
   2451   9089  Vasumathi 	mdb_printf("Options:\n");
   2452   9089  Vasumathi 	mdb_printf("\t-P v4 | v6"
   2453   9089  Vasumathi 	    "\tfilter ill structures for the specified protocol\n");
   2454   9089  Vasumathi }
   2455   9089  Vasumathi 
   2456   9089  Vasumathi static int
   2457   9089  Vasumathi ip_list_walk_init(mdb_walk_state_t *wsp)
   2458   9089  Vasumathi {
   2459   9089  Vasumathi 	const ip_list_walk_arg_t *arg = wsp->walk_arg;
   2460   9089  Vasumathi 	ip_list_walk_data_t *iw;
   2461   9089  Vasumathi 	uintptr_t addr = (uintptr_t)(wsp->walk_addr + arg->off);
   2462   9089  Vasumathi 
   2463   9089  Vasumathi 	if (wsp->walk_addr == NULL) {
   2464   9089  Vasumathi 		mdb_warn("only local walks supported\n");
   2465   9089  Vasumathi 		return (WALK_ERR);
   2466   9089  Vasumathi 	}
   2467   9089  Vasumathi 	if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t),
   2468   9089  Vasumathi 	    addr) == -1) {
   2469   9089  Vasumathi 		mdb_warn("failed to read list head at %p", addr);
   2470   9089  Vasumathi 		return (WALK_ERR);
   2471   9089  Vasumathi 	}
   2472   9089  Vasumathi 	iw = mdb_alloc(sizeof (ip_list_walk_data_t), UM_SLEEP);
   2473   9089  Vasumathi 	iw->nextoff = arg->nextp_off;
   2474   9089  Vasumathi 	wsp->walk_data = iw;
   2475   9089  Vasumathi 
   2476   9089  Vasumathi 	return (WALK_NEXT);
   2477   9089  Vasumathi }
   2478   9089  Vasumathi 
   2479   9089  Vasumathi static int
   2480   9089  Vasumathi ip_list_walk_step(mdb_walk_state_t *wsp)
   2481   9089  Vasumathi {
   2482   9089  Vasumathi 	ip_list_walk_data_t *iw = wsp->walk_data;
   2483   9089  Vasumathi 	uintptr_t addr = wsp->walk_addr;
   2484   9089  Vasumathi 
   2485   9089  Vasumathi 	if (addr == NULL)
   2486   9089  Vasumathi 		return (WALK_DONE);
   2487   9089  Vasumathi 	wsp->walk_addr = addr + iw->nextoff;
   2488   9089  Vasumathi 	if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t),
   2489   9089  Vasumathi 	    wsp->walk_addr) == -1) {
   2490   9089  Vasumathi 		mdb_warn("failed to read list node at %p", addr);
   2491   9089  Vasumathi 		return (WALK_ERR);
   2492   9089  Vasumathi 	}
   2493   9089  Vasumathi 	return (wsp->walk_callback(addr, iw, wsp->walk_cbdata));
   2494   9089  Vasumathi }
   2495   9089  Vasumathi 
   2496   9089  Vasumathi static void
   2497   9089  Vasumathi ip_list_walk_fini(mdb_walk_state_t *wsp)
   2498   9089  Vasumathi {
   2499   9089  Vasumathi 	mdb_free(wsp->walk_data, sizeof (ip_list_walk_data_t));
   2500   9089  Vasumathi }
   2501   9089  Vasumathi 
   2502   9089  Vasumathi static int
   2503   9089  Vasumathi ipif_walk_init(mdb_walk_state_t *wsp)
   2504   9089  Vasumathi {
   2505   9089  Vasumathi 	if (mdb_layered_walk("ill", wsp) == -1) {
   2506   9089  Vasumathi 		mdb_warn("can't walk 'ills'");
   2507   9089  Vasumathi 		return (WALK_ERR);
   2508   9089  Vasumathi 	}
   2509   9089  Vasumathi 	return (WALK_NEXT);
   2510   9089  Vasumathi }
   2511   9089  Vasumathi 
   2512   9089  Vasumathi static int
   2513   9089  Vasumathi ipif_walk_step(mdb_walk_state_t *wsp)
   2514   9089  Vasumathi {
   2515   9089  Vasumathi 	if (mdb_pwalk("ipif_list", wsp->walk_callback, wsp->walk_cbdata,
   2516   9089  Vasumathi 	    wsp->walk_addr) == -1) {
   2517   9089  Vasumathi 		mdb_warn("can't walk 'ipif_list'");
   2518   9089  Vasumathi 		return (WALK_ERR);
   2519   9089  Vasumathi 	}
   2520   9089  Vasumathi 
   2521   9089  Vasumathi 	return (WALK_NEXT);
   2522   9089  Vasumathi }
   2523   9089  Vasumathi 
   2524   9089  Vasumathi /* ARGSUSED */
   2525   9089  Vasumathi static int
   2526   9089  Vasumathi ipif_cb(uintptr_t addr, const ipif_walk_data_t *iw, ipif_cbdata_t *id)
   2527   9089  Vasumathi {
   2528   9089  Vasumathi 	ipif_t ipif;
   2529   9089  Vasumathi 
   2530   9089  Vasumathi 	if (mdb_vread(&ipif, sizeof (ipif_t), (uintptr_t)addr) == -1) {
   2531   9089  Vasumathi 		mdb_warn("failed to read ipif at %p", addr);
   2532   9089  Vasumathi 		return (WALK_NEXT);
   2533   9089  Vasumathi 	}
   2534   9089  Vasumathi 	if (mdb_vread(&id->ill, sizeof (ill_t),
   2535   9089  Vasumathi 	    (uintptr_t)ipif.ipif_ill) == -1) {
   2536   9089  Vasumathi 		mdb_warn("failed to read ill at %p", ipif.ipif_ill);
   2537   9089  Vasumathi 		return (WALK_NEXT);
   2538   9089  Vasumathi 	}
   2539   9089  Vasumathi 	(void) ipif_format((uintptr_t)addr, &ipif, id);
   2540   9089  Vasumathi 	return (WALK_NEXT);
   2541   9089  Vasumathi }
   2542   9089  Vasumathi 
   2543   9089  Vasumathi static void
   2544   9089  Vasumathi ipif_header(boolean_t verbose)
   2545   9089  Vasumathi {
   2546   9089  Vasumathi 	if (verbose) {
   2547   9089  Vasumathi 		mdb_printf("%-?s %-10s %-3s %-?s %-8s %-30s\n",
   2548   9089  Vasumathi 		    "ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS");
   2549   9089  Vasumathi 		mdb_printf("%s\n%s\n",
   2550   9089  Vasumathi 		    "LCLADDR", "BROADCAST");
   2551   9089  Vasumathi 		mdb_printf("%<u>%80s%</u>\n", "");
   2552   9089  Vasumathi 	} else {
   2553   9089  Vasumathi 		mdb_printf("%-?s %-10s %6s %-?s %-8s %-30s\n",
   2554   9089  Vasumathi 		    "ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS");
   2555   9089  Vasumathi 		mdb_printf("%s\n%<u>%80s%</u>\n", "LCLADDR", "");
   2556   9089  Vasumathi 	}
   2557   9089  Vasumathi }
   2558   9089  Vasumathi 
   2559   9089  Vasumathi #ifdef _BIG_ENDIAN
   2560   9089  Vasumathi #define	ip_ntohl_32(x)	((x) & 0xffffffff)
   2561   9089  Vasumathi #else
   2562   9089  Vasumathi #define	ip_ntohl_32(x)	(((uint32_t)(x) << 24) | \
   2563   9089  Vasumathi 			(((uint32_t)(x) << 8) & 0xff0000) | \
   2564   9089  Vasumathi 			(((uint32_t)(x) >> 8) & 0xff00) | \
   2565   9089  Vasumathi 			((uint32_t)(x)  >> 24))
   2566   9089  Vasumathi #endif
   2567   9089  Vasumathi 
   2568   9089  Vasumathi int
   2569   9089  Vasumathi mask_to_prefixlen(int af, const in6_addr_t *addr)
   2570   9089  Vasumathi {
   2571   9089  Vasumathi 	int len = 0;
   2572   9089  Vasumathi 	int i;
   2573   9089  Vasumathi 	uint_t mask = 0;
   2574   9089  Vasumathi 
   2575   9089  Vasumathi 	if (af == AF_INET6) {
   2576   9089  Vasumathi 		for (i = 0; i < 4; i++) {
   2577   9089  Vasumathi 			if (addr->s6_addr32[i] == 0xffffffff) {
   2578   9089  Vasumathi 				len += 32;
   2579   9089  Vasumathi 			} else {
   2580   9089  Vasumathi 				mask = addr->s6_addr32[i];
   2581   9089  Vasumathi 				break;
   2582   9089  Vasumathi 			}
   2583   9089  Vasumathi 		}
   2584   9089  Vasumathi 	} else {
   2585   9089  Vasumathi 		mask = V4_PART_OF_V6((*addr));
   2586   9089  Vasumathi 	}
   2587   9089  Vasumathi 	if (mask > 0)
   2588   9089  Vasumathi 		len += (33 - mdb_ffs(ip_ntohl_32(mask)));
   2589   9089  Vasumathi 	return (len);
   2590   9089  Vasumathi }
   2591   9089  Vasumathi 
   2592   9089  Vasumathi static int
   2593   9089  Vasumathi ipif_format(uintptr_t addr, const void *ipifptr, void *ipif_cb_arg)
   2594   9089  Vasumathi {
   2595   9089  Vasumathi 	const ipif_t *ipif = ipifptr;
   2596   9089  Vasumathi 	ipif_cbdata_t *ipifcb = ipif_cb_arg;
   2597   9089  Vasumathi 	boolean_t verbose = ipifcb->verbose;
   2598   9089  Vasumathi 	char ill_name[LIFNAMSIZ];
   2599   9089  Vasumathi 	char buf[LIFNAMSIZ];
   2600   9089  Vasumathi 	int cnt;
   2601   9089  Vasumathi 	static const mdb_bitmask_t sfmasks[] = {
   2602   9089  Vasumathi 		{ "CO",		IPIF_CONDEMNED,		IPIF_CONDEMNED},
   2603   9089  Vasumathi 		{ "CH",		IPIF_CHANGING,		IPIF_CHANGING},
   2604   9089  Vasumathi 		{ "SL",		IPIF_SET_LINKLOCAL,	IPIF_SET_LINKLOCAL},
   2605   9089  Vasumathi 		{ NULL,		0,			0		}
   2606   9089  Vasumathi 	};
   2607   9089  Vasumathi 	static const mdb_bitmask_t fmasks[] = {
   2608   9089  Vasumathi 		{ "UP",		IPIF_UP,		IPIF_UP		},
   2609   9089  Vasumathi 		{ "UNN",	IPIF_UNNUMBERED,	IPIF_UNNUMBERED},
   2610   9089  Vasumathi 		{ "DHCP",	IPIF_DHCPRUNNING,	IPIF_DHCPRUNNING},
   2611   9089  Vasumathi 		{ "PRIV",	IPIF_PRIVATE,		IPIF_PRIVATE},
   2612   9089  Vasumathi 		{ "NOXMT",	IPIF_NOXMIT,		IPIF_NOXMIT},
   2613   9089  Vasumathi 		{ "NOLCL",	IPIF_NOLOCAL,		IPIF_NOLOCAL},
   2614   9089  Vasumathi 		{ "DEPR",	IPIF_DEPRECATED,	IPIF_DEPRECATED},
   2615   9089  Vasumathi 		{ "PREF",	IPIF_PREFERRED,		IPIF_PREFERRED},
   2616   9089  Vasumathi 		{ "TEMP",	IPIF_TEMPORARY,		IPIF_TEMPORARY},
   2617   9089  Vasumathi 		{ "ACONF",	IPIF_ADDRCONF,		IPIF_ADDRCONF},
   2618   9089  Vasumathi 		{ "ANY",	IPIF_ANYCAST,		IPIF_ANYCAST},
   2619   9089  Vasumathi 		{ "NFAIL",	IPIF_NOFAILOVER,	IPIF_NOFAILOVER},
   2620   9089  Vasumathi 		{ NULL,		0,			0		}
   2621   9089  Vasumathi 	};
   2622   9089  Vasumathi 	char flagsbuf[2 * A_CNT(fmasks)];
   2623   9089  Vasumathi 	char bitfields[A_CNT(fmasks)];
   2624   9089  Vasumathi 	char sflagsbuf[A_CNT(sfmasks)];
   2625   9089  Vasumathi 	char sbuf[DEFCOLS], addrstr[INET6_ADDRSTRLEN];
   2626   9089  Vasumathi 	int ipver = ipifcb->ipif_ipversion;
   2627   9089  Vasumathi 	int af;
   2628   9089  Vasumathi 
   2629   9089  Vasumathi 	if (ipver != 0) {
   2630   9089  Vasumathi 		if ((ipver == IPV4_VERSION && ipifcb->ill.ill_isv6) ||
   2631   9089  Vasumathi 		    (ipver == IPV6_VERSION && !ipifcb->ill.ill_isv6)) {
   2632   9089  Vasumathi 			return (WALK_NEXT);
   2633   9089  Vasumathi 		}
   2634   9089  Vasumathi 	}
   2635   9089  Vasumathi 	if ((mdb_readstr(ill_name, MIN(LIFNAMSIZ,
   2636   9089  Vasumathi 	    ipifcb->ill.ill_name_length),
   2637   9089  Vasumathi 	    (uintptr_t)ipifcb->ill.ill_name)) == -1) {
   2638   9089  Vasumathi 		mdb_warn("failed to read ill_name of ill %p\n", ipifcb->ill);
   2639   9089  Vasumathi 		return (WALK_NEXT);
   2640   9089  Vasumathi 	}
   2641   9089  Vasumathi 	if (ipif->ipif_id != 0) {
   2642   9089  Vasumathi 		mdb_snprintf(buf, LIFNAMSIZ, "%s:%d",
   2643   9089  Vasumathi 		    ill_name, ipif->ipif_id);
   2644   9089  Vasumathi 	} else {
   2645   9089  Vasumathi 		mdb_snprintf(buf, LIFNAMSIZ, "%s", ill_name);
   2646   9089  Vasumathi 	}
   2647   9089  Vasumathi 	mdb_snprintf(bitfields, sizeof (bitfields), "%s",
   2648   9089  Vasumathi 	    ipif->ipif_addr_ready ? ",ADR" : "",
   2649   9089  Vasumathi 	    ipif->ipif_was_up ? ",WU" : "",
   2650  11042       Erik 	    ipif->ipif_was_dup ? ",WD" : "");
   2651   9089  Vasumathi 	mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%llb%s",
   2652   9089  Vasumathi 	    ipif->ipif_flags, fmasks, bitfields);
   2653   9089  Vasumathi 	mdb_snprintf(sflagsbuf, sizeof (sflagsbuf), "%b",
   2654   9089  Vasumathi 	    ipif->ipif_state_flags, sfmasks);
   2655   9089  Vasumathi 
   2656  11042       Erik 	cnt = ipif->ipif_refcnt;
   2657   9089  Vasumathi 
   2658   9089  Vasumathi 	if (ipifcb->ill.ill_isv6) {
   2659   9089  Vasumathi 		mdb_snprintf(addrstr, sizeof (addrstr), "%N",
   2660   9089  Vasumathi 		    &ipif->ipif_v6lcl_addr);
   2661   9089  Vasumathi 		af = AF_INET6;
   2662   9089  Vasumathi 	} else {
   2663   9089  Vasumathi 		mdb_snprintf(addrstr, sizeof (addrstr), "%I",
   2664   9089  Vasumathi 		    V4_PART_OF_V6((ipif->ipif_v6lcl_addr)));
   2665   9089  Vasumathi 		af = AF_INET;
   2666   9089  Vasumathi 	}
   2667   9089  Vasumathi 
   2668   9089  Vasumathi 	if (verbose) {
   2669   9089  Vasumathi 		mdb_printf("%-?p %-10s %3d %-?p %-8s %-30s\n",
   2670   9089  Vasumathi 		    addr, buf, cnt, ipif->ipif_ill,
   2671   9089  Vasumathi 		    sflagsbuf, flagsbuf);
   2672   9089  Vasumathi 		mdb_snprintf(sbuf, sizeof (sbuf), "%*s %12s",
   2673   9089  Vasumathi 		    sizeof (uintptr_t) * 2, "", "");
   2674   9089  Vasumathi 		mdb_printf("%s |\n%s +---> %4d %-15s "
   2675   9089  Vasumathi 		    "Active consistent reader cnt\n",
   2676   9089  Vasumathi 		    sbuf, sbuf, ipif->ipif_refcnt, "ipif_refcnt");
   2677   9089  Vasumathi 		mdb_printf("%-s/%d\n",
   2678   9089  Vasumathi 		    addrstr, mask_to_prefixlen(af, &ipif->ipif_v6net_mask));
   2679   9089  Vasumathi 		if (ipifcb->ill.ill_isv6) {
   2680   9089  Vasumathi 			mdb_printf("%-N\n", &ipif->ipif_v6brd_addr);
   2681   9089  Vasumathi 		} else {
   2682   9089  Vasumathi 			mdb_printf("%-I\n",
   2683   9089  Vasumathi 			    V4_PART_OF_V6((ipif->ipif_v6brd_addr)));
   2684   9089  Vasumathi 		}
   2685   9089  Vasumathi 	} else {
   2686   9089  Vasumathi 		mdb_printf("%-?p %-10s %6d %-?p %-8s %-30s\n",
   2687   9089  Vasumathi 		    addr, buf, cnt, ipif->ipif_ill,
   2688   9089  Vasumathi 		    sflagsbuf, flagsbuf);
   2689   9089  Vasumathi 		mdb_printf("%-s/%d\n",
   2690   9089  Vasumathi 		    addrstr, mask_to_prefixlen(af, &ipif->ipif_v6net_mask));
   2691   9089  Vasumathi 	}
   2692   9089  Vasumathi 
   2693   9089  Vasumathi 	return (WALK_NEXT);
   2694   9089  Vasumathi }
   2695   9089  Vasumathi 
   2696   9089  Vasumathi static int
   2697   9089  Vasumathi ipif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   2698   9089  Vasumathi {
   2699   9089  Vasumathi 	ipif_t ipif;
   2700   9089  Vasumathi 	ipif_cbdata_t id;
   2701   9089  Vasumathi 	int ipversion = 0;
   2702   9089  Vasumathi 	const char *opt_P = NULL;
   2703   9089  Vasumathi 	uint_t verbose = FALSE;
   2704   9089  Vasumathi 
   2705   9089  Vasumathi 	if (mdb_getopts(argc, argv,
   2706   9089  Vasumathi 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
   2707   9089  Vasumathi 	    'P', MDB_OPT_STR, &opt_P, NULL) != argc)
   2708   9089  Vasumathi 		return (DCMD_USAGE);
   2709   9089  Vasumathi 
   2710   9089  Vasumathi 	if (opt_P != NULL) {
   2711   9089  Vasumathi 		if (strcmp("v4", opt_P) == 0) {
   2712   9089  Vasumathi 			ipversion = IPV4_VERSION;
   2713   9089  Vasumathi 		} else if (strcmp("v6", opt_P) == 0) {
   2714   9089  Vasumathi 			ipversion = IPV6_VERSION;
   2715   9089  Vasumathi 		} else {
   2716   9089  Vasumathi 			mdb_warn("invalid protocol '%s'\n", opt_P);
   2717   9089  Vasumathi 			return (DCMD_USAGE);
   2718   9089  Vasumathi 		}
   2719   9089  Vasumathi 	}
   2720   9089  Vasumathi 
   2721   9089  Vasumathi 	id.verbose = verbose;
   2722   9089  Vasumathi 	id.ipif_ipversion = ipversion;
   2723   9089  Vasumathi 
   2724   9089  Vasumathi 	if (flags & DCMD_ADDRSPEC) {
   2725   9089  Vasumathi 		if (mdb_vread(&ipif, sizeof (ipif_t), addr) == -1) {
   2726   9089  Vasumathi 			mdb_warn("failed to read ipif at %p\n", addr);
   2727   9089  Vasumathi 			return (DCMD_ERR);
   2728   9089  Vasumathi 		}
   2729   9089  Vasumathi 		ipif_header(verbose);
   2730   9089  Vasumathi 		if (mdb_vread(&id.ill, sizeof (ill_t),
   2731   9089  Vasumathi 		    (uintptr_t)ipif.ipif_ill) == -1) {
   2732   9089  Vasumathi 			mdb_warn("failed to read ill at %p", ipif.ipif_ill);
   2733   9089  Vasumathi 			return (WALK_NEXT);
   2734   9089  Vasumathi 		}
   2735   9089  Vasumathi 		return (ipif_format(addr, &ipif, &id));
   2736   9089  Vasumathi 	} else {
   2737   9089  Vasumathi 		ipif_header(verbose);
   2738   9089  Vasumathi 		if (mdb_walk("ipif", (mdb_walk_cb_t)ipif_cb, &id) == -1) {
   2739   9089  Vasumathi 			mdb_warn("failed to walk ipifs\n");
   2740   9089  Vasumathi 			return (DCMD_ERR);
   2741   9089  Vasumathi 		}
   2742   9089  Vasumathi 	}
   2743   9089  Vasumathi 	return (DCMD_OK);
   2744   9089  Vasumathi }
   2745   9089  Vasumathi 
   2746   9089  Vasumathi static void
   2747   9089  Vasumathi ipif_help(void)
   2748   9089  Vasumathi {
   2749   9089  Vasumathi 	mdb_printf("Prints the following fields: ipif ptr, name, "
   2750   9089  Vasumathi 	    "count, ill ptr, state flags and ipif flags.\n"
   2751   9089  Vasumathi 	    "The count field is a sum of individual refcnts and is expanded "
   2752   9089  Vasumathi 	    "with the -v option.\n"
   2753   9089  Vasumathi 	    "The flags field shows the following:"
   2754   9089  Vasumathi 	    "\n\tUNN -> UNNUMBERED, DHCP -> DHCPRUNNING, PRIV -> PRIVATE, "
   2755   9089  Vasumathi 	    "\n\tNOXMT -> NOXMIT, NOLCL -> NOLOCAL, DEPR -> DEPRECATED, "
   2756   9089  Vasumathi 	    "\n\tPREF -> PREFERRED, TEMP -> TEMPORARY, ACONF -> ADDRCONF, "
   2757   9089  Vasumathi 	    "\n\tANY -> ANYCAST, NFAIL -> NOFAILOVER, "
   2758   9089  Vasumathi 	    "\n\tADR -> ipif_addr_ready, MU -> ipif_multicast_up, "
   2759   9089  Vasumathi 	    "\n\tWU -> ipif_was_up, WD -> ipif_was_dup, "
   2760   9089  Vasumathi 	    "JA -> ipif_joined_allhosts.\n\n");
   2761   9089  Vasumathi 	mdb_printf("Options:\n");
   2762   9089  Vasumathi 	mdb_printf("\t-P v4 | v6"
   2763   9089  Vasumathi 	    "\tfilter ipif structures on ills for the specified protocol\n");
   2764   9089  Vasumathi }
   2765   9089  Vasumathi 
   2766   9089  Vasumathi static int
   2767   9089  Vasumathi conn_status_walk_fanout(uintptr_t addr, mdb_walk_state_t *wsp,
   2768   9089  Vasumathi     const char *walkname)
   2769   9089  Vasumathi {
   2770   9089  Vasumathi 	if (mdb_pwalk(walkname, wsp->walk_callback, wsp->walk_cbdata,
   2771   9089  Vasumathi 	    addr) == -1) {
   2772   9089  Vasumathi 		mdb_warn("couldn't walk '%s' at %p", walkname, addr);
   2773   9089  Vasumathi 		return (WALK_ERR);
   2774   9089  Vasumathi 	}
   2775   9089  Vasumathi 	return (WALK_NEXT);
   2776   9089  Vasumathi }
   2777   9089  Vasumathi 
   2778   9089  Vasumathi static int
   2779   9089  Vasumathi conn_status_walk_step(mdb_walk_state_t *wsp)
   2780   9089  Vasumathi {
   2781   9089  Vasumathi 	uintptr_t addr = wsp->walk_addr;
   2782   9089  Vasumathi 
   2783   9089  Vasumathi 	(void) conn_status_walk_fanout(addr, wsp, "udp_hash");
   2784   9089  Vasumathi 	(void) conn_status_walk_fanout(addr, wsp, "conn_hash");
   2785   9089  Vasumathi 	(void) conn_status_walk_fanout(addr, wsp, "bind_hash");
   2786   9089  Vasumathi 	(void) conn_status_walk_fanout(addr, wsp, "proto_hash");
   2787   9089  Vasumathi 	(void) conn_status_walk_fanout(addr, wsp, "proto_v6_hash");
   2788   9089  Vasumathi 	return (WALK_NEXT);
   2789   9089  Vasumathi }
   2790   9089  Vasumathi 
   2791   9089  Vasumathi /* ARGSUSED */
   2792   9089  Vasumathi static int
   2793   9089  Vasumathi conn_status_cb(uintptr_t addr, const void *walk_data,
   2794   9089  Vasumathi     void *private)
   2795   9089  Vasumathi {
   2796   9089  Vasumathi 	netstack_t nss;
   2797   9089  Vasumathi 	char src_addrstr[INET6_ADDRSTRLEN];
   2798   9089  Vasumathi 	char rem_addrstr[INET6_ADDRSTRLEN];
   2799   9089  Vasumathi 	const ipcl_hash_walk_data_t *iw = walk_data;
   2800   9089  Vasumathi 	conn_t *conn = iw->conn;
   2801   9089  Vasumathi 
   2802   9089  Vasumathi 	if (mdb_vread(conn, sizeof (conn_t), addr) == -1) {
   2803   9089  Vasumathi 		mdb_warn("failed to read conn_t at %p", addr);
   2804   9089  Vasumathi 		return (WALK_ERR);
   2805   9089  Vasumathi 	}
   2806   9089  Vasumathi 	if (mdb_vread(&nss, sizeof (nss),
   2807   9089  Vasumathi 	    (uintptr_t)conn->conn_netstack) == -1) {
   2808   9089  Vasumathi 		mdb_warn("failed to read netstack_t %p",
   2809   9089  Vasumathi 		    conn->conn_netstack);
   2810   9089  Vasumathi 		return (WALK_ERR);
   2811   9089  Vasumathi 	}
   2812   9089  Vasumathi 	mdb_printf("%-?p %-?p %?d %?d\n", addr, conn->conn_wq,
   2813   9089  Vasumathi 	    nss.netstack_stackid, conn->conn_zoneid);
   2814   9089  Vasumathi 
   2815  11042       Erik 	if (conn->conn_family == AF_INET6) {
   2816   9089  Vasumathi 		mdb_snprintf(src_addrstr, sizeof (rem_addrstr), "%N",
   2817  11042       Erik 		    &conn->conn_laddr_v6);
   2818   9089  Vasumathi 		mdb_snprintf(rem_addrstr, sizeof (rem_addrstr), "%N",
   2819  11042       Erik 		    &conn->conn_faddr_v6);
   2820   9089  Vasumathi 	} else {
   2821   9089  Vasumathi 		mdb_snprintf(src_addrstr, sizeof (src_addrstr), "%I",
   2822  11042       Erik 		    V4_PART_OF_V6((conn->conn_laddr_v6)));
   2823   9089  Vasumathi 		mdb_snprintf(rem_addrstr, sizeof (rem_addrstr), "%I",
   2824  11042       Erik 		    V4_PART_OF_V6((conn->conn_faddr_v6)));
   2825   9089  Vasumathi 	}
   2826   9089  Vasumathi 	mdb_printf("%s:%-5d\n%s:%-5d\n",
   2827   9089  Vasumathi 	    src_addrstr, conn->conn_lport, rem_addrstr, conn->conn_fport);
   2828   9089  Vasumathi 	return (WALK_NEXT);
   2829   9089  Vasumathi }
   2830   9089  Vasumathi 
   2831   9089  Vasumathi static void
   2832   9089  Vasumathi conn_header(void)
   2833   9089  Vasumathi {
   2834   9089  Vasumathi 	mdb_printf("%-?s %-?s %?s %?s\n%s\n%s\n",
   2835   9089  Vasumathi 	    "ADDR", "WQ", "STACK", "ZONE", "SRC:PORT", "DEST:PORT");
   2836   9089  Vasumathi 	mdb_printf("%<u>%80s%</u>\n", "");
   2837   9089  Vasumathi }
   2838   9089  Vasumathi 
   2839   9089  Vasumathi /*ARGSUSED*/
   2840   9089  Vasumathi static int
   2841   9089  Vasumathi conn_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   2842   9089  Vasumathi {
   2843   9089  Vasumathi 	conn_header();
   2844   9089  Vasumathi 	if (flags & DCMD_ADDRSPEC) {
   2845   9089  Vasumathi 		(void) conn_status_cb(addr, NULL, NULL);
   2846   9089  Vasumathi 	} else {
   2847   9089  Vasumathi 		if (mdb_walk("conn_status", (mdb_walk_cb_t)conn_status_cb,
   2848   9089  Vasumathi 		    NULL) == -1) {
   2849   9089  Vasumathi 			mdb_warn("failed to walk conn_fanout");
   2850   9089  Vasumathi 			return (DCMD_ERR);
   2851   9089  Vasumathi 		}
   2852   9089  Vasumathi 	}
   2853   9089  Vasumathi 	return (DCMD_OK);
   2854   9089  Vasumathi }
   2855   9089  Vasumathi 
   2856   9089  Vasumathi static void
   2857   9089  Vasumathi conn_status_help(void)
   2858   9089  Vasumathi {
   2859   9089  Vasumathi 	mdb_printf("Prints conn_t structures from the following hash tables: "
   2860   9089  Vasumathi 	    "\n\tips_ipcl_udp_fanout\n\tips_ipcl_bind_fanout"
   2861  11042       Erik 	    "\n\tips_ipcl_conn_fanout\n\tips_ipcl_proto_fanout_v4"
   2862   9089  Vasumathi 	    "\n\tips_ipcl_proto_fanout_v6\n");
   2863   9089  Vasumathi }
   2864   9089  Vasumathi 
   2865   9089  Vasumathi static int
   2866   9089  Vasumathi srcid_walk_step(mdb_walk_state_t *wsp)
   2867   9089  Vasumathi {
   2868   9089  Vasumathi 	if (mdb_pwalk("srcid_list", wsp->walk_callback, wsp->walk_cbdata,
   2869   9089  Vasumathi 	    wsp->walk_addr) == -1) {
   2870   9089  Vasumathi 		mdb_warn("can't walk 'srcid_list'");
   2871   9089  Vasumathi 		return (WALK_ERR);
   2872   9089  Vasumathi 	}
   2873   9089  Vasumathi 	return (WALK_NEXT);
   2874   9089  Vasumathi }
   2875   9089  Vasumathi 
   2876   9089  Vasumathi /* ARGSUSED */
   2877   9089  Vasumathi static int
   2878   9089  Vasumathi srcid_status_cb(uintptr_t addr, const void *walk_data,
   2879   9089  Vasumathi     void *private)
   2880   9089  Vasumathi {
   2881   9089  Vasumathi 	srcid_map_t smp;
   2882   9089  Vasumathi 
   2883   9089  Vasumathi 	if (mdb_vread(&smp, sizeof (srcid_map_t), addr) == -1) {
   2884   9089  Vasumathi 		mdb_warn("failed to read srcid_map at %p", addr);
   2885   9089  Vasumathi 		return (WALK_ERR);
   2886   9089  Vasumathi 	}
   2887   9089  Vasumathi 	mdb_printf("%-?p %3d %4d %6d %N\n",
   2888   9089  Vasumathi 	    addr, smp.sm_srcid, smp.sm_zoneid, smp.sm_refcnt,
   2889   9089  Vasumathi 	    &smp.sm_addr);
   2890   9089  Vasumathi 	return (WALK_NEXT);
   2891   9089  Vasumathi }
   2892   9089  Vasumathi 
   2893   9089  Vasumathi static void
   2894   9089  Vasumathi srcid_header(void)
   2895   9089  Vasumathi {
   2896   9089  Vasumathi 	mdb_printf("%-?s %3s %4s %6s %s\n",
   2897   9089  Vasumathi 	    "ADDR", "ID", "ZONE", "REFCNT", "IPADDR");
   2898   9089  Vasumathi 	mdb_printf("%<u>%80s%</u>\n", "");
   2899   9089  Vasumathi }
   2900   9089  Vasumathi 
   2901   9089  Vasumathi /*ARGSUSED*/
   2902   9089  Vasumathi static int
   2903   9089  Vasumathi srcid_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   2904   9089  Vasumathi {
   2905   9089  Vasumathi 	srcid_header();
   2906   9089  Vasumathi 	if (flags & DCMD_ADDRSPEC) {
   2907   9089  Vasumathi 		(void) srcid_status_cb(addr, NULL, NULL);
   2908   9089  Vasumathi 	} else {
   2909   9089  Vasumathi 		if (mdb_walk("srcid", (mdb_walk_cb_t)srcid_status_cb,
   2910   9089  Vasumathi 		    NULL) == -1) {
   2911   9089  Vasumathi 			mdb_warn("failed to walk srcid_map");
   2912   9089  Vasumathi 			return (DCMD_ERR);
   2913   9089  Vasumathi 		}
   2914   9089  Vasumathi 	}
   2915   9089  Vasumathi 	return (DCMD_OK);
   2916   9089  Vasumathi }
   2917  10946   Sangeeta 
   2918  10946   Sangeeta static int
   2919  10946   Sangeeta ilb_stacks_walk_step(mdb_walk_state_t *wsp)
   2920  10946   Sangeeta {
   2921  10946   Sangeeta 	uintptr_t kaddr;
   2922  10946   Sangeeta 	netstack_t nss;
   2923  10946   Sangeeta 
   2924  10946   Sangeeta 	if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
   2925  10946   Sangeeta 		mdb_warn("can't read netstack at %p", wsp->walk_addr);
   2926  10946   Sangeeta 		return (WALK_ERR);
   2927  10946   Sangeeta 	}
   2928  10946   Sangeeta 	kaddr = (uintptr_t)nss.netstack_modules[NS_ILB];
   2929  10946   Sangeeta 
   2930  10946   Sangeeta 	return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
   2931  10946   Sangeeta }
   2932  10946   Sangeeta 
   2933  10946   Sangeeta static int
   2934  10946   Sangeeta ilb_rules_walk_init(mdb_walk_state_t *wsp)
   2935  10946   Sangeeta {
   2936  10946   Sangeeta 	ilb_stack_t ilbs;
   2937  10946   Sangeeta 
   2938  10946   Sangeeta 	if (wsp->walk_addr == NULL)
   2939  10946   Sangeeta 		return (WALK_ERR);
   2940  10946   Sangeeta 
   2941  10946   Sangeeta 	if (mdb_vread(&ilbs, sizeof (ilbs), wsp->walk_addr) == -1) {
   2942  10946   Sangeeta 		mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr);
   2943  10946   Sangeeta 		return (WALK_ERR);
   2944  10946   Sangeeta 	}
   2945  10946   Sangeeta 	if ((wsp->walk_addr = (uintptr_t)ilbs.ilbs_rule_head) != NULL)
   2946  10946   Sangeeta 		return (WALK_NEXT);
   2947  10946   Sangeeta 	else
   2948  10946   Sangeeta 		return (WALK_DONE);
   2949  10946   Sangeeta }
   2950  10946   Sangeeta 
   2951  10946   Sangeeta static int
   2952  10946   Sangeeta ilb_rules_walk_step(mdb_walk_state_t *wsp)
   2953  10946   Sangeeta {
   2954  10946   Sangeeta 	ilb_rule_t rule;
   2955  10946   Sangeeta 	int status;
   2956  10946   Sangeeta 
   2957  10946   Sangeeta 	if (mdb_vread(&rule, sizeof (rule), wsp->walk_addr) == -1) {
   2958  10946   Sangeeta 		mdb_warn("failed to read ilb_rule_t at %p", wsp->walk_addr);
   2959  10946   Sangeeta 		return (WALK_ERR);
   2960  10946   Sangeeta 	}
   2961  10946   Sangeeta 	status = wsp->walk_callback(wsp->walk_addr, &rule, wsp->walk_cbdata);
   2962  10946   Sangeeta 	if (status != WALK_NEXT)
   2963  10946   Sangeeta 		return (status);
   2964  10946   Sangeeta 	if ((wsp->walk_addr = (uintptr_t)rule.ir_next) == NULL)
   2965  10946   Sangeeta 		return (WALK_DONE);
   2966  10946   Sangeeta 	else
   2967  10946   Sangeeta 		return (WALK_NEXT);
   2968  10946   Sangeeta }
   2969  10946   Sangeeta 
   2970  10946   Sangeeta static int
   2971  10946   Sangeeta ilb_servers_walk_init(mdb_walk_state_t *wsp)
   2972  10946   Sangeeta {
   2973  10946   Sangeeta 	ilb_rule_t rule;
   2974  10946   Sangeeta 
   2975  10946   Sangeeta 	if (wsp->walk_addr == NULL)
   2976  10946   Sangeeta 		return (WALK_ERR);
   2977  10946   Sangeeta 
   2978  10946   Sangeeta 	if (mdb_vread(&rule, sizeof (rule), wsp->walk_addr) == -1) {
   2979  10946   Sangeeta 		mdb_warn("failed to read ilb_rule_t at %p", wsp->walk_addr);
   2980  10946   Sangeeta 		return (WALK_ERR);
   2981  10946   Sangeeta 	}
   2982  10946   Sangeeta 	if ((wsp->walk_addr = (uintptr_t)rule.ir_servers) != NULL)
   2983  10946   Sangeeta 		return (WALK_NEXT);
   2984  10946   Sangeeta 	else
   2985  10946   Sangeeta 		return (WALK_DONE);
   2986  10946   Sangeeta }
   2987  10946   Sangeeta 
   2988