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