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