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