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