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 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 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 == NULL) 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 == NULL) { 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 == NULL) { 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 == NULL) 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 static void 1026 tcphdr_print(struct tcphdr *tcph) 1027 { 1028 in_port_t sport, dport; 1029 tcp_seq seq, ack; 1030 uint16_t win, urp; 1031 1032 mdb_printf("%<b>TCP header%</b>\n"); 1033 1034 mdb_nhconvert(&sport, &tcph->th_sport, sizeof (sport)); 1035 mdb_nhconvert(&dport, &tcph->th_dport, sizeof (dport)); 1036 mdb_nhconvert(&seq, &tcph->th_seq, sizeof (seq)); 1037 mdb_nhconvert(&ack, &tcph->th_ack, sizeof (ack)); 1038 mdb_nhconvert(&win, &tcph->th_win, sizeof (win)); 1039 mdb_nhconvert(&urp, &tcph->th_urp, sizeof (urp)); 1040 1041 mdb_printf("%<u>%6s %6s %10s %10s %4s %5s %5s %5s %-15s%</u>\n", 1042 "SPORT", "DPORT", "SEQ", "ACK", "HLEN", "WIN", "CSUM", "URP", 1043 "FLAGS"); 1044 mdb_printf("%6hu %6hu %10u %10u %4d %5hu %5hu %5hu <%b>\n", 1045 sport, dport, seq, ack, tcph->th_off << 2, win, 1046 tcph->th_sum, urp, tcph->th_flags, tcp_flags); 1047 mdb_printf("0x%04x 0x%04x 0x%08x 0x%08x\n\n", 1048 sport, dport, seq, ack); 1049 } 1050 1051 /* ARGSUSED */ 1052 static int 1053 tcphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 1054 { 1055 struct tcphdr tcph; 1056 1057 if (!(flags & DCMD_ADDRSPEC)) 1058 return (DCMD_USAGE); 1059 1060 if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) { 1061 mdb_warn("failed to read TCP header at %p", addr); 1062 return (DCMD_ERR); 1063 } 1064 tcphdr_print(&tcph); 1065 return (DCMD_OK); 1066 } 1067 1068 static void 1069 udphdr_print(struct udphdr *udph) 1070 { 1071 in_port_t sport, dport; 1072 uint16_t hlen; 1073 1074 mdb_printf("%<b>UDP header%</b>\n"); 1075 1076 mdb_nhconvert(&sport, &udph->uh_sport, sizeof (sport)); 1077 mdb_nhconvert(&dport, &udph->uh_dport, sizeof (dport)); 1078 mdb_nhconvert(&hlen, &udph->uh_ulen, sizeof (hlen)); 1079 1080 mdb_printf("%<u>%14s %14s %5s %6s%</u>\n", 1081 "SPORT", "DPORT", "LEN", "CSUM"); 1082 mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %5hu 0x%04hx\n\n", sport, sport, 1083 dport, dport, hlen, udph->uh_sum); 1084 } 1085 1086 /* ARGSUSED */ 1087 static int 1088 udphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 1089 { 1090 struct udphdr udph; 1091 1092 if (!(flags & DCMD_ADDRSPEC)) 1093 return (DCMD_USAGE); 1094 1095 if (mdb_vread(&udph, sizeof (udph), addr) == -1) { 1096 mdb_warn("failed to read UDP header at %p", addr); 1097 return (DCMD_ERR); 1098 } 1099 udphdr_print(&udph); 1100 return (DCMD_OK); 1101 } 1102 1103 static void 1104 sctphdr_print(sctp_hdr_t *sctph) 1105 { 1106 in_port_t sport, dport; 1107 1108 mdb_printf("%<b>SCTP header%</b>\n"); 1109 mdb_nhconvert(&sport, &sctph->sh_sport, sizeof (sport)); 1110 mdb_nhconvert(&dport, &sctph->sh_dport, sizeof (dport)); 1111 1112 mdb_printf("%<u>%14s %14s %10s %10s%</u>\n", 1113 "SPORT", "DPORT", "VTAG", "CHKSUM"); 1114 mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %10u 0x%08x\n\n", sport, sport, 1115 dport, dport, sctph->sh_verf, sctph->sh_chksum); 1116 } 1117 1118 /* ARGSUSED */ 1119 static int 1120 sctphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 1121 { 1122 sctp_hdr_t sctph; 1123 1124 if (!(flags & DCMD_ADDRSPEC)) 1125 return (DCMD_USAGE); 1126 1127 if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) { 1128 mdb_warn("failed to read SCTP header at %p", addr); 1129 return (DCMD_ERR); 1130 } 1131 1132 sctphdr_print(&sctph); 1133 return (DCMD_OK); 1134 } 1135 1136 static int 1137 transport_hdr(int proto, uintptr_t addr) 1138 { 1139 mdb_printf("\n"); 1140 switch (proto) { 1141 case IPPROTO_TCP: { 1142 struct tcphdr tcph; 1143 1144 if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) { 1145 mdb_warn("failed to read TCP header at %p", addr); 1146 return (DCMD_ERR); 1147 } 1148 tcphdr_print(&tcph); 1149 break; 1150 } 1151 case IPPROTO_UDP: { 1152 struct udphdr udph; 1153 1154 if (mdb_vread(&udph, sizeof (udph), addr) == -1) { 1155 mdb_warn("failed to read UDP header at %p", addr); 1156 return (DCMD_ERR); 1157 } 1158 udphdr_print(&udph); 1159 break; 1160 } 1161 case IPPROTO_SCTP: { 1162 sctp_hdr_t sctph; 1163 1164 if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) { 1165 mdb_warn("failed to read SCTP header at %p", addr); 1166 return (DCMD_ERR); 1167 } 1168 sctphdr_print(&sctph); 1169 break; 1170 } 1171 default: 1172 break; 1173 } 1174 1175 return (DCMD_OK); 1176 } 1177 1178 static const mdb_bitmask_t ip_flags[] = { 1179 { "DF", IPH_DF, IPH_DF }, 1180 { "MF", IPH_MF, IPH_MF }, 1181 { NULL, 0, 0 } 1182 }; 1183 1184 /* ARGSUSED */ 1185 static int 1186 iphdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1187 { 1188 uint_t verbose = FALSE, force = FALSE; 1189 ipha_t iph[1]; 1190 uint16_t ver, totlen, hdrlen, ipid, off, csum; 1191 uintptr_t nxt_proto; 1192 char exp_csum[8]; 1193 1194 if (mdb_getopts(argc, argv, 1195 'v', MDB_OPT_SETBITS, TRUE, &verbose, 1196 'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc) 1197 return (DCMD_USAGE); 1198 1199 if (mdb_vread(iph, sizeof (*iph), addr) == -1) { 1200 mdb_warn("failed to read IPv4 header at %p", addr); 1201 return (DCMD_ERR); 1202 } 1203 1204 ver = (iph->ipha_version_and_hdr_length & 0xf0) >> 4; 1205 if (ver != IPV4_VERSION) { 1206 if (ver == IPV6_VERSION) { 1207 return (ip6hdr(addr, flags, argc, argv)); 1208 } else if (!force) { 1209 mdb_warn("unknown IP version: %d\n", ver); 1210 return (DCMD_ERR); 1211 } 1212 } 1213 1214 mdb_printf("%<b>IPv4 header%</b>\n"); 1215 mdb_printf("%-34s %-34s\n" 1216 "%<u>%-4s %-4s %-5s %-5s %-6s %-5s %-5s %-6s %-8s %-6s%</u>\n", 1217 "SRC", "DST", 1218 "HLEN", "TOS", "LEN", "ID", "OFFSET", "TTL", "PROTO", "CHKSUM", 1219 "EXP-CSUM", "FLGS"); 1220 1221 hdrlen = (iph->ipha_version_and_hdr_length & 0x0f) << 2; 1222 mdb_nhconvert(&totlen, &iph->ipha_length, sizeof (totlen)); 1223 mdb_nhconvert(&ipid, &iph->ipha_ident, sizeof (ipid)); 1224 mdb_nhconvert(&off, &iph->ipha_fragment_offset_and_flags, sizeof (off)); 1225 if (hdrlen == IP_SIMPLE_HDR_LENGTH) { 1226 if ((csum = ipcksum(iph, sizeof (*iph))) != 0) 1227 csum = ~(~csum + ~iph->ipha_hdr_checksum); 1228 else 1229 csum = iph->ipha_hdr_checksum; 1230 mdb_snprintf(exp_csum, 8, "%u", csum); 1231 } else { 1232 mdb_snprintf(exp_csum, 8, "<n/a>"); 1233 } 1234 1235 mdb_printf("%-34I %-34I%\n" 1236 "%-4d %-4d %-5hu %-5hu %-6hu %-5hu %-5hu %-6u %-8s <%5hb>\n", 1237 iph->ipha_src, iph->ipha_dst, 1238 hdrlen, iph->ipha_type_of_service, totlen, ipid, 1239 (off << 3) & 0xffff, iph->ipha_ttl, iph->ipha_protocol, 1240 iph->ipha_hdr_checksum, exp_csum, off, ip_flags); 1241 1242 if (verbose) { 1243 nxt_proto = addr + hdrlen; 1244 return (transport_hdr(iph->ipha_protocol, nxt_proto)); 1245 } else { 1246 return (DCMD_OK); 1247 } 1248 } 1249 1250 /* ARGSUSED */ 1251 static int 1252 ip6hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1253 { 1254 uint_t verbose = FALSE, force = FALSE; 1255 ip6_t iph[1]; 1256 int ver, class, flow; 1257 uint16_t plen; 1258 uintptr_t nxt_proto; 1259 1260 if (mdb_getopts(argc, argv, 1261 'v', MDB_OPT_SETBITS, TRUE, &verbose, 1262 'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc) 1263 return (DCMD_USAGE); 1264 1265 if (mdb_vread(iph, sizeof (*iph), addr) == -1) { 1266 mdb_warn("failed to read IPv6 header at %p", addr); 1267 return (DCMD_ERR); 1268 } 1269 1270 ver = (iph->ip6_vfc & 0xf0) >> 4; 1271 if (ver != IPV6_VERSION) { 1272 if (ver == IPV4_VERSION) { 1273 return (iphdr(addr, flags, argc, argv)); 1274 } else if (!force) { 1275 mdb_warn("unknown IP version: %d\n", ver); 1276 return (DCMD_ERR); 1277 } 1278 } 1279 1280 mdb_printf("%<b>IPv6 header%</b>\n"); 1281 mdb_printf("%<u>%-26s %-26s %4s %7s %5s %3s %3s%</u>\n", 1282 "SRC", "DST", "TCLS", "FLOW-ID", "PLEN", "NXT", "HOP"); 1283 1284 class = (iph->ip6_vcf & IPV6_FLOWINFO_TCLASS) >> 20; 1285 mdb_nhconvert(&class, &class, sizeof (class)); 1286 flow = iph->ip6_vcf & IPV6_FLOWINFO_FLOWLABEL; 1287 mdb_nhconvert(&flow, &flow, sizeof (flow)); 1288 mdb_nhconvert(&plen, &iph->ip6_plen, sizeof (plen)); 1289 1290 mdb_printf("%-26N %-26N %4d %7d %5hu %3d %3d\n", 1291 &iph->ip6_src, &iph->ip6_dst, 1292 class, flow, plen, iph->ip6_nxt, iph->ip6_hlim); 1293 1294 if (verbose) { 1295 nxt_proto = addr + sizeof (ip6_t); 1296 return (transport_hdr(iph->ip6_nxt, nxt_proto)); 1297 } else { 1298 return (DCMD_OK); 1299 } 1300 } 1301 1302 int 1303 nce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1304 { 1305 nce_t nce; 1306 nce_cbdata_t nce_cb; 1307 int ipversion = 0; 1308 const char *opt_P = NULL, *opt_ill; 1309 1310 if (mdb_getopts(argc, argv, 1311 'i', MDB_OPT_STR, &opt_ill, 1312 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 1313 return (DCMD_USAGE); 1314 1315 if (opt_P != NULL) { 1316 if (strcmp("v4", opt_P) == 0) { 1317 ipversion = IPV4_VERSION; 1318 } else if (strcmp("v6", opt_P) == 0) { 1319 ipversion = IPV6_VERSION; 1320 } else { 1321 mdb_warn("invalid protocol '%s'\n", opt_P); 1322 return (DCMD_USAGE); 1323 } 1324 } 1325 1326 if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 1327 mdb_printf("%<u>%?s %5s %18s %?s %s %s %</u>\n", 1328 "ADDR", "INTF", "LLADDR", "FP_MP", "REFCNT", 1329 "NCE_ADDR"); 1330 } 1331 1332 bzero(&nce_cb, sizeof (nce_cb)); 1333 if (opt_ill != NULL) { 1334 strcpy(nce_cb.nce_ill_name, opt_ill); 1335 } 1336 nce_cb.nce_ipversion = ipversion; 1337 1338 if (flags & DCMD_ADDRSPEC) { 1339 (void) mdb_vread(&nce, sizeof (nce_t), addr); 1340 (void) nce_format(addr, &nce, &nce_cb); 1341 } else if (mdb_walk("nce", (mdb_walk_cb_t)nce_format, &nce_cb) == -1) { 1342 mdb_warn("failed to walk ire table"); 1343 return (DCMD_ERR); 1344 } 1345 1346 return (DCMD_OK); 1347 } 1348 1349 /* ARGSUSED */ 1350 static int 1351 dce_format(uintptr_t addr, const dce_t *dcep, void *dce_cb_arg) 1352 { 1353 static const mdb_bitmask_t dmasks[] = { 1354 { "D", DCEF_DEFAULT, DCEF_DEFAULT }, 1355 { "P", DCEF_PMTU, DCEF_PMTU }, 1356 { "U", DCEF_UINFO, DCEF_UINFO }, 1357 { "S", DCEF_TOO_SMALL_PMTU, DCEF_TOO_SMALL_PMTU }, 1358 { NULL, 0, 0 } 1359 }; 1360 char flagsbuf[2 * A_CNT(dmasks)]; 1361 int ipversion = *(int *)dce_cb_arg; 1362 boolean_t condemned = dcep->dce_generation == DCE_GENERATION_CONDEMNED; 1363 1364 if (ipversion != 0 && ipversion != dcep->dce_ipversion) 1365 return (WALK_NEXT); 1366 1367 mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%b", dcep->dce_flags, 1368 dmasks); 1369 1370 switch (dcep->dce_ipversion) { 1371 case IPV4_VERSION: 1372 mdb_printf("%<u>%?p%3s %8s %8d %30I %</u>\n", addr, condemned ? 1373 "(C)" : "", flagsbuf, dcep->dce_pmtu, &dcep->dce_v4addr); 1374 break; 1375 case IPV6_VERSION: 1376 mdb_printf("%<u>%?p%3s %8s %8d %30N %</u>\n", addr, condemned ? 1377 "(C)" : "", flagsbuf, dcep->dce_pmtu, &dcep->dce_v6addr); 1378 break; 1379 default: 1380 mdb_printf("%<u>%?p%3s %8s %8d %30s %</u>\n", addr, condemned ? 1381 "(C)" : "", flagsbuf, dcep->dce_pmtu, ""); 1382 } 1383 1384 return (WALK_NEXT); 1385 } 1386 1387 int 1388 dce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1389 { 1390 dce_t dce; 1391 const char *opt_P = NULL; 1392 const char *zone_name = NULL; 1393 ip_stack_t *ipst = NULL; 1394 int ipversion = 0; 1395 1396 if (mdb_getopts(argc, argv, 1397 's', MDB_OPT_STR, &zone_name, 1398 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 1399 return (DCMD_USAGE); 1400 1401 /* Follow the specified zone name to find a ip_stack_t*. */ 1402 if (zone_name != NULL) { 1403 ipst = zone_to_ips(zone_name); 1404 if (ipst == NULL) 1405 return (DCMD_USAGE); 1406 } 1407 1408 if (opt_P != NULL) { 1409 if (strcmp("v4", opt_P) == 0) { 1410 ipversion = IPV4_VERSION; 1411 } else if (strcmp("v6", opt_P) == 0) { 1412 ipversion = IPV6_VERSION; 1413 } else { 1414 mdb_warn("invalid protocol '%s'\n", opt_P); 1415 return (DCMD_USAGE); 1416 } 1417 } 1418 1419 if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 1420 mdb_printf("%<u>%?s%3s %8s %8s %30s %</u>\n", 1421 "ADDR", "", "FLAGS", "PMTU", "DST_ADDR"); 1422 } 1423 1424 if (flags & DCMD_ADDRSPEC) { 1425 (void) mdb_vread(&dce, sizeof (dce_t), addr); 1426 (void) dce_format(addr, &dce, &ipversion); 1427 } else if (mdb_pwalk("dce", (mdb_walk_cb_t)dce_format, &ipversion, 1428 (uintptr_t)ipst) == -1) { 1429 mdb_warn("failed to walk dce cache"); 1430 return (DCMD_ERR); 1431 } 1432 1433 return (DCMD_OK); 1434 } 1435 1436 int 1437 ire(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1438 { 1439 uint_t verbose = FALSE; 1440 ire_t ire; 1441 ire_cbdata_t ire_cb; 1442 int ipversion = 0; 1443 const char *opt_P = NULL; 1444 const char *zone_name = NULL; 1445 ip_stack_t *ipst = NULL; 1446 1447 if (mdb_getopts(argc, argv, 1448 'v', MDB_OPT_SETBITS, TRUE, &verbose, 1449 's', MDB_OPT_STR, &zone_name, 1450 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 1451 return (DCMD_USAGE); 1452 1453 /* Follow the specified zone name to find a ip_stack_t*. */ 1454 if (zone_name != NULL) { 1455 ipst = zone_to_ips(zone_name); 1456 if (ipst == NULL) 1457 return (DCMD_USAGE); 1458 } 1459 1460 if (opt_P != NULL) { 1461 if (strcmp("v4", opt_P) == 0) { 1462 ipversion = IPV4_VERSION; 1463 } else if (strcmp("v6", opt_P) == 0) { 1464 ipversion = IPV6_VERSION; 1465 } else { 1466 mdb_warn("invalid protocol '%s'\n", opt_P); 1467 return (DCMD_USAGE); 1468 } 1469 } 1470 1471 if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 1472 1473 if (verbose) { 1474 mdb_printf("%?s %40s %-20s%\n" 1475 "%?s %40s %-20s%\n" 1476 "%<u>%?s %40s %4s %-20s %s%</u>\n", 1477 "ADDR", "SRC", "TYPE", 1478 "", "DST", "MARKS", 1479 "", "STACK", "ZONE", "FLAGS", "INTF"); 1480 } else { 1481 mdb_printf("%<u>%?s %30s %30s %5s %4s %s%</u>\n", 1482 "ADDR", "SRC", "DST", "STACK", "ZONE", "INTF"); 1483 } 1484 } 1485 1486 ire_cb.verbose = (verbose == TRUE); 1487 ire_cb.ire_ipversion = ipversion; 1488 1489 if (flags & DCMD_ADDRSPEC) { 1490 (void) mdb_vread(&ire, sizeof (ire_t), addr); 1491 (void) ire_format(addr, &ire, &ire_cb); 1492 } else if (mdb_pwalk("ire", (mdb_walk_cb_t)ire_format, &ire_cb, 1493 (uintptr_t)ipst) == -1) { 1494 mdb_warn("failed to walk ire table"); 1495 return (DCMD_ERR); 1496 } 1497 1498 return (DCMD_OK); 1499 } 1500 1501 static size_t 1502 mi_osize(const queue_t *q) 1503 { 1504 /* 1505 * The code in common/inet/mi.c allocates an extra word to store the 1506 * size of the allocation. An mi_o_s is thus a size_t plus an mi_o_s. 1507 */ 1508 struct mi_block { 1509 size_t mi_nbytes; 1510 struct mi_o_s mi_o; 1511 } m; 1512 1513 if (mdb_vread(&m, sizeof (m), (uintptr_t)q->q_ptr - 1514 sizeof (m)) == sizeof (m)) 1515 return (m.mi_nbytes - sizeof (m)); 1516 1517 return (0); 1518 } 1519 1520 static void 1521 ip_ill_qinfo(const queue_t *q, char *buf, size_t nbytes) 1522 { 1523 char name[32]; 1524 ill_t ill; 1525 1526 if (mdb_vread(&ill, sizeof (ill), 1527 (uintptr_t)q->q_ptr) == sizeof (ill) && 1528 mdb_readstr(name, sizeof (name), (uintptr_t)ill.ill_name) > 0) 1529 (void) mdb_snprintf(buf, nbytes, "if: %s", name); 1530 } 1531 1532 void 1533 ip_qinfo(const queue_t *q, char *buf, size_t nbytes) 1534 { 1535 size_t size = mi_osize(q); 1536 1537 if (size == sizeof (ill_t)) 1538 ip_ill_qinfo(q, buf, nbytes); 1539 } 1540 1541 uintptr_t 1542 ip_rnext(const queue_t *q) 1543 { 1544 size_t size = mi_osize(q); 1545 ill_t ill; 1546 1547 if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill), 1548 (uintptr_t)q->q_ptr) == sizeof (ill)) 1549 return ((uintptr_t)ill.ill_rq); 1550 1551 return (NULL); 1552 } 1553 1554 uintptr_t 1555 ip_wnext(const queue_t *q) 1556 { 1557 size_t size = mi_osize(q); 1558 ill_t ill; 1559 1560 if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill), 1561 (uintptr_t)q->q_ptr) == sizeof (ill)) 1562 return ((uintptr_t)ill.ill_wq); 1563 1564 return (NULL); 1565 } 1566 1567 /* 1568 * Print the core fields in an squeue_t. With the "-v" argument, 1569 * provide more verbose output. 1570 */ 1571 static int 1572 squeue(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1573 { 1574 unsigned int i; 1575 unsigned int verbose = FALSE; 1576 const int SQUEUE_STATEDELT = (int)(sizeof (uintptr_t) + 9); 1577 boolean_t arm; 1578 squeue_t squeue; 1579 1580 if (!(flags & DCMD_ADDRSPEC)) { 1581 if (mdb_walk_dcmd("genunix`squeue_cache", "ip`squeue", 1582 argc, argv) == -1) { 1583 mdb_warn("failed to walk squeue cache"); 1584 return (DCMD_ERR); 1585 } 1586 return (DCMD_OK); 1587 } 1588 1589 if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) 1590 != argc) 1591 return (DCMD_USAGE); 1592 1593 if (!DCMD_HDRSPEC(flags) && verbose) 1594 mdb_printf("\n\n"); 1595 1596 if (DCMD_HDRSPEC(flags) || verbose) { 1597 mdb_printf("%?s %-5s %-3s %?s %?s %?s\n", 1598 "ADDR", "STATE", "CPU", 1599 "FIRST", "LAST", "WORKER"); 1600 } 1601 1602 if (mdb_vread(&squeue, sizeof (squeue_t), addr) == -1) { 1603 mdb_warn("cannot read squeue_t at %p", addr); 1604 return (DCMD_ERR); 1605 } 1606 1607 mdb_printf("%0?p %05x %3d %0?p %0?p %0?p\n", 1608 addr, squeue.sq_state, squeue.sq_bind, 1609 squeue.sq_first, squeue.sq_last, squeue.sq_worker); 1610 1611 if (!verbose) 1612 return (DCMD_OK); 1613 1614 arm = B_TRUE; 1615 for (i = 0; squeue_states[i].bit_name != NULL; i++) { 1616 if (((squeue.sq_state) & (1 << i)) == 0) 1617 continue; 1618 1619 if (arm) { 1620 mdb_printf("%*s|\n", SQUEUE_STATEDELT, ""); 1621 mdb_printf("%*s+--> ", SQUEUE_STATEDELT, ""); 1622 arm = B_FALSE; 1623 } else 1624 mdb_printf("%*s ", SQUEUE_STATEDELT, ""); 1625 1626 mdb_printf("%-12s %s\n", squeue_states[i].bit_name, 1627 squeue_states[i].bit_descr); 1628 } 1629 1630 return (DCMD_OK); 1631 } 1632 1633 static void 1634 ip_squeue_help(void) 1635 { 1636 mdb_printf("Print the core information for a given NCA squeue_t.\n\n"); 1637 mdb_printf("Options:\n"); 1638 mdb_printf("\t-v\tbe verbose (more descriptive)\n"); 1639 } 1640 1641 /* 1642 * This is called by ::th_trace (via a callback) when walking the th_hash 1643 * list. It calls modent to find the entries. 1644 */ 1645 /* ARGSUSED */ 1646 static int 1647 modent_summary(uintptr_t addr, const void *data, void *private) 1648 { 1649 th_walk_data_t *thw = private; 1650 const struct mod_hash_entry *mhe = data; 1651 th_trace_t th; 1652 1653 if (mdb_vread(&th, sizeof (th), (uintptr_t)mhe->mhe_val) == -1) { 1654 mdb_warn("failed to read th_trace_t %p", mhe->mhe_val); 1655 return (WALK_ERR); 1656 } 1657 1658 if (th.th_refcnt == 0 && thw->thw_non_zero_only) 1659 return (WALK_NEXT); 1660 1661 if (!thw->thw_match) { 1662 mdb_printf("%?p %?p %?p %8d %?p\n", thw->thw_ipst, mhe->mhe_key, 1663 mhe->mhe_val, th.th_refcnt, th.th_id); 1664 } else if (thw->thw_matchkey == (uintptr_t)mhe->mhe_key) { 1665 int i, j, k; 1666 tr_buf_t *tr; 1667 1668 mdb_printf("Object %p in IP stack %p:\n", mhe->mhe_key, 1669 thw->thw_ipst); 1670 i = th.th_trace_lastref; 1671 mdb_printf("\tThread %p refcnt %d:\n", th.th_id, 1672 th.th_refcnt); 1673 for (j = TR_BUF_MAX; j > 0; j--) { 1674 tr = th.th_trbuf + i; 1675 if (tr->tr_depth == 0 || tr->tr_depth > TR_STACK_DEPTH) 1676 break; 1677 mdb_printf("\t T%+ld:\n", tr->tr_time - 1678 thw->thw_lbolt); 1679 for (k = 0; k < tr->tr_depth; k++) 1680 mdb_printf("\t\t%a\n", tr->tr_stack[k]); 1681 if (--i < 0) 1682 i = TR_BUF_MAX - 1; 1683 } 1684 } 1685 return (WALK_NEXT); 1686 } 1687 1688 /* 1689 * This is called by ::th_trace (via a callback) when walking the th_hash 1690 * list. It calls modent to find the entries. 1691 */ 1692 /* ARGSUSED */ 1693 static int 1694 th_hash_summary(uintptr_t addr, const void *data, void *private) 1695 { 1696 const th_hash_t *thh = data; 1697 th_walk_data_t *thw = private; 1698 1699 thw->thw_ipst = (uintptr_t)thh->thh_ipst; 1700 return (mdb_pwalk("modent", modent_summary, private, 1701 (uintptr_t)thh->thh_hash)); 1702 } 1703 1704 /* 1705 * Print or summarize the th_trace_t structures. 1706 */ 1707 static int 1708 th_trace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1709 { 1710 th_walk_data_t thw; 1711 1712 (void) memset(&thw, 0, sizeof (thw)); 1713 1714 if (mdb_getopts(argc, argv, 1715 'n', MDB_OPT_SETBITS, TRUE, &thw.thw_non_zero_only, 1716 NULL) != argc) 1717 return (DCMD_USAGE); 1718 1719 if (!(flags & DCMD_ADDRSPEC)) { 1720 /* 1721 * No address specified. Walk all of the th_hash_t in the 1722 * system, and summarize the th_trace_t entries in each. 1723 */ 1724 mdb_printf("%?s %?s %?s %8s %?s\n", 1725 "IPSTACK", "OBJECT", "TRACE", "REFCNT", "THREAD"); 1726 thw.thw_match = B_FALSE; 1727 } else { 1728 thw.thw_match = B_TRUE; 1729 thw.thw_matchkey = addr; 1730 1731 if ((thw.thw_lbolt = (clock_t)mdb_get_lbolt()) == -1) { 1732 mdb_warn("failed to read lbolt"); 1733 return (DCMD_ERR); 1734 } 1735 } 1736 if (mdb_pwalk("th_hash", th_hash_summary, &thw, NULL) == -1) { 1737 mdb_warn("can't walk th_hash entries"); 1738 return (DCMD_ERR); 1739 } 1740 return (DCMD_OK); 1741 } 1742 1743 static void 1744 th_trace_help(void) 1745 { 1746 mdb_printf("If given an address of an ill_t, ipif_t, ire_t, or ncec_t, " 1747 "print the\n" 1748 "corresponding th_trace_t structure in detail. Otherwise, if no " 1749 "address is\n" 1750 "given, then summarize all th_trace_t structures.\n\n"); 1751 mdb_printf("Options:\n" 1752 "\t-n\tdisplay only entries with non-zero th_refcnt\n"); 1753 } 1754 1755 static const mdb_dcmd_t dcmds[] = { 1756 { "conn_status", ":", 1757 "display connection structures from ipcl hash tables", 1758 conn_status, conn_status_help }, 1759 { "srcid_status", ":", 1760 "display connection structures from ipcl hash tables", 1761 srcid_status }, 1762 { "ill", "?[-v] [-P v4 | v6] [-s exclusive-ip-zone-name]", 1763 "display ill_t structures", ill, ill_help }, 1764 { "illif", "?[-P v4 | v6]", 1765 "display or filter IP Lower Level InterFace structures", illif, 1766 illif_help }, 1767 { "iphdr", ":[-vf]", "display an IPv4 header", iphdr }, 1768 { "ip6hdr", ":[-vf]", "display an IPv6 header", ip6hdr }, 1769 { "ipif", "?[-v] [-P v4 | v6]", "display ipif structures", 1770 ipif, ipif_help }, 1771 { "ire", "?[-v] [-P v4|v6] [-s exclusive-ip-zone-name]", 1772 "display Internet Route Entry structures", ire }, 1773 { "nce", "?[-P v4|v6] [-i <interface>]", 1774 "display interface-specific Neighbor Cache structures", nce }, 1775 { "ncec", "?[-P v4 | v6]", "display Neighbor Cache Entry structures", 1776 ncec }, 1777 { "dce", "?[-P v4|v6] [-s exclusive-ip-zone-name]", 1778 "display Destination Cache Entry structures", dce }, 1779 { "squeue", ":[-v]", "print core squeue_t info", squeue, 1780 ip_squeue_help }, 1781 { "tcphdr", ":", "display a TCP header", tcphdr }, 1782 { "udphdr", ":", "display an UDP header", udphdr }, 1783 { "sctphdr", ":", "display an SCTP header", sctphdr }, 1784 { "th_trace", "?[-n]", "display th_trace_t structures", th_trace, 1785 th_trace_help }, 1786 { NULL } 1787 }; 1788 1789 static const mdb_walker_t walkers[] = { 1790 { "conn_status", "walk list of conn_t structures", 1791 ip_stacks_common_walk_init, conn_status_walk_step, NULL }, 1792 { "illif", "walk list of ill interface types for all stacks", 1793 ip_stacks_common_walk_init, illif_walk_step, NULL }, 1794 { "illif_stack", "walk list of ill interface types", 1795 illif_stack_walk_init, illif_stack_walk_step, 1796 illif_stack_walk_fini }, 1797 { "ill", "walk active ill_t structures for all stacks", 1798 ill_walk_init, ill_walk_step, NULL }, 1799 { "ipif", "walk list of ipif structures for all stacks", 1800 ipif_walk_init, ipif_walk_step, NULL }, 1801 { "ipif_list", "walk the linked list of ipif structures " 1802 "for a given ill", 1803 ip_list_walk_init, ip_list_walk_step, 1804 ip_list_walk_fini, &ipif_walk_arg }, 1805 { "srcid", "walk list of srcid_map structures for all stacks", 1806 ip_stacks_common_walk_init, srcid_walk_step, NULL }, 1807 { "srcid_list", "walk list of srcid_map structures for a stack", 1808 ip_list_walk_init, ip_list_walk_step, ip_list_walk_fini, 1809 &srcid_walk_arg }, 1810 { "ire", "walk active ire_t structures", 1811 ire_walk_init, ire_walk_step, NULL }, 1812 { "ire_next", "walk ire_t structures in the ctable", 1813 ire_next_walk_init, ire_next_walk_step, NULL }, 1814 { "nce", "walk active nce_t structures", 1815 nce_walk_init, nce_walk_step, NULL }, 1816 { "dce", "walk active dce_t structures", 1817 dce_walk_init, dce_walk_step, NULL }, 1818 { "ip_stacks", "walk all the ip_stack_t", 1819 ns_walk_init, ip_stacks_walk_step, NULL }, 1820 { "tcp_stacks", "walk all the tcp_stack_t", 1821 ns_walk_init, tcp_stacks_walk_step, NULL }, 1822 { "sctp_stacks", "walk all the sctp_stack_t", 1823 ns_walk_init, sctp_stacks_walk_step, NULL }, 1824 { "udp_stacks", "walk all the udp_stack_t", 1825 ns_walk_init, udp_stacks_walk_step, NULL }, 1826 { "th_hash", "walk all the th_hash_t entries", 1827 th_hash_walk_init, th_hash_walk_step, NULL }, 1828 { "ncec", "walk list of ncec structures for all stacks", 1829 ip_stacks_common_walk_init, ncec_walk_step, NULL }, 1830 { "ncec_stack", "walk list of ncec structures", 1831 ncec_stack_walk_init, ncec_stack_walk_step, 1832 ncec_stack_walk_fini}, 1833 { "udp_hash", "walk list of conn_t structures in ips_ipcl_udp_fanout", 1834 ipcl_hash_walk_init, ipcl_hash_walk_step, 1835 ipcl_hash_walk_fini, &udp_hash_arg}, 1836 { "conn_hash", "walk list of conn_t structures in ips_ipcl_conn_fanout", 1837 ipcl_hash_walk_init, ipcl_hash_walk_step, 1838 ipcl_hash_walk_fini, &conn_hash_arg}, 1839 { "bind_hash", "walk list of conn_t structures in ips_ipcl_bind_fanout", 1840 ipcl_hash_walk_init, ipcl_hash_walk_step, 1841 ipcl_hash_walk_fini, &bind_hash_arg}, 1842 { "proto_hash", "walk list of conn_t structures in " 1843 "ips_ipcl_proto_fanout", 1844 ipcl_hash_walk_init, ipcl_hash_walk_step, 1845 ipcl_hash_walk_fini, &proto_hash_arg}, 1846 { "proto_v6_hash", "walk list of conn_t structures in " 1847 "ips_ipcl_proto_fanout_v6", 1848 ipcl_hash_walk_init, ipcl_hash_walk_step, 1849 ipcl_hash_walk_fini, &proto_v6_hash_arg}, 1850 { "ilb_stacks", "walk all ilb_stack_t", 1851 ns_walk_init, ilb_stacks_walk_step, NULL }, 1852 { "ilb_rules", "walk ilb rules in a given ilb_stack_t", 1853 ilb_rules_walk_init, ilb_rules_walk_step, NULL }, 1854 { "ilb_servers", "walk server in a given ilb_rule_t", 1855 ilb_servers_walk_init, ilb_servers_walk_step, NULL }, 1856 { "ilb_nat_src", "walk NAT source table of a given ilb_stack_t", 1857 ilb_nat_src_walk_init, ilb_nat_src_walk_step, 1858 ilb_common_walk_fini }, 1859 { "ilb_conns", "walk NAT table of a given ilb_stack_t", 1860 ilb_conn_walk_init, ilb_conn_walk_step, ilb_common_walk_fini }, 1861 { "ilb_stickys", "walk sticky table of a given ilb_stack_t", 1862 ilb_sticky_walk_init, ilb_sticky_walk_step, 1863 ilb_common_walk_fini }, 1864 { "tcps_sc", "walk all the per CPU stats counters of a tcp_stack_t", 1865 tcps_sc_walk_init, tcps_sc_walk_step, NULL }, 1866 { NULL } 1867 }; 1868 1869 static const mdb_qops_t ip_qops = { ip_qinfo, ip_rnext, ip_wnext }; 1870 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 1871 1872 const mdb_modinfo_t * 1873 _mdb_init(void) 1874 { 1875 GElf_Sym sym; 1876 1877 if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0) 1878 mdb_qops_install(&ip_qops, (uintptr_t)sym.st_value); 1879 1880 return (&modinfo); 1881 } 1882 1883 void 1884 _mdb_fini(void) 1885 { 1886 GElf_Sym sym; 1887 1888 if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0) 1889 mdb_qops_remove(&ip_qops, (uintptr_t)sym.st_value); 1890 } 1891 1892 static char * 1893 ncec_state(int ncec_state) 1894 { 1895 switch (ncec_state) { 1896 case ND_UNCHANGED: 1897 return ("unchanged"); 1898 case ND_INCOMPLETE: 1899 return ("incomplete"); 1900 case ND_REACHABLE: 1901 return ("reachable"); 1902 case ND_STALE: 1903 return ("stale"); 1904 case ND_DELAY: 1905 return ("delay"); 1906 case ND_PROBE: 1907 return ("probe"); 1908 case ND_UNREACHABLE: 1909 return ("unreach"); 1910 case ND_INITIAL: 1911 return ("initial"); 1912 default: 1913 return ("??"); 1914 } 1915 } 1916 1917 static char * 1918 ncec_l2_addr(const ncec_t *ncec, const ill_t *ill) 1919 { 1920 uchar_t *h; 1921 static char addr_buf[L2MAXADDRSTRLEN]; 1922 1923 if (ncec->ncec_lladdr == NULL) { 1924 return ("None"); 1925 } 1926 1927 if (ill->ill_net_type == IRE_IF_RESOLVER) { 1928 1929 if (ill->ill_phys_addr_length == 0) 1930 return ("None"); 1931 h = mdb_zalloc(ill->ill_phys_addr_length, UM_SLEEP); 1932 if (mdb_vread(h, ill->ill_phys_addr_length, 1933 (uintptr_t)ncec->ncec_lladdr) == -1) { 1934 mdb_warn("failed to read hwaddr at %p", 1935 ncec->ncec_lladdr); 1936 return ("Unknown"); 1937 } 1938 mdb_mac_addr(h, ill->ill_phys_addr_length, 1939 addr_buf, sizeof (addr_buf)); 1940 } else { 1941 return ("None"); 1942 } 1943 mdb_free(h, ill->ill_phys_addr_length); 1944 return (addr_buf); 1945 } 1946 1947 static char * 1948 nce_l2_addr(const nce_t *nce, const ill_t *ill) 1949 { 1950 uchar_t *h; 1951 static char addr_buf[L2MAXADDRSTRLEN]; 1952 mblk_t mp; 1953 size_t mblen; 1954 1955 if (nce->nce_dlur_mp == NULL) 1956 return ("None"); 1957 1958 if (ill->ill_net_type == IRE_IF_RESOLVER) { 1959 if (mdb_vread(&mp, sizeof (mblk_t), 1960 (uintptr_t)nce->nce_dlur_mp) == -1) { 1961 mdb_warn("failed to read nce_dlur_mp at %p", 1962 nce->nce_dlur_mp); 1963 return ("None"); 1964 } 1965 if (ill->ill_phys_addr_length == 0) 1966 return ("None"); 1967 mblen = mp.b_wptr - mp.b_rptr; 1968 if (mblen > (sizeof (dl_unitdata_req_t) + MAX_SAP_LEN) || 1969 ill->ill_phys_addr_length > MAX_SAP_LEN || 1970 (NCE_LL_ADDR_OFFSET(ill) + 1971 ill->ill_phys_addr_length) > mblen) { 1972 return ("Unknown"); 1973 } 1974 h = mdb_zalloc(mblen, UM_SLEEP); 1975 if (mdb_vread(h, mblen, (uintptr_t)(mp.b_rptr)) == -1) { 1976 mdb_warn("failed to read hwaddr at %p", 1977 mp.b_rptr + NCE_LL_ADDR_OFFSET(ill)); 1978 return ("Unknown"); 1979 } 1980 mdb_mac_addr(h + NCE_LL_ADDR_OFFSET(ill), 1981 ill->ill_phys_addr_length, addr_buf, sizeof (addr_buf)); 1982 } else { 1983 return ("None"); 1984 } 1985 mdb_free(h, mblen); 1986 return (addr_buf); 1987 } 1988 1989 static void 1990 ncec_header(uint_t flags) 1991 { 1992 if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 1993 1994 mdb_printf("%<u>%?s %-20s %-10s %-8s %-5s %s%</u>\n", 1995 "ADDR", "HW_ADDR", "STATE", "FLAGS", "ILL", "IP ADDR"); 1996 } 1997 } 1998 1999 int 2000 ncec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2001 { 2002 ncec_t ncec; 2003 ncec_cbdata_t id; 2004 int ipversion = 0; 2005 const char *opt_P = NULL; 2006 2007 if (mdb_getopts(argc, argv, 2008 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 2009 return (DCMD_USAGE); 2010 2011 if (opt_P != NULL) { 2012 if (strcmp("v4", opt_P) == 0) { 2013 ipversion = IPV4_VERSION; 2014 } else if (strcmp("v6", opt_P) == 0) { 2015 ipversion = IPV6_VERSION; 2016 } else { 2017 mdb_warn("invalid protocol '%s'\n", opt_P); 2018 return (DCMD_USAGE); 2019 } 2020 } 2021 2022 if (flags & DCMD_ADDRSPEC) { 2023 2024 if (mdb_vread(&ncec, sizeof (ncec_t), addr) == -1) { 2025 mdb_warn("failed to read ncec at %p\n", addr); 2026 return (DCMD_ERR); 2027 } 2028 if (ipversion != 0 && ncec.ncec_ipversion != ipversion) { 2029 mdb_printf("IP Version mismatch\n"); 2030 return (DCMD_ERR); 2031 } 2032 ncec_header(flags); 2033 return (ncec_format(addr, &ncec, ipversion)); 2034 2035 } else { 2036 id.ncec_addr = addr; 2037 id.ncec_ipversion = ipversion; 2038 ncec_header(flags); 2039 if (mdb_walk("ncec", (mdb_walk_cb_t)ncec_cb, &id) == -1) { 2040 mdb_warn("failed to walk ncec table\n"); 2041 return (DCMD_ERR); 2042 } 2043 } 2044 return (DCMD_OK); 2045 } 2046 2047 static int 2048 ncec_format(uintptr_t addr, const ncec_t *ncec, int ipversion) 2049 { 2050 static const mdb_bitmask_t ncec_flags[] = { 2051 { "P", NCE_F_NONUD, NCE_F_NONUD }, 2052 { "R", NCE_F_ISROUTER, NCE_F_ISROUTER }, 2053 { "N", NCE_F_NONUD, NCE_F_NONUD }, 2054 { "A", NCE_F_ANYCAST, NCE_F_ANYCAST }, 2055 { "C", NCE_F_CONDEMNED, NCE_F_CONDEMNED }, 2056 { "U", NCE_F_UNSOL_ADV, NCE_F_UNSOL_ADV }, 2057 { "B", NCE_F_BCAST, NCE_F_BCAST }, 2058 { NULL, 0, 0 } 2059 }; 2060 #define NCE_MAX_FLAGS (sizeof (ncec_flags) / sizeof (mdb_bitmask_t)) 2061 struct in_addr nceaddr; 2062 ill_t ill; 2063 char ill_name[LIFNAMSIZ]; 2064 char flagsbuf[NCE_MAX_FLAGS]; 2065 2066 if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ncec->ncec_ill) == -1) { 2067 mdb_warn("failed to read ncec_ill at %p", 2068 ncec->ncec_ill); 2069 return (DCMD_ERR); 2070 } 2071 2072 (void) mdb_readstr(ill_name, MIN(LIFNAMSIZ, ill.ill_name_length), 2073 (uintptr_t)ill.ill_name); 2074 2075 mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%hb", 2076 ncec->ncec_flags, ncec_flags); 2077 2078 if (ipversion != 0 && ncec->ncec_ipversion != ipversion) 2079 return (DCMD_OK); 2080 2081 if (ncec->ncec_ipversion == IPV4_VERSION) { 2082 IN6_V4MAPPED_TO_INADDR(&ncec->ncec_addr, &nceaddr); 2083 mdb_printf("%?p %-20s %-10s " 2084 "%-8s " 2085 "%-5s %I\n", 2086 addr, ncec_l2_addr(ncec, &ill), 2087 ncec_state(ncec->ncec_state), 2088 flagsbuf, 2089 ill_name, nceaddr.s_addr); 2090 } else { 2091 mdb_printf("%?p %-20s %-10s %-8s %-5s %N\n", 2092 addr, ncec_l2_addr(ncec, &ill), 2093 ncec_state(ncec->ncec_state), 2094 flagsbuf, 2095 ill_name, &ncec->ncec_addr); 2096 } 2097 2098 return (DCMD_OK); 2099 } 2100 2101 static uintptr_t 2102 ncec_get_next_hash_tbl(uintptr_t start, int *index, struct ndp_g_s ndp) 2103 { 2104 uintptr_t addr = start; 2105 int i = *index; 2106 2107 while (addr == NULL) { 2108 2109 if (++i >= NCE_TABLE_SIZE) 2110 break; 2111 addr = (uintptr_t)ndp.nce_hash_tbl[i]; 2112 } 2113 *index = i; 2114 return (addr); 2115 } 2116 2117 static int 2118 ncec_walk_step(mdb_walk_state_t *wsp) 2119 { 2120 uintptr_t kaddr4, kaddr6; 2121 2122 kaddr4 = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ndp4); 2123 kaddr6 = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ndp6); 2124 2125 if (mdb_vread(&kaddr4, sizeof (kaddr4), kaddr4) == -1) { 2126 mdb_warn("can't read ips_ip_cache_table at %p", kaddr4); 2127 return (WALK_ERR); 2128 } 2129 if (mdb_vread(&kaddr6, sizeof (kaddr6), kaddr6) == -1) { 2130 mdb_warn("can't read ips_ip_cache_table at %p", kaddr6); 2131 return (WALK_ERR); 2132 } 2133 if (mdb_pwalk("ncec_stack", wsp->walk_callback, wsp->walk_cbdata, 2134 kaddr4) == -1) { 2135 mdb_warn("couldn't walk 'ncec_stack' for ips_ndp4 %p", 2136 kaddr4); 2137 return (WALK_ERR); 2138 } 2139 if (mdb_pwalk("ncec_stack", wsp->walk_callback, 2140 wsp->walk_cbdata, kaddr6) == -1) { 2141 mdb_warn("couldn't walk 'ncec_stack' for ips_ndp6 %p", 2142 kaddr6); 2143 return (WALK_ERR); 2144 } 2145 return (WALK_NEXT); 2146 } 2147 2148 static uintptr_t 2149 ipcl_hash_get_next_connf_tbl(ipcl_hash_walk_data_t *iw) 2150 { 2151 struct connf_s connf; 2152 uintptr_t addr = NULL, next; 2153 int index = iw->connf_tbl_index; 2154 2155 do { 2156 next = iw->hash_tbl + index * sizeof (struct connf_s); 2157 if (++index >= iw->hash_tbl_size) { 2158 addr = NULL; 2159 break; 2160 } 2161 if (mdb_vread(&connf, sizeof (struct connf_s), next) == -1) { 2162 mdb_warn("failed to read conn_t at %p", next); 2163 return (NULL); 2164 } 2165 addr = (uintptr_t)connf.connf_head; 2166 } while (addr == NULL); 2167 iw->connf_tbl_index = index; 2168 return (addr); 2169 } 2170 2171 static int 2172 ipcl_hash_walk_init(mdb_walk_state_t *wsp) 2173 { 2174 const hash_walk_arg_t *arg = wsp->walk_arg; 2175 ipcl_hash_walk_data_t *iw; 2176 uintptr_t tbladdr; 2177 uintptr_t sizeaddr; 2178 2179 iw = mdb_alloc(sizeof (ipcl_hash_walk_data_t), UM_SLEEP); 2180 iw->conn = mdb_alloc(sizeof (conn_t), UM_SLEEP); 2181 tbladdr = wsp->walk_addr + arg->tbl_off; 2182 sizeaddr = wsp->walk_addr + arg->size_off; 2183 2184 if (mdb_vread(&iw->hash_tbl, sizeof (uintptr_t), tbladdr) == -1) { 2185 mdb_warn("can't read fanout table addr at %p", tbladdr); 2186 mdb_free(iw->conn, sizeof (conn_t)); 2187 mdb_free(iw, sizeof (ipcl_hash_walk_data_t)); 2188 return (WALK_ERR); 2189 } 2190 if (arg->tbl_off == OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v4) || 2191 arg->tbl_off == OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v6)) { 2192 iw->hash_tbl_size = IPPROTO_MAX; 2193 } else { 2194 if (mdb_vread(&iw->hash_tbl_size, sizeof (int), 2195 sizeaddr) == -1) { 2196 mdb_warn("can't read fanout table size addr at %p", 2197 sizeaddr); 2198 mdb_free(iw->conn, sizeof (conn_t)); 2199 mdb_free(iw, sizeof (ipcl_hash_walk_data_t)); 2200 return (WALK_ERR); 2201 } 2202 } 2203 iw->connf_tbl_index = 0; 2204 wsp->walk_addr = ipcl_hash_get_next_connf_tbl(iw); 2205 wsp->walk_data = iw; 2206 2207 if (wsp->walk_addr != NULL) 2208 return (WALK_NEXT); 2209 else 2210 return (WALK_DONE); 2211 } 2212 2213 static int 2214 ipcl_hash_walk_step(mdb_walk_state_t *wsp) 2215 { 2216 uintptr_t addr = wsp->walk_addr; 2217 ipcl_hash_walk_data_t *iw = wsp->walk_data; 2218 conn_t *conn = iw->conn; 2219 int ret = WALK_DONE; 2220 2221 while (addr != NULL) { 2222 if (mdb_vread(conn, sizeof (conn_t), addr) == -1) { 2223 mdb_warn("failed to read conn_t at %p", addr); 2224 return (WALK_ERR); 2225 } 2226 ret = wsp->walk_callback(addr, iw, wsp->walk_cbdata); 2227 if (ret != WALK_NEXT) 2228 break; 2229 addr = (uintptr_t)conn->conn_next; 2230 } 2231 if (ret == WALK_NEXT) { 2232 wsp->walk_addr = ipcl_hash_get_next_connf_tbl(iw); 2233 2234 if (wsp->walk_addr != NULL) 2235 return (WALK_NEXT); 2236 else 2237 return (WALK_DONE); 2238 } 2239 2240 return (ret); 2241 } 2242 2243 static void 2244 ipcl_hash_walk_fini(mdb_walk_state_t *wsp) 2245 { 2246 ipcl_hash_walk_data_t *iw = wsp->walk_data; 2247 2248 mdb_free(iw->conn, sizeof (conn_t)); 2249 mdb_free(iw, sizeof (ipcl_hash_walk_data_t)); 2250 } 2251 2252 /* 2253 * Called with walk_addr being the address of ips_ndp{4,6} 2254 */ 2255 static int 2256 ncec_stack_walk_init(mdb_walk_state_t *wsp) 2257 { 2258 ncec_walk_data_t *nw; 2259 2260 if (wsp->walk_addr == NULL) { 2261 mdb_warn("ncec_stack requires ndp_g_s address\n"); 2262 return (WALK_ERR); 2263 } 2264 2265 nw = mdb_alloc(sizeof (ncec_walk_data_t), UM_SLEEP); 2266 2267 if (mdb_vread(&nw->ncec_ip_ndp, sizeof (struct ndp_g_s), 2268 wsp->walk_addr) == -1) { 2269 mdb_warn("failed to read 'ip_ndp' at %p", 2270 wsp->walk_addr); 2271 mdb_free(nw, sizeof (ncec_walk_data_t)); 2272 return (WALK_ERR); 2273 } 2274 2275 /* 2276 * ncec_get_next_hash_tbl() starts at ++i , so initialize index to -1 2277 */ 2278 nw->ncec_hash_tbl_index = -1; 2279 wsp->walk_addr = ncec_get_next_hash_tbl(NULL, 2280 &nw->ncec_hash_tbl_index, nw->ncec_ip_ndp); 2281 wsp->walk_data = nw; 2282 2283 return (WALK_NEXT); 2284 } 2285 2286 static int 2287 ncec_stack_walk_step(mdb_walk_state_t *wsp) 2288 { 2289 uintptr_t addr = wsp->walk_addr; 2290 ncec_walk_data_t *nw = wsp->walk_data; 2291 2292 if (addr == NULL) 2293 return (WALK_DONE); 2294 2295 if (mdb_vread(&nw->ncec, sizeof (ncec_t), addr) == -1) { 2296 mdb_warn("failed to read ncec_t at %p", addr); 2297 return (WALK_ERR); 2298 } 2299 2300 wsp->walk_addr = (uintptr_t)nw->ncec.ncec_next; 2301 2302 wsp->walk_addr = ncec_get_next_hash_tbl(wsp->walk_addr, 2303 &nw->ncec_hash_tbl_index, nw->ncec_ip_ndp); 2304 2305 return (wsp->walk_callback(addr, nw, wsp->walk_cbdata)); 2306 } 2307 2308 static void 2309 ncec_stack_walk_fini(mdb_walk_state_t *wsp) 2310 { 2311 mdb_free(wsp->walk_data, sizeof (ncec_walk_data_t)); 2312 } 2313 2314 /* ARGSUSED */ 2315 static int 2316 ncec_cb(uintptr_t addr, const ncec_walk_data_t *iw, ncec_cbdata_t *id) 2317 { 2318 ncec_t ncec; 2319 2320 if (mdb_vread(&ncec, sizeof (ncec_t), addr) == -1) { 2321 mdb_warn("failed to read ncec at %p", addr); 2322 return (WALK_NEXT); 2323 } 2324 (void) ncec_format(addr, &ncec, id->ncec_ipversion); 2325 return (WALK_NEXT); 2326 } 2327 2328 static int 2329 ill_walk_init(mdb_walk_state_t *wsp) 2330 { 2331 if (mdb_layered_walk("illif", wsp) == -1) { 2332 mdb_warn("can't walk 'illif'"); 2333 return (WALK_ERR); 2334 } 2335 return (WALK_NEXT); 2336 } 2337 2338 static int 2339 ill_walk_step(mdb_walk_state_t *wsp) 2340 { 2341 ill_if_t ill_if; 2342 2343 if (mdb_vread(&ill_if, sizeof (ill_if_t), wsp->walk_addr) == -1) { 2344 mdb_warn("can't read ill_if_t at %p", wsp->walk_addr); 2345 return (WALK_ERR); 2346 } 2347 wsp->walk_addr = (uintptr_t)(wsp->walk_addr + 2348 offsetof(ill_if_t, illif_avl_by_ppa)); 2349 if (mdb_pwalk("avl", wsp->walk_callback, wsp->walk_cbdata, 2350 wsp->walk_addr) == -1) { 2351 mdb_warn("can't walk 'avl'"); 2352 return (WALK_ERR); 2353 } 2354 2355 return (WALK_NEXT); 2356 } 2357 2358 /* ARGSUSED */ 2359 static int 2360 ill_cb(uintptr_t addr, const ill_walk_data_t *iw, ill_cbdata_t *id) 2361 { 2362 ill_t ill; 2363 2364 if (mdb_vread(&ill, sizeof (ill_t), (uintptr_t)addr) == -1) { 2365 mdb_warn("failed to read ill at %p", addr); 2366 return (WALK_NEXT); 2367 } 2368 2369 /* If ip_stack_t is specified, skip ILLs that don't belong to it. */ 2370 if (id->ill_ipst != NULL && ill.ill_ipst != id->ill_ipst) 2371 return (WALK_NEXT); 2372 2373 return (ill_format((uintptr_t)addr, &ill, id)); 2374 } 2375 2376 static void 2377 ill_header(boolean_t verbose) 2378 { 2379 if (verbose) { 2380 mdb_printf("%-?s %-8s %3s %-10s %-?s %-?s %-10s%</u>\n", 2381 "ADDR", "NAME", "VER", "TYPE", "WQ", "IPST", "FLAGS"); 2382 mdb_printf("%-?s %4s%4s %-?s\n", 2383 "PHYINT", "CNT", "", "GROUP"); 2384 mdb_printf("%<u>%80s%</u>\n", ""); 2385 } else { 2386 mdb_printf("%<u>%-?s %-8s %-3s %-10s %4s %-?s %-10s%</u>\n", 2387 "ADDR", "NAME", "VER", "TYPE", "CNT", "WQ", "FLAGS"); 2388 } 2389 } 2390 2391 static int 2392 ill_format(uintptr_t addr, const void *illptr, void *ill_cb_arg) 2393 { 2394 ill_t *ill = (ill_t *)illptr; 2395 ill_cbdata_t *illcb = ill_cb_arg; 2396 boolean_t verbose = illcb->verbose; 2397 phyint_t phyi; 2398 static const mdb_bitmask_t fmasks[] = { 2399 { "R", PHYI_RUNNING, PHYI_RUNNING }, 2400 { "P", PHYI_PROMISC, PHYI_PROMISC }, 2401 { "V", PHYI_VIRTUAL, PHYI_VIRTUAL }, 2402 { "I", PHYI_IPMP, PHYI_IPMP }, 2403 { "f", PHYI_FAILED, PHYI_FAILED }, 2404 { "S", PHYI_STANDBY, PHYI_STANDBY }, 2405 { "i", PHYI_INACTIVE, PHYI_INACTIVE }, 2406 { "O", PHYI_OFFLINE, PHYI_OFFLINE }, 2407 { "T", ILLF_NOTRAILERS, ILLF_NOTRAILERS }, 2408 { "A", ILLF_NOARP, ILLF_NOARP }, 2409 { "M", ILLF_MULTICAST, ILLF_MULTICAST }, 2410 { "F", ILLF_ROUTER, ILLF_ROUTER }, 2411 { "D", ILLF_NONUD, ILLF_NONUD }, 2412 { "X", ILLF_NORTEXCH, ILLF_NORTEXCH }, 2413 { NULL, 0, 0 } 2414 }; 2415 static const mdb_bitmask_t v_fmasks[] = { 2416 { "RUNNING", PHYI_RUNNING, PHYI_RUNNING }, 2417 { "PROMISC", PHYI_PROMISC, PHYI_PROMISC }, 2418 { "VIRTUAL", PHYI_VIRTUAL, PHYI_VIRTUAL }, 2419 { "IPMP", PHYI_IPMP, PHYI_IPMP }, 2420 { "FAILED", PHYI_FAILED, PHYI_FAILED }, 2421 { "STANDBY", PHYI_STANDBY, PHYI_STANDBY }, 2422 { "INACTIVE", PHYI_INACTIVE, PHYI_INACTIVE }, 2423 { "OFFLINE", PHYI_OFFLINE, PHYI_OFFLINE }, 2424 { "NOTRAILER", ILLF_NOTRAILERS, ILLF_NOTRAILERS }, 2425 { "NOARP", ILLF_NOARP, ILLF_NOARP }, 2426 { "MULTICAST", ILLF_MULTICAST, ILLF_MULTICAST }, 2427 { "ROUTER", ILLF_ROUTER, ILLF_ROUTER }, 2428 { "NONUD", ILLF_NONUD, ILLF_NONUD }, 2429 { "NORTEXCH", ILLF_NORTEXCH, ILLF_NORTEXCH }, 2430 { NULL, 0, 0 } 2431 }; 2432 char ill_name[LIFNAMSIZ]; 2433 int cnt; 2434 char *typebuf; 2435 char sbuf[DEFCOLS]; 2436 int ipver = illcb->ill_ipversion; 2437 2438 if (ipver != 0) { 2439 if ((ipver == IPV4_VERSION && ill->ill_isv6) || 2440 (ipver == IPV6_VERSION && !ill->ill_isv6)) { 2441 return (WALK_NEXT); 2442 } 2443 } 2444 if (mdb_vread(&phyi, sizeof (phyint_t), 2445 (uintptr_t)ill->ill_phyint) == -1) { 2446 mdb_warn("failed to read ill_phyint at %p", 2447 (uintptr_t)ill->ill_phyint); 2448 return (WALK_NEXT); 2449 } 2450 (void) mdb_readstr(ill_name, MIN(LIFNAMSIZ, ill->ill_name_length), 2451 (uintptr_t)ill->ill_name); 2452 2453 switch (ill->ill_type) { 2454 case 0: 2455 typebuf = "LOOPBACK"; 2456 break; 2457 case IFT_ETHER: 2458 typebuf = "ETHER"; 2459 break; 2460 case IFT_OTHER: 2461 typebuf = "OTHER"; 2462 break; 2463 default: 2464 typebuf = NULL; 2465 break; 2466 } 2467 cnt = ill->ill_refcnt + ill->ill_ire_cnt + ill->ill_nce_cnt + 2468 ill->ill_ilm_cnt + ill->ill_ncec_cnt; 2469 mdb_printf("%-?p %-8s %-3s ", 2470 addr, ill_name, ill->ill_isv6 ? "v6" : "v4"); 2471 if (typebuf != NULL) 2472 mdb_printf("%-10s ", typebuf); 2473 else 2474 mdb_printf("%-10x ", ill->ill_type); 2475 if (verbose) { 2476 mdb_printf("%-?p %-?p %-llb\n", 2477 ill->ill_wq, ill->ill_ipst, 2478 ill->ill_flags | phyi.phyint_flags, v_fmasks); 2479 mdb_printf("%-?p %4d%4s %-?p\n", 2480 ill->ill_phyint, cnt, "", ill->ill_grp); 2481 mdb_snprintf(sbuf, sizeof (sbuf), "%*s %3s", 2482 sizeof (uintptr_t) * 2, "", ""); 2483 mdb_printf("%s|\n%s+--> %3d %-18s " 2484 "references from active threads\n", 2485 sbuf, sbuf, ill->ill_refcnt, "ill_refcnt"); 2486 mdb_printf("%*s %7d %-18s ires referencing this ill\n", 2487 strlen(sbuf), "", ill->ill_ire_cnt, "ill_ire_cnt"); 2488 mdb_printf("%*s %7d %-18s nces referencing this ill\n", 2489 strlen(sbuf), "", ill->ill_nce_cnt, "ill_nce_cnt"); 2490 mdb_printf("%*s %7d %-18s ncecs referencing this ill\n", 2491 strlen(sbuf), "", ill->ill_ncec_cnt, "ill_ncec_cnt"); 2492 mdb_printf("%*s %7d %-18s ilms referencing this ill\n", 2493 strlen(sbuf), "", ill->ill_ilm_cnt, "ill_ilm_cnt"); 2494 } else { 2495 mdb_printf("%4d %-?p %-llb\n", 2496 cnt, ill->ill_wq, 2497 ill->ill_flags | phyi.phyint_flags, fmasks); 2498 } 2499 return (WALK_NEXT); 2500 } 2501 2502 static int 2503 ill(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2504 { 2505 ill_t ill_data; 2506 ill_cbdata_t id; 2507 int ipversion = 0; 2508 const char *zone_name = NULL; 2509 const char *opt_P = NULL; 2510 uint_t verbose = FALSE; 2511 ip_stack_t *ipst = NULL; 2512 2513 if (mdb_getopts(argc, argv, 2514 'v', MDB_OPT_SETBITS, TRUE, &verbose, 2515 's', MDB_OPT_STR, &zone_name, 2516 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 2517 return (DCMD_USAGE); 2518 2519 /* Follow the specified zone name to find a ip_stack_t*. */ 2520 if (zone_name != NULL) { 2521 ipst = zone_to_ips(zone_name); 2522 if (ipst == NULL) 2523 return (DCMD_USAGE); 2524 } 2525 2526 if (opt_P != NULL) { 2527 if (strcmp("v4", opt_P) == 0) { 2528 ipversion = IPV4_VERSION; 2529 } else if (strcmp("v6", opt_P) == 0) { 2530 ipversion = IPV6_VERSION; 2531 } else { 2532 mdb_warn("invalid protocol '%s'\n", opt_P); 2533 return (DCMD_USAGE); 2534 } 2535 } 2536 2537 id.verbose = verbose; 2538 id.ill_addr = addr; 2539 id.ill_ipversion = ipversion; 2540 id.ill_ipst = ipst; 2541 2542 ill_header(verbose); 2543 if (flags & DCMD_ADDRSPEC) { 2544 if (mdb_vread(&ill_data, sizeof (ill_t), addr) == -1) { 2545 mdb_warn("failed to read ill at %p\n", addr); 2546 return (DCMD_ERR); 2547 } 2548 (void) ill_format(addr, &ill_data, &id); 2549 } else { 2550 if (mdb_walk("ill", (mdb_walk_cb_t)ill_cb, &id) == -1) { 2551 mdb_warn("failed to walk ills\n"); 2552 return (DCMD_ERR); 2553 } 2554 } 2555 return (DCMD_OK); 2556 } 2557 2558 static void 2559 ill_help(void) 2560 { 2561 mdb_printf("Prints the following fields: ill ptr, name, " 2562 "IP version, count, ill type and ill flags.\n" 2563 "The count field is a sum of individual refcnts and is expanded " 2564 "with the -v option.\n\n"); 2565 mdb_printf("Options:\n"); 2566 mdb_printf("\t-P v4 | v6" 2567 "\tfilter ill structures for the specified protocol\n"); 2568 } 2569 2570 static int 2571 ip_list_walk_init(mdb_walk_state_t *wsp) 2572 { 2573 const ip_list_walk_arg_t *arg = wsp->walk_arg; 2574 ip_list_walk_data_t *iw; 2575 uintptr_t addr = (uintptr_t)(wsp->walk_addr + arg->off); 2576 2577 if (wsp->walk_addr == NULL) { 2578 mdb_warn("only local walks supported\n"); 2579 return (WALK_ERR); 2580 } 2581 if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t), 2582 addr) == -1) { 2583 mdb_warn("failed to read list head at %p", addr); 2584 return (WALK_ERR); 2585 } 2586 iw = mdb_alloc(sizeof (ip_list_walk_data_t), UM_SLEEP); 2587 iw->nextoff = arg->nextp_off; 2588 wsp->walk_data = iw; 2589 2590 return (WALK_NEXT); 2591 } 2592 2593 static int 2594 ip_list_walk_step(mdb_walk_state_t *wsp) 2595 { 2596 ip_list_walk_data_t *iw = wsp->walk_data; 2597 uintptr_t addr = wsp->walk_addr; 2598 2599 if (addr == NULL) 2600 return (WALK_DONE); 2601 wsp->walk_addr = addr + iw->nextoff; 2602 if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t), 2603 wsp->walk_addr) == -1) { 2604 mdb_warn("failed to read list node at %p", addr); 2605 return (WALK_ERR); 2606 } 2607 return (wsp->walk_callback(addr, iw, wsp->walk_cbdata)); 2608 } 2609 2610 static void 2611 ip_list_walk_fini(mdb_walk_state_t *wsp) 2612 { 2613 mdb_free(wsp->walk_data, sizeof (ip_list_walk_data_t)); 2614 } 2615 2616 static int 2617 ipif_walk_init(mdb_walk_state_t *wsp) 2618 { 2619 if (mdb_layered_walk("ill", wsp) == -1) { 2620 mdb_warn("can't walk 'ills'"); 2621 return (WALK_ERR); 2622 } 2623 return (WALK_NEXT); 2624 } 2625 2626 static int 2627 ipif_walk_step(mdb_walk_state_t *wsp) 2628 { 2629 if (mdb_pwalk("ipif_list", wsp->walk_callback, wsp->walk_cbdata, 2630 wsp->walk_addr) == -1) { 2631 mdb_warn("can't walk 'ipif_list'"); 2632 return (WALK_ERR); 2633 } 2634 2635 return (WALK_NEXT); 2636 } 2637 2638 /* ARGSUSED */ 2639 static int 2640 ipif_cb(uintptr_t addr, const ipif_walk_data_t *iw, ipif_cbdata_t *id) 2641 { 2642 ipif_t ipif; 2643 2644 if (mdb_vread(&ipif, sizeof (ipif_t), (uintptr_t)addr) == -1) { 2645 mdb_warn("failed to read ipif at %p", addr); 2646 return (WALK_NEXT); 2647 } 2648 if (mdb_vread(&id->ill, sizeof (ill_t), 2649 (uintptr_t)ipif.ipif_ill) == -1) { 2650 mdb_warn("failed to read ill at %p", ipif.ipif_ill); 2651 return (WALK_NEXT); 2652 } 2653 (void) ipif_format((uintptr_t)addr, &ipif, id); 2654 return (WALK_NEXT); 2655 } 2656 2657 static void 2658 ipif_header(boolean_t verbose) 2659 { 2660 if (verbose) { 2661 mdb_printf("%-?s %-10s %-3s %-?s %-8s %-30s\n", 2662 "ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS"); 2663 mdb_printf("%s\n%s\n", 2664 "LCLADDR", "BROADCAST"); 2665 mdb_printf("%<u>%80s%</u>\n", ""); 2666 } else { 2667 mdb_printf("%-?s %-10s %6s %-?s %-8s %-30s\n", 2668 "ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS"); 2669 mdb_printf("%s\n%<u>%80s%</u>\n", "LCLADDR", ""); 2670 } 2671 } 2672 2673 #ifdef _BIG_ENDIAN 2674 #define ip_ntohl_32(x) ((x) & 0xffffffff) 2675 #else 2676 #define ip_ntohl_32(x) (((uint32_t)(x) << 24) | \ 2677 (((uint32_t)(x) << 8) & 0xff0000) | \ 2678 (((uint32_t)(x) >> 8) & 0xff00) | \ 2679 ((uint32_t)(x) >> 24)) 2680 #endif 2681 2682 int 2683 mask_to_prefixlen(int af, const in6_addr_t *addr) 2684 { 2685 int len = 0; 2686 int i; 2687 uint_t mask = 0; 2688 2689 if (af == AF_INET6) { 2690 for (i = 0; i < 4; i++) { 2691 if (addr->s6_addr32[i] == 0xffffffff) { 2692 len += 32; 2693 } else { 2694 mask = addr->s6_addr32[i]; 2695 break; 2696 } 2697 } 2698 } else { 2699 mask = V4_PART_OF_V6((*addr)); 2700 } 2701 if (mask > 0) 2702 len += (33 - mdb_ffs(ip_ntohl_32(mask))); 2703 return (len); 2704 } 2705 2706 static int 2707 ipif_format(uintptr_t addr, const void *ipifptr, void *ipif_cb_arg) 2708 { 2709 const ipif_t *ipif = ipifptr; 2710 ipif_cbdata_t *ipifcb = ipif_cb_arg; 2711 boolean_t verbose = ipifcb->verbose; 2712 char ill_name[LIFNAMSIZ]; 2713 char buf[LIFNAMSIZ]; 2714 int cnt; 2715 static const mdb_bitmask_t sfmasks[] = { 2716 { "CO", IPIF_CONDEMNED, IPIF_CONDEMNED}, 2717 { "CH", IPIF_CHANGING, IPIF_CHANGING}, 2718 { "SL", IPIF_SET_LINKLOCAL, IPIF_SET_LINKLOCAL}, 2719 { NULL, 0, 0 } 2720 }; 2721 static const mdb_bitmask_t fmasks[] = { 2722 { "UP", IPIF_UP, IPIF_UP }, 2723 { "UNN", IPIF_UNNUMBERED, IPIF_UNNUMBERED}, 2724 { "DHCP", IPIF_DHCPRUNNING, IPIF_DHCPRUNNING}, 2725 { "PRIV", IPIF_PRIVATE, IPIF_PRIVATE}, 2726 { "NOXMT", IPIF_NOXMIT, IPIF_NOXMIT}, 2727 { "NOLCL", IPIF_NOLOCAL, IPIF_NOLOCAL}, 2728 { "DEPR", IPIF_DEPRECATED, IPIF_DEPRECATED}, 2729 { "PREF", IPIF_PREFERRED, IPIF_PREFERRED}, 2730 { "TEMP", IPIF_TEMPORARY, IPIF_TEMPORARY}, 2731 { "ACONF", IPIF_ADDRCONF, IPIF_ADDRCONF}, 2732 { "ANY", IPIF_ANYCAST, IPIF_ANYCAST}, 2733 { "NFAIL", IPIF_NOFAILOVER, IPIF_NOFAILOVER}, 2734 { NULL, 0, 0 } 2735 }; 2736 char flagsbuf[2 * A_CNT(fmasks)]; 2737 char bitfields[A_CNT(fmasks)]; 2738 char sflagsbuf[A_CNT(sfmasks)]; 2739 char sbuf[DEFCOLS], addrstr[INET6_ADDRSTRLEN]; 2740 int ipver = ipifcb->ipif_ipversion; 2741 int af; 2742 2743 if (ipver != 0) { 2744 if ((ipver == IPV4_VERSION && ipifcb->ill.ill_isv6) || 2745 (ipver == IPV6_VERSION && !ipifcb->ill.ill_isv6)) { 2746 return (WALK_NEXT); 2747 } 2748 } 2749 if ((mdb_readstr(ill_name, MIN(LIFNAMSIZ, 2750 ipifcb->ill.ill_name_length), 2751 (uintptr_t)ipifcb->ill.ill_name)) == -1) { 2752 mdb_warn("failed to read ill_name of ill %p\n", ipifcb->ill); 2753 return (WALK_NEXT); 2754 } 2755 if (ipif->ipif_id != 0) { 2756 mdb_snprintf(buf, LIFNAMSIZ, "%s:%d", 2757 ill_name, ipif->ipif_id); 2758 } else { 2759 mdb_snprintf(buf, LIFNAMSIZ, "%s", ill_name); 2760 } 2761 mdb_snprintf(bitfields, sizeof (bitfields), "%s", 2762 ipif->ipif_addr_ready ? ",ADR" : "", 2763 ipif->ipif_was_up ? ",WU" : "", 2764 ipif->ipif_was_dup ? ",WD" : ""); 2765 mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%llb%s", 2766 ipif->ipif_flags, fmasks, bitfields); 2767 mdb_snprintf(sflagsbuf, sizeof (sflagsbuf), "%b", 2768 ipif->ipif_state_flags, sfmasks); 2769 2770 cnt = ipif->ipif_refcnt; 2771 2772 if (ipifcb->ill.ill_isv6) { 2773 mdb_snprintf(addrstr, sizeof (addrstr), "%N", 2774 &ipif->ipif_v6lcl_addr); 2775 af = AF_INET6; 2776 } else { 2777 mdb_snprintf(addrstr, sizeof (addrstr), "%I", 2778 V4_PART_OF_V6((ipif->ipif_v6lcl_addr))); 2779 af = AF_INET; 2780 } 2781 2782 if (verbose) { 2783 mdb_printf("%-?p %-10s %3d %-?p %-8s %-30s\n", 2784 addr, buf, cnt, ipif->ipif_ill, 2785 sflagsbuf, flagsbuf); 2786 mdb_snprintf(sbuf, sizeof (sbuf), "%*s %12s", 2787 sizeof (uintptr_t) * 2, "", ""); 2788 mdb_printf("%s |\n%s +---> %4d %-15s " 2789 "Active consistent reader cnt\n", 2790 sbuf, sbuf, ipif->ipif_refcnt, "ipif_refcnt"); 2791 mdb_printf("%-s/%d\n", 2792 addrstr, mask_to_prefixlen(af, &ipif->ipif_v6net_mask)); 2793 if (ipifcb->ill.ill_isv6) { 2794 mdb_printf("%-N\n", &ipif->ipif_v6brd_addr); 2795 } else { 2796 mdb_printf("%-I\n", 2797 V4_PART_OF_V6((ipif->ipif_v6brd_addr))); 2798 } 2799 } else { 2800 mdb_printf("%-?p %-10s %6d %-?p %-8s %-30s\n", 2801 addr, buf, cnt, ipif->ipif_ill, 2802 sflagsbuf, flagsbuf); 2803 mdb_printf("%-s/%d\n", 2804 addrstr, mask_to_prefixlen(af, &ipif->ipif_v6net_mask)); 2805 } 2806 2807 return (WALK_NEXT); 2808 } 2809 2810 static int 2811 ipif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2812 { 2813 ipif_t ipif; 2814 ipif_cbdata_t id; 2815 int ipversion = 0; 2816 const char *opt_P = NULL; 2817 uint_t verbose = FALSE; 2818 2819 if (mdb_getopts(argc, argv, 2820 'v', MDB_OPT_SETBITS, TRUE, &verbose, 2821 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 2822 return (DCMD_USAGE); 2823 2824 if (opt_P != NULL) { 2825 if (strcmp("v4", opt_P) == 0) { 2826 ipversion = IPV4_VERSION; 2827 } else if (strcmp("v6", opt_P) == 0) { 2828 ipversion = IPV6_VERSION; 2829 } else { 2830 mdb_warn("invalid protocol '%s'\n", opt_P); 2831 return (DCMD_USAGE); 2832 } 2833 } 2834 2835 id.verbose = verbose; 2836 id.ipif_ipversion = ipversion; 2837 2838 if (flags & DCMD_ADDRSPEC) { 2839 if (mdb_vread(&ipif, sizeof (ipif_t), addr) == -1) { 2840 mdb_warn("failed to read ipif at %p\n", addr); 2841 return (DCMD_ERR); 2842 } 2843 ipif_header(verbose); 2844 if (mdb_vread(&id.ill, sizeof (ill_t), 2845 (uintptr_t)ipif.ipif_ill) == -1) { 2846 mdb_warn("failed to read ill at %p", ipif.ipif_ill); 2847 return (WALK_NEXT); 2848 } 2849 return (ipif_format(addr, &ipif, &id)); 2850 } else { 2851 ipif_header(verbose); 2852 if (mdb_walk("ipif", (mdb_walk_cb_t)ipif_cb, &id) == -1) { 2853 mdb_warn("failed to walk ipifs\n"); 2854 return (DCMD_ERR); 2855 } 2856 } 2857 return (DCMD_OK); 2858 } 2859 2860 static void 2861 ipif_help(void) 2862 { 2863 mdb_printf("Prints the following fields: ipif ptr, name, " 2864 "count, ill ptr, state flags and ipif flags.\n" 2865 "The count field is a sum of individual refcnts and is expanded " 2866 "with the -v option.\n" 2867 "The flags field shows the following:" 2868 "\n\tUNN -> UNNUMBERED, DHCP -> DHCPRUNNING, PRIV -> PRIVATE, " 2869 "\n\tNOXMT -> NOXMIT, NOLCL -> NOLOCAL, DEPR -> DEPRECATED, " 2870 "\n\tPREF -> PREFERRED, TEMP -> TEMPORARY, ACONF -> ADDRCONF, " 2871 "\n\tANY -> ANYCAST, NFAIL -> NOFAILOVER, " 2872 "\n\tADR -> ipif_addr_ready, MU -> ipif_multicast_up, " 2873 "\n\tWU -> ipif_was_up, WD -> ipif_was_dup, " 2874 "JA -> ipif_joined_allhosts.\n\n"); 2875 mdb_printf("Options:\n"); 2876 mdb_printf("\t-P v4 | v6" 2877 "\tfilter ipif structures on ills for the specified protocol\n"); 2878 } 2879 2880 static int 2881 conn_status_walk_fanout(uintptr_t addr, mdb_walk_state_t *wsp, 2882 const char *walkname) 2883 { 2884 if (mdb_pwalk(walkname, wsp->walk_callback, wsp->walk_cbdata, 2885 addr) == -1) { 2886 mdb_warn("couldn't walk '%s' at %p", walkname, addr); 2887 return (WALK_ERR); 2888 } 2889 return (WALK_NEXT); 2890 } 2891 2892 static int 2893 conn_status_walk_step(mdb_walk_state_t *wsp) 2894 { 2895 uintptr_t addr = wsp->walk_addr; 2896 2897 (void) conn_status_walk_fanout(addr, wsp, "udp_hash"); 2898 (void) conn_status_walk_fanout(addr, wsp, "conn_hash"); 2899 (void) conn_status_walk_fanout(addr, wsp, "bind_hash"); 2900 (void) conn_status_walk_fanout(addr, wsp, "proto_hash"); 2901 (void) conn_status_walk_fanout(addr, wsp, "proto_v6_hash"); 2902 return (WALK_NEXT); 2903 } 2904 2905 /* ARGSUSED */ 2906 static int 2907 conn_status_cb(uintptr_t addr, const void *walk_data, 2908 void *private) 2909 { 2910 netstack_t nss; 2911 char src_addrstr[INET6_ADDRSTRLEN]; 2912 char rem_addrstr[INET6_ADDRSTRLEN]; 2913 const ipcl_hash_walk_data_t *iw = walk_data; 2914 conn_t *conn = iw->conn; 2915 2916 if (mdb_vread(conn, sizeof (conn_t), addr) == -1) { 2917 mdb_warn("failed to read conn_t at %p", addr); 2918 return (WALK_ERR); 2919 } 2920 if (mdb_vread(&nss, sizeof (nss), 2921 (uintptr_t)conn->conn_netstack) == -1) { 2922 mdb_warn("failed to read netstack_t %p", 2923 conn->conn_netstack); 2924 return (WALK_ERR); 2925 } 2926 mdb_printf("%-?p %-?p %?d %?d\n", addr, conn->conn_wq, 2927 nss.netstack_stackid, conn->conn_zoneid); 2928 2929 if (conn->conn_family == AF_INET6) { 2930 mdb_snprintf(src_addrstr, sizeof (rem_addrstr), "%N", 2931 &conn->conn_laddr_v6); 2932 mdb_snprintf(rem_addrstr, sizeof (rem_addrstr), "%N", 2933 &conn->conn_faddr_v6); 2934 } else { 2935 mdb_snprintf(src_addrstr, sizeof (src_addrstr), "%I", 2936 V4_PART_OF_V6((conn->conn_laddr_v6))); 2937 mdb_snprintf(rem_addrstr, sizeof (rem_addrstr), "%I", 2938 V4_PART_OF_V6((conn->conn_faddr_v6))); 2939 } 2940 mdb_printf("%s:%-5d\n%s:%-5d\n", 2941 src_addrstr, conn->conn_lport, rem_addrstr, conn->conn_fport); 2942 return (WALK_NEXT); 2943 } 2944 2945 static void 2946 conn_header(void) 2947 { 2948 mdb_printf("%-?s %-?s %?s %?s\n%s\n%s\n", 2949 "ADDR", "WQ", "STACK", "ZONE", "SRC:PORT", "DEST:PORT"); 2950 mdb_printf("%<u>%80s%</u>\n", ""); 2951 } 2952 2953 /*ARGSUSED*/ 2954 static int 2955 conn_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2956 { 2957 conn_header(); 2958 if (flags & DCMD_ADDRSPEC) { 2959 (void) conn_status_cb(addr, NULL, NULL); 2960 } else { 2961 if (mdb_walk("conn_status", (mdb_walk_cb_t)conn_status_cb, 2962 NULL) == -1) { 2963 mdb_warn("failed to walk conn_fanout"); 2964 return (DCMD_ERR); 2965 } 2966 } 2967 return (DCMD_OK); 2968 } 2969 2970 static void 2971 conn_status_help(void) 2972 { 2973 mdb_printf("Prints conn_t structures from the following hash tables: " 2974 "\n\tips_ipcl_udp_fanout\n\tips_ipcl_bind_fanout" 2975 "\n\tips_ipcl_conn_fanout\n\tips_ipcl_proto_fanout_v4" 2976 "\n\tips_ipcl_proto_fanout_v6\n"); 2977 } 2978 2979 static int 2980 srcid_walk_step(mdb_walk_state_t *wsp) 2981 { 2982 if (mdb_pwalk("srcid_list", wsp->walk_callback, wsp->walk_cbdata, 2983 wsp->walk_addr) == -1) { 2984 mdb_warn("can't walk 'srcid_list'"); 2985 return (WALK_ERR); 2986 } 2987 return (WALK_NEXT); 2988 } 2989 2990 /* ARGSUSED */ 2991 static int 2992 srcid_status_cb(uintptr_t addr, const void *walk_data, 2993 void *private) 2994 { 2995 srcid_map_t smp; 2996 2997 if (mdb_vread(&smp, sizeof (srcid_map_t), addr) == -1) { 2998 mdb_warn("failed to read srcid_map at %p", addr); 2999 return (WALK_ERR); 3000 } 3001 mdb_printf("%-?p %3d %4d %6d %N\n", 3002 addr, smp.sm_srcid, smp.sm_zoneid, smp.sm_refcnt, 3003 &smp.sm_addr); 3004 return (WALK_NEXT); 3005 } 3006 3007 static void 3008 srcid_header(void) 3009 { 3010 mdb_printf("%-?s %3s %4s %6s %s\n", 3011 "ADDR", "ID", "ZONE", "REFCNT", "IPADDR"); 3012 mdb_printf("%<u>%80s%</u>\n", ""); 3013 } 3014 3015 /*ARGSUSED*/ 3016 static int 3017 srcid_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3018 { 3019 srcid_header(); 3020 if (flags & DCMD_ADDRSPEC) { 3021 (void) srcid_status_cb(addr, NULL, NULL); 3022 } else { 3023 if (mdb_walk("srcid", (mdb_walk_cb_t)srcid_status_cb, 3024 NULL) == -1) { 3025 mdb_warn("failed to walk srcid_map"); 3026 return (DCMD_ERR); 3027 } 3028 } 3029 return (DCMD_OK); 3030 } 3031 3032 static int 3033 ilb_stacks_walk_step(mdb_walk_state_t *wsp) 3034 { 3035 return (ns_walk_step(wsp, NS_ILB)); 3036 } 3037 3038 static int 3039 ilb_rules_walk_init(mdb_walk_state_t *wsp) 3040 { 3041 ilb_stack_t ilbs; 3042 3043 if (wsp->walk_addr == NULL) 3044 return (WALK_ERR); 3045 3046 if (mdb_vread(&ilbs, sizeof (ilbs), wsp->walk_addr) == -1) { 3047 mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr); 3048 return (WALK_ERR); 3049 } 3050 if ((wsp->walk_addr = (uintptr_t)ilbs.ilbs_rule_head) != NULL) 3051 return (WALK_NEXT); 3052 else 3053 return (WALK_DONE); 3054 } 3055 3056 static int 3057 ilb_rules_walk_step(mdb_walk_state_t *wsp) 3058 { 3059 ilb_rule_t rule; 3060 int status; 3061 3062 if (mdb_vread(&rule, sizeof (rule), wsp->walk_addr) == -1) { 3063 mdb_warn("failed to read ilb_rule_t at %p", wsp->walk_addr); 3064 return (WALK_ERR); 3065 } 3066 status = wsp->walk_callback(wsp->walk_addr, &rule, wsp->walk_cbdata); 3067 if (status != WALK_NEXT) 3068 return (status); 3069 if ((wsp->walk_addr = (uintptr_t)rule.ir_next) == NULL) 3070 return (WALK_DONE); 3071 else 3072 return (WALK_NEXT); 3073 } 3074 3075 static int 3076 ilb_servers_walk_init(mdb_walk_state_t *wsp) 3077 { 3078 ilb_rule_t rule; 3079 3080 if (wsp->walk_addr == NULL) 3081 return (WALK_ERR); 3082 3083 if (mdb_vread(&rule, sizeof (rule), wsp->walk_addr) == -1) { 3084 mdb_warn("failed to read ilb_rule_t at %p", wsp->walk_addr); 3085 return (WALK_ERR); 3086 } 3087 if ((wsp->walk_addr = (uintptr_t)rule.ir_servers) != NULL) 3088 return (WALK_NEXT); 3089 else 3090 return (WALK_DONE); 3091 } 3092 3093 static int 3094 ilb_servers_walk_step(mdb_walk_state_t *wsp) 3095 { 3096 ilb_server_t server; 3097 int status; 3098 3099 if (mdb_vread(&server, sizeof (server), wsp->walk_addr) == -1) { 3100 mdb_warn("failed to read ilb_server_t at %p", wsp->walk_addr); 3101 return (WALK_ERR); 3102 } 3103 status = wsp->walk_callback(wsp->walk_addr, &server, wsp->walk_cbdata); 3104 if (status != WALK_NEXT) 3105 return (status); 3106 if ((wsp->walk_addr = (uintptr_t)server.iser_next) == NULL) 3107 return (WALK_DONE); 3108 else 3109 return (WALK_NEXT); 3110 } 3111 3112 /* 3113 * Helper structure for ilb_nat_src walker. It stores the current index of the 3114 * nat src table. 3115 */ 3116 typedef struct { 3117 ilb_stack_t ilbs; 3118 int idx; 3119 } ilb_walk_t; 3120 3121 /* Copy from list.c */ 3122 #define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset)) 3123 3124 static int 3125 ilb_nat_src_walk_init(mdb_walk_state_t *wsp) 3126 { 3127 int i; 3128 ilb_walk_t *ns_walk; 3129 ilb_nat_src_entry_t *entry = NULL; 3130 3131 if (wsp->walk_addr == NULL) 3132 return (WALK_ERR); 3133 3134 ns_walk = mdb_alloc(sizeof (ilb_walk_t), UM_SLEEP); 3135 if (mdb_vread(&ns_walk->ilbs, sizeof (ns_walk->ilbs), 3136 wsp->walk_addr) == -1) { 3137 mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr); 3138 mdb_free(ns_walk, sizeof (ilb_walk_t)); 3139 return (WALK_ERR); 3140 } 3141 3142 if (ns_walk->ilbs.ilbs_nat_src == NULL) { 3143 mdb_free(ns_walk, sizeof (ilb_walk_t)); 3144 return (WALK_DONE); 3145 } 3146 3147 wsp->walk_data = ns_walk; 3148 for (i = 0; i < ns_walk->ilbs.ilbs_nat_src_hash_size; i++) { 3149 list_t head; 3150 char *khead; 3151 3152 /* Read in the nsh_head in the i-th element of the array. */ 3153 khead = (char *)ns_walk->ilbs.ilbs_nat_src + i * 3154 sizeof (ilb_nat_src_hash_t); 3155 if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) { 3156 mdb_warn("failed to read ilbs_nat_src at %p\n", khead); 3157 return (WALK_ERR); 3158 } 3159 3160 /* 3161 * Note that list_next points to a kernel address and we need 3162 * to compare list_next with the kernel address of the list 3163 * head. So we need to calculate the address manually. 3164 */ 3165 if ((char *)head.list_head.list_next != khead + 3166 offsetof(list_t, list_head)) { 3167 entry = list_object(&head, head.list_head.list_next); 3168 break; 3169 } 3170 } 3171 3172 if (entry == NULL) 3173 return (WALK_DONE); 3174 3175 wsp->walk_addr = (uintptr_t)entry; 3176 ns_walk->idx = i; 3177 return (WALK_NEXT); 3178 } 3179 3180 static int 3181 ilb_nat_src_walk_step(mdb_walk_state_t *wsp) 3182 { 3183 int status; 3184 ilb_nat_src_entry_t entry, *next_entry; 3185 ilb_walk_t *ns_walk; 3186 ilb_stack_t *ilbs; 3187 list_t head; 3188 char *khead; 3189 int i; 3190 3191 if (mdb_vread(&entry, sizeof (ilb_nat_src_entry_t), 3192 wsp->walk_addr) == -1) { 3193 mdb_warn("failed to read ilb_nat_src_entry_t at %p", 3194 wsp->walk_addr); 3195 return (WALK_ERR); 3196 } 3197 status = wsp->walk_callback(wsp->walk_addr, &entry, wsp->walk_cbdata); 3198 if (status != WALK_NEXT) 3199 return (status); 3200 3201 ns_walk = (ilb_walk_t *)wsp->walk_data; 3202 ilbs = &ns_walk->ilbs; 3203 i = ns_walk->idx; 3204 3205 /* Read in the nsh_head in the i-th element of the array. */ 3206 khead = (char *)ilbs->ilbs_nat_src + i * sizeof (ilb_nat_src_hash_t); 3207 if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) { 3208 mdb_warn("failed to read ilbs_nat_src at %p\n", khead); 3209 return (WALK_ERR); 3210 } 3211 3212 /* 3213 * Check if there is still entry in the current list. 3214 * 3215 * Note that list_next points to a kernel address and we need to 3216 * compare list_next with the kernel address of the list head. 3217 * So we need to calculate the address manually. 3218 */ 3219 if ((char *)entry.nse_link.list_next != khead + offsetof(list_t, 3220 list_head)) { 3221 wsp->walk_addr = (uintptr_t)list_object(&head, 3222 entry.nse_link.list_next); 3223 return (WALK_NEXT); 3224 } 3225 3226 /* Start with the next bucket in the array. */ 3227 next_entry = NULL; 3228 for (i++; i < ilbs->ilbs_nat_src_hash_size; i++) { 3229 khead = (char *)ilbs->ilbs_nat_src + i * 3230 sizeof (ilb_nat_src_hash_t); 3231 if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) { 3232 mdb_warn("failed to read ilbs_nat_src at %p\n", khead); 3233 return (WALK_ERR); 3234 } 3235 3236 if ((char *)head.list_head.list_next != khead + 3237 offsetof(list_t, list_head)) { 3238 next_entry = list_object(&head, 3239 head.list_head.list_next); 3240 break; 3241 } 3242 } 3243 3244 if (next_entry == NULL) 3245 return (WALK_DONE); 3246 3247 wsp->walk_addr = (uintptr_t)next_entry; 3248 ns_walk->idx = i; 3249 return (WALK_NEXT); 3250 } 3251 3252 static void 3253 ilb_common_walk_fini(mdb_walk_state_t *wsp) 3254 { 3255 ilb_walk_t *walk; 3256 3257 walk = (ilb_walk_t *)wsp->walk_data; 3258 if (walk == NULL) 3259 return; 3260 mdb_free(walk, sizeof (ilb_walk_t *)); 3261 } 3262 3263 static int 3264 ilb_conn_walk_init(mdb_walk_state_t *wsp) 3265 { 3266 int i; 3267 ilb_walk_t *conn_walk; 3268 ilb_conn_hash_t head; 3269 3270 if (wsp->walk_addr == NULL) 3271 return (WALK_ERR); 3272 3273 conn_walk = mdb_alloc(sizeof (ilb_walk_t), UM_SLEEP); 3274 if (mdb_vread(&conn_walk->ilbs, sizeof (conn_walk->ilbs), 3275 wsp->walk_addr) == -1) { 3276 mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr); 3277 mdb_free(conn_walk, sizeof (ilb_walk_t)); 3278 return (WALK_ERR); 3279 } 3280 3281 if (conn_walk->ilbs.ilbs_c2s_conn_hash == NULL) { 3282 mdb_free(conn_walk, sizeof (ilb_walk_t)); 3283 return (WALK_DONE); 3284 } 3285 3286 wsp->walk_data = conn_walk; 3287 for (i = 0; i < conn_walk->ilbs.ilbs_conn_hash_size; i++) { 3288 char *khead; 3289 3290 /* Read in the nsh_head in the i-th element of the array. */ 3291 khead = (char *)conn_walk->ilbs.ilbs_c2s_conn_hash + i * 3292 sizeof (ilb_conn_hash_t); 3293 if (mdb_vread(&head, sizeof (ilb_conn_hash_t), 3294 (uintptr_t)khead) == -1) { 3295 mdb_warn("failed to read ilbs_c2s_conn_hash at %p\n", 3296 khead); 3297 return (WALK_ERR); 3298 } 3299 3300 if (head.ilb_connp != NULL) 3301 break; 3302 } 3303 3304 if (head.ilb_connp == NULL) 3305 return (WALK_DONE); 3306 3307 wsp->walk_addr = (uintptr_t)head.ilb_connp; 3308 conn_walk->idx = i; 3309 return (WALK_NEXT); 3310 } 3311 3312 static int 3313 ilb_conn_walk_step(mdb_walk_state_t *wsp) 3314 { 3315 int status; 3316 ilb_conn_t conn; 3317 ilb_walk_t *conn_walk; 3318 ilb_stack_t *ilbs; 3319 ilb_conn_hash_t head; 3320 char *khead; 3321 int i; 3322 3323 if (mdb_vread(&conn, sizeof (ilb_conn_t), wsp->walk_addr) == -1) { 3324 mdb_warn("failed to read ilb_conn_t at %p", wsp->walk_addr); 3325 return (WALK_ERR); 3326 } 3327 3328 status = wsp->walk_callback(wsp->walk_addr, &conn, wsp->walk_cbdata); 3329 if (status != WALK_NEXT) 3330 return (status); 3331 3332 conn_walk = (ilb_walk_t *)wsp->walk_data; 3333 ilbs = &conn_walk->ilbs; 3334 i = conn_walk->idx; 3335 3336 /* Check if there is still entry in the current list. */ 3337 if (conn.conn_c2s_next != NULL) { 3338 wsp->walk_addr = (uintptr_t)conn.conn_c2s_next; 3339 return (WALK_NEXT); 3340 } 3341 3342 /* Start with the next bucket in the array. */ 3343 for (i++; i < ilbs->ilbs_conn_hash_size; i++) { 3344 khead = (char *)ilbs->ilbs_c2s_conn_hash + i * 3345 sizeof (ilb_conn_hash_t); 3346 if (mdb_vread(&head, sizeof (ilb_conn_hash_t), 3347 (uintptr_t)khead) == -1) { 3348 mdb_warn("failed to read ilbs_c2s_conn_hash at %p\n", 3349 khead); 3350 return (WALK_ERR); 3351 } 3352 3353 if (head.ilb_connp != NULL) 3354 break; 3355 } 3356 3357 if (head.ilb_connp == NULL) 3358 return (WALK_DONE); 3359 3360 wsp->walk_addr = (uintptr_t)head.ilb_connp; 3361 conn_walk->idx = i; 3362 return (WALK_NEXT); 3363 } 3364 3365 static int 3366 ilb_sticky_walk_init(mdb_walk_state_t *wsp) 3367 { 3368 int i; 3369 ilb_walk_t *sticky_walk; 3370 ilb_sticky_t *st = NULL; 3371 3372 if (wsp->walk_addr == NULL) 3373 return (WALK_ERR); 3374 3375 sticky_walk = mdb_alloc(sizeof (ilb_walk_t), UM_SLEEP); 3376 if (mdb_vread(&sticky_walk->ilbs, sizeof (sticky_walk->ilbs), 3377 wsp->walk_addr) == -1) { 3378 mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr); 3379 mdb_free(sticky_walk, sizeof (ilb_walk_t)); 3380 return (WALK_ERR); 3381 } 3382 3383 if (sticky_walk->ilbs.ilbs_sticky_hash == NULL) { 3384 mdb_free(sticky_walk, sizeof (ilb_walk_t)); 3385 return (WALK_DONE); 3386 } 3387 3388 wsp->walk_data = sticky_walk; 3389 for (i = 0; i < sticky_walk->ilbs.ilbs_sticky_hash_size; i++) { 3390 list_t head; 3391 char *khead; 3392 3393 /* Read in the nsh_head in the i-th element of the array. */ 3394 khead = (char *)sticky_walk->ilbs.ilbs_sticky_hash + i * 3395 sizeof (ilb_sticky_hash_t); 3396 if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) { 3397 mdb_warn("failed to read ilbs_sticky_hash at %p\n", 3398 khead); 3399 return (WALK_ERR); 3400 } 3401 3402 /* 3403 * Note that list_next points to a kernel address and we need 3404 * to compare list_next with the kernel address of the list 3405 * head. So we need to calculate the address manually. 3406 */ 3407 if ((char *)head.list_head.list_next != khead + 3408 offsetof(list_t, list_head)) { 3409 st = list_object(&head, head.list_head.list_next); 3410 break; 3411 } 3412 } 3413 3414 if (st == NULL) 3415 return (WALK_DONE); 3416 3417 wsp->walk_addr = (uintptr_t)st; 3418 sticky_walk->idx = i; 3419 return (WALK_NEXT); 3420 } 3421 3422 static int 3423 ilb_sticky_walk_step(mdb_walk_state_t *wsp) 3424 { 3425 int status; 3426 ilb_sticky_t st, *st_next; 3427 ilb_walk_t *sticky_walk; 3428 ilb_stack_t *ilbs; 3429 list_t head; 3430 char *khead; 3431 int i; 3432 3433 if (mdb_vread(&st, sizeof (ilb_sticky_t), wsp->walk_addr) == -1) { 3434 mdb_warn("failed to read ilb_sticky_t at %p", wsp->walk_addr); 3435 return (WALK_ERR); 3436 } 3437 3438 status = wsp->walk_callback(wsp->walk_addr, &st, wsp->walk_cbdata); 3439 if (status != WALK_NEXT) 3440 return (status); 3441 3442 sticky_walk = (ilb_walk_t *)wsp->walk_data; 3443 ilbs = &sticky_walk->ilbs; 3444 i = sticky_walk->idx; 3445 3446 /* Read in the nsh_head in the i-th element of the array. */ 3447 khead = (char *)ilbs->ilbs_sticky_hash + i * sizeof (ilb_sticky_hash_t); 3448 if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) { 3449 mdb_warn("failed to read ilbs_sticky_hash at %p\n", khead); 3450 return (WALK_ERR); 3451 } 3452 3453 /* 3454 * Check if there is still entry in the current list. 3455 * 3456 * Note that list_next points to a kernel address and we need to 3457 * compare list_next with the kernel address of the list head. 3458 * So we need to calculate the address manually. 3459 */ 3460 if ((char *)st.list.list_next != khead + offsetof(list_t, 3461 list_head)) { 3462 wsp->walk_addr = (uintptr_t)list_object(&head, 3463 st.list.list_next); 3464 return (WALK_NEXT); 3465 } 3466 3467 /* Start with the next bucket in the array. */ 3468 st_next = NULL; 3469 for (i++; i < ilbs->ilbs_nat_src_hash_size; i++) { 3470 khead = (char *)ilbs->ilbs_sticky_hash + i * 3471 sizeof (ilb_sticky_hash_t); 3472 if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) { 3473 mdb_warn("failed to read ilbs_sticky_hash at %p\n", 3474 khead); 3475 return (WALK_ERR); 3476 } 3477 3478 if ((char *)head.list_head.list_next != khead + 3479 offsetof(list_t, list_head)) { 3480 st_next = list_object(&head, 3481 head.list_head.list_next); 3482 break; 3483 } 3484 } 3485 3486 if (st_next == NULL) 3487 return (WALK_DONE); 3488 3489 wsp->walk_addr = (uintptr_t)st_next; 3490 sticky_walk->idx = i; 3491 return (WALK_NEXT); 3492 } 3493