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 /* 23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/stream.h> 28 #include <sys/mdb_modapi.h> 29 #include <sys/socket.h> 30 #include <sys/list.h> 31 #include <sys/strsun.h> 32 33 #include <mdb/mdb_stdlib.h> 34 35 #include <netinet/in.h> 36 #include <netinet/ip6.h> 37 #include <netinet/sctp.h> 38 39 #include <inet/common.h> 40 #include <inet/ip.h> 41 #include <inet/ip6.h> 42 #include <inet/ipclassifier.h> 43 44 #include <sctp/sctp_impl.h> 45 #include <sctp/sctp_addr.h> 46 47 #define MDB_SCTP_SHOW_FLAGS 0x1 48 #define MDB_SCTP_DUMP_ADDRS 0x2 49 #define MDB_SCTP_SHOW_HASH 0x4 50 #define MDB_SCTP_SHOW_OUT 0x8 51 #define MDB_SCTP_SHOW_IN 0x10 52 #define MDB_SCTP_SHOW_MISC 0x20 53 #define MDB_SCTP_SHOW_RTT 0x40 54 #define MDB_SCTP_SHOW_STATS 0x80 55 #define MDB_SCTP_SHOW_FLOW 0x100 56 #define MDB_SCTP_SHOW_HDR 0x200 57 #define MDB_SCTP_SHOW_PMTUD 0x400 58 #define MDB_SCTP_SHOW_RXT 0x800 59 #define MDB_SCTP_SHOW_CONN 0x1000 60 #define MDB_SCTP_SHOW_CLOSE 0x2000 61 #define MDB_SCTP_SHOW_EXT 0x4000 62 63 #define MDB_SCTP_SHOW_ALL 0xffffffff 64 65 /* 66 * Copy from usr/src/uts/common/os/list.c. Should we have a generic 67 * mdb list walker? 68 */ 69 #define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset)) 70 71 static int 72 ns_to_stackid(uintptr_t kaddr) 73 { 74 netstack_t nss; 75 76 if (mdb_vread(&nss, sizeof (nss), kaddr) == -1) { 77 mdb_warn("failed to read netdstack info %p", kaddr); 78 return (0); 79 } 80 return (nss.netstack_stackid); 81 } 82 83 int 84 sctp_stacks_walk_init(mdb_walk_state_t *wsp) 85 { 86 if (mdb_layered_walk("netstack", wsp) == -1) { 87 mdb_warn("can't walk 'netstack'"); 88 return (WALK_ERR); 89 } 90 return (WALK_NEXT); 91 } 92 93 int 94 sctp_stacks_walk_step(mdb_walk_state_t *wsp) 95 { 96 uintptr_t kaddr; 97 netstack_t nss; 98 99 if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) { 100 mdb_warn("can't read netstack at %p", wsp->walk_addr); 101 return (WALK_ERR); 102 } 103 kaddr = (uintptr_t)nss.netstack_modules[NS_SCTP]; 104 return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata)); 105 } 106 107 static char * 108 sctp_faddr_state(int state) 109 { 110 char *statestr; 111 112 switch (state) { 113 case SCTP_FADDRS_UNREACH: 114 statestr = "Unreachable"; 115 break; 116 case SCTP_FADDRS_DOWN: 117 statestr = "Down"; 118 break; 119 case SCTP_FADDRS_ALIVE: 120 statestr = "Alive"; 121 break; 122 case SCTP_FADDRS_UNCONFIRMED: 123 statestr = "Unconfirmed"; 124 break; 125 default: 126 statestr = "Unknown"; 127 break; 128 } 129 return (statestr); 130 } 131 132 /* ARGSUSED */ 133 static int 134 sctp_faddr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 135 { 136 sctp_faddr_t fa[1]; 137 char *statestr; 138 139 if (!(flags & DCMD_ADDRSPEC)) 140 return (DCMD_USAGE); 141 142 if (mdb_vread(fa, sizeof (*fa), addr) == -1) { 143 mdb_warn("cannot read fadder at %p", addr); 144 return (DCMD_ERR); 145 } 146 147 statestr = sctp_faddr_state(fa->state); 148 mdb_printf("%<u>%p\t%<b>%N%</b>\t%s%</u>\n", addr, &fa->faddr, 149 statestr); 150 mdb_printf("next\t\t%?p\tsaddr\t%N\n", fa->next, &fa->saddr); 151 mdb_printf("rto\t\t%?d\tsrtt\t\t%?d\n", fa->rto, fa->srtt); 152 mdb_printf("rttvar\t\t%?d\trtt_updates\t%?u\n", fa->rttvar, 153 fa->rtt_updates); 154 mdb_printf("strikes\t\t%?d\tmax_retr\t%?d\n", fa->strikes, 155 fa->max_retr); 156 mdb_printf("hb_expiry\t%?ld\thb_interval\t%?u\n", fa->hb_expiry, 157 fa->hb_interval); 158 mdb_printf("pmss\t\t%?u\tcwnd\t\t%?u\n", fa->sfa_pmss, fa->cwnd); 159 mdb_printf("ssthresh\t%?u\tsuna\t\t%?u\n", fa->ssthresh, fa->suna); 160 mdb_printf("pba\t\t%?u\tacked\t\t%?u\n", fa->pba, fa->acked); 161 mdb_printf("lastactive\t%?ld\thb_secret\t%?#lx\n", fa->lastactive, 162 fa->hb_secret); 163 mdb_printf("rxt_unacked\t%?u\n", fa->rxt_unacked); 164 mdb_printf("timer_mp\t%?p\tixa\t\t%?p\n", fa->timer_mp, fa->ixa); 165 mdb_printf("hb_enabled\t%?d\thb_pending\t%?d\n" 166 "timer_running\t%?d\tdf\t\t%?d\n" 167 "pmtu_discovered\t%?d\tisv4\t\t%?d\n" 168 "retransmissions\t%?u\n", 169 fa->hb_enabled, fa->hb_pending, fa->timer_running, fa->df, 170 fa->pmtu_discovered, fa->isv4, fa->T3expire); 171 172 return (DCMD_OK); 173 } 174 175 static void 176 print_set(sctp_set_t *sp) 177 { 178 mdb_printf("\tbegin\t%<b>%?x%</b>\t\tend\t%<b>%?x%</b>\n", 179 sp->begin, sp->end); 180 mdb_printf("\tnext\t%?p\tprev\t%?p\n", sp->next, sp->prev); 181 } 182 183 /* ARGSUSED */ 184 static int 185 sctp_set(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 186 { 187 sctp_set_t sp[1]; 188 189 if (!(flags & DCMD_ADDRSPEC)) 190 return (DCMD_USAGE); 191 192 if (mdb_vread(sp, sizeof (*sp), addr) == -1) 193 return (DCMD_ERR); 194 195 print_set(sp); 196 197 return (DCMD_OK); 198 } 199 200 static void 201 dump_sack_info(uintptr_t addr) 202 { 203 sctp_set_t sp[1]; 204 205 while (addr != 0) { 206 if (mdb_vread(sp, sizeof (*sp), addr) == -1) { 207 mdb_warn("failed to read sctp_set at %p", addr); 208 return; 209 } 210 211 addr = (uintptr_t)sp->next; 212 print_set(sp); 213 } 214 } 215 216 static int 217 dump_msghdr(mblk_t *meta) 218 { 219 sctp_msg_hdr_t smh; 220 221 if (mdb_vread(&smh, sizeof (smh), (uintptr_t)meta->b_rptr) == -1) 222 return (-1); 223 224 mdb_printf("%<u>msg_hdr_t at \t%?p\tsentto\t%?p%</u>\n", 225 meta->b_rptr, SCTP_CHUNK_DEST(meta)); 226 mdb_printf("\tttl\t%?ld\ttob\t%?ld\n", smh.smh_ttl, smh.smh_tob); 227 mdb_printf("\tsid\t%?u\tssn\t%?u\n", smh.smh_sid, smh.smh_ssn); 228 mdb_printf("\tppid\t%?u\tflags\t%?s\n", smh.smh_ppid, 229 smh.smh_flags & MSG_UNORDERED ? "unordered" : " "); 230 mdb_printf("\tcontext\t%?u\tmsglen\t%?d\n", smh.smh_context, 231 smh.smh_msglen); 232 233 return (0); 234 } 235 236 static int 237 dump_datahdr(mblk_t *mp) 238 { 239 sctp_data_hdr_t sdc; 240 uint16_t sdh_int16; 241 uint32_t sdh_int32; 242 243 if (mdb_vread(&sdc, sizeof (sdc), (uintptr_t)mp->b_rptr) == -1) 244 return (-1); 245 246 mdb_printf("%<u>data_chunk_t \t%?p\tsentto\t%?p%</u>\n", 247 mp->b_rptr, SCTP_CHUNK_DEST(mp)); 248 mdb_printf("\tsent\t%?d\t", SCTP_CHUNK_ISSENT(mp)?1:0); 249 mdb_printf("retrans\t%?d\n", SCTP_CHUNK_WANT_REXMIT(mp)?1:0); 250 mdb_printf("\tacked\t%?d\t", SCTP_CHUNK_ISACKED(mp)?1:0); 251 mdb_printf("sackcnt\t%?u\n", SCTP_CHUNK_SACKCNT(mp)); 252 253 mdb_nhconvert(&sdh_int16, &sdc.sdh_len, sizeof (sdc.sdh_len)); 254 mdb_printf("\tlen\t%?d\t", sdh_int16); 255 mdb_printf("BBIT=%d", SCTP_DATA_GET_BBIT(&sdc) == 0 ? 0 : 1); 256 mdb_printf("EBIT=%d", SCTP_DATA_GET_EBIT(&sdc) == 0 ? 0 : 1); 257 258 mdb_nhconvert(&sdh_int32, &sdc.sdh_tsn, sizeof (sdc.sdh_tsn)); 259 mdb_nhconvert(&sdh_int16, &sdc.sdh_sid, sizeof (sdc.sdh_sid)); 260 mdb_printf("\ttsn\t%?x\tsid\t%?hu\n", sdh_int32, sdh_int16); 261 262 mdb_nhconvert(&sdh_int16, &sdc.sdh_ssn, sizeof (sdc.sdh_ssn)); 263 mdb_nhconvert(&sdh_int32, &sdc.sdh_payload_id, 264 sizeof (sdc.sdh_payload_id)); 265 mdb_printf("\tssn\t%?hu\tppid\t%?d\n", sdh_int16, sdh_int32); 266 267 return (0); 268 } 269 270 static int 271 sctp_sent_list(mblk_t *addr) 272 { 273 mblk_t meta, mp; 274 275 if (!addr) 276 return (0); 277 278 if (mdb_vread(&meta, sizeof (meta), (uintptr_t)addr) == -1) 279 return (-1); 280 281 for (;;) { 282 dump_msghdr(&meta); 283 284 if (meta.b_cont == NULL) { 285 mdb_printf("No data chunks with message header!\n"); 286 return (-1); 287 } 288 if (mdb_vread(&mp, sizeof (mp), 289 (uintptr_t)meta.b_cont) == -1) { 290 return (-1); 291 } 292 for (;;) { 293 dump_datahdr(&mp); 294 if (!mp.b_next) 295 break; 296 297 if (mdb_vread(&mp, sizeof (mp), 298 (uintptr_t)(mp.b_next)) == -1) 299 return (-1); 300 } 301 if (meta.b_next == NULL) 302 break; 303 if (mdb_vread(&meta, sizeof (meta), 304 (uintptr_t)meta.b_next) == -1) 305 return (-1); 306 } 307 308 return (0); 309 } 310 311 static int 312 sctp_unsent_list(mblk_t *addr) 313 { 314 mblk_t meta; 315 316 if (!addr) 317 return (0); 318 319 if (mdb_vread(&meta, sizeof (meta), (uintptr_t)addr) == -1) 320 return (-1); 321 322 for (;;) { 323 dump_msghdr(&meta); 324 325 if (meta.b_next == NULL) 326 break; 327 328 if (mdb_vread(&meta, sizeof (meta), 329 (uintptr_t)meta.b_next) == -1) 330 return (-1); 331 } 332 333 return (0); 334 } 335 336 /* ARGSUSED */ 337 static int 338 sctp_xmit_list(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 339 { 340 sctp_t sctp; 341 342 if (!(flags & DCMD_ADDRSPEC)) 343 return (DCMD_USAGE); 344 345 if (mdb_vread(&sctp, sizeof (sctp), addr) == -1) 346 return (DCMD_ERR); 347 348 mdb_printf("%<b>Chunkified TX list%</b>\n"); 349 if (sctp_sent_list(sctp.sctp_xmit_head) < 0) 350 return (DCMD_ERR); 351 352 mdb_printf("%<b>Unchunkified TX list%</b>\n"); 353 if (sctp_unsent_list(sctp.sctp_xmit_unsent) < 0) 354 return (DCMD_ERR); 355 356 return (DCMD_OK); 357 } 358 359 /* ARGSUSED */ 360 static int 361 sctp_mdata_chunk(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 362 { 363 sctp_data_hdr_t dc; 364 mblk_t mp; 365 366 if (!(flags & DCMD_ADDRSPEC)) 367 return (DCMD_USAGE); 368 369 if (mdb_vread(&mp, sizeof (mp), addr) == -1) 370 return (DCMD_ERR); 371 372 if (mdb_vread(&dc, sizeof (dc), (uintptr_t)mp.b_rptr) == -1) 373 return (DCMD_ERR); 374 375 mdb_printf("%<b>%-?p%</b>tsn\t%?x\tsid\t%?hu\n", addr, 376 dc.sdh_tsn, dc.sdh_sid); 377 mdb_printf("%-?sssn\t%?hu\tppid\t%?x\n", "", dc.sdh_ssn, 378 dc.sdh_payload_id); 379 380 return (DCMD_OK); 381 } 382 383 /* ARGSUSED */ 384 static int 385 sctp_istr_msgs(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 386 { 387 mblk_t istrmp; 388 mblk_t dmp; 389 sctp_data_hdr_t dp; 390 uintptr_t daddr; 391 uintptr_t chaddr; 392 boolean_t bbit; 393 boolean_t ebit; 394 395 if (!(flags & DCMD_ADDRSPEC)) 396 return (DCMD_USAGE); 397 398 do { 399 if (mdb_vread(&istrmp, sizeof (istrmp), addr) == -1) 400 return (DCMD_ERR); 401 402 mdb_printf("\tistr mblk at %p: next: %?p\n" 403 "\t\tprev: %?p\tcont: %?p\n", addr, istrmp.b_next, 404 istrmp.b_prev, istrmp.b_cont); 405 daddr = (uintptr_t)&istrmp; 406 do { 407 if (mdb_vread(&dmp, sizeof (dmp), daddr) == -1) 408 break; 409 chaddr = (uintptr_t)dmp.b_rptr; 410 if (mdb_vread(&dp, sizeof (dp), chaddr) == -1) 411 break; 412 413 bbit = (SCTP_DATA_GET_BBIT(&dp) != 0); 414 ebit = (SCTP_DATA_GET_EBIT(&dp) != 0); 415 416 mdb_printf("\t\t\ttsn: %x bbit: %d ebit: %d\n", 417 dp.sdh_tsn, bbit, ebit); 418 419 420 daddr = (uintptr_t)dmp.b_cont; 421 } while (daddr != NULL); 422 423 addr = (uintptr_t)istrmp.b_next; 424 } while (addr != NULL); 425 426 return (DCMD_OK); 427 } 428 429 /* ARGSUSED */ 430 static int 431 sctp_reass_list(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 432 { 433 sctp_reass_t srp; 434 mblk_t srpmp; 435 sctp_data_hdr_t dp; 436 mblk_t dmp; 437 uintptr_t daddr; 438 uintptr_t chaddr; 439 boolean_t bbit, ebit; 440 441 if (!(flags & DCMD_ADDRSPEC)) 442 return (DCMD_USAGE); 443 444 do { 445 if (mdb_vread(&srpmp, sizeof (srpmp), addr) == -1) 446 return (DCMD_ERR); 447 448 if (mdb_vread(&srp, sizeof (srp), 449 (uintptr_t)srpmp.b_datap->db_base) == -1) 450 return (DCMD_ERR); 451 452 mdb_printf("\treassembly mblk at %p: next: %?p\n" 453 "\t\tprev: %?p\tcont: %?p\n", addr, srpmp.b_next, 454 srpmp.b_prev, srpmp.b_cont); 455 mdb_printf("\t\tssn: %hu\tneeded: %hu\tgot: %hu\ttail: %?p\n" 456 "\t\tpartial_delivered: %s\n", srp.ssn, srp.needed, 457 srp.got, srp.tail, srp.partial_delivered ? "TRUE" : 458 "FALSE"); 459 460 /* display the contents of this ssn's reassemby list */ 461 daddr = DB_TYPE(&srpmp) == M_CTL ? (uintptr_t)srpmp.b_cont : 462 (uintptr_t)&srpmp; 463 do { 464 if (mdb_vread(&dmp, sizeof (dmp), daddr) == -1) 465 break; 466 chaddr = (uintptr_t)dmp.b_rptr; 467 if (mdb_vread(&dp, sizeof (dp), chaddr) == -1) 468 break; 469 470 bbit = (SCTP_DATA_GET_BBIT(&dp) != 0); 471 ebit = (SCTP_DATA_GET_EBIT(&dp) != 0); 472 473 mdb_printf("\t\t\ttsn: %x bbit: %d ebit: %d\n", 474 dp.sdh_tsn, bbit, ebit); 475 476 daddr = (uintptr_t)dmp.b_cont; 477 } while (daddr != NULL); 478 479 addr = (uintptr_t)srpmp.b_next; 480 } while (addr != NULL); 481 482 return (DCMD_OK); 483 } 484 485 /* ARGSUSED */ 486 static int 487 sctp_uo_reass_list(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 488 { 489 sctp_data_hdr_t dp; 490 mblk_t dmp; 491 uintptr_t chaddr; 492 boolean_t bbit; 493 boolean_t ebit; 494 boolean_t ubit; 495 496 if (!(flags & DCMD_ADDRSPEC)) 497 return (DCMD_USAGE); 498 499 do { 500 if (mdb_vread(&dmp, sizeof (dmp), addr) == -1) 501 return (DCMD_ERR); 502 503 mdb_printf("\treassembly mblk at %p: next: %?p\n" 504 "\t\tprev: %?p\n", addr, dmp.b_next, dmp.b_prev); 505 506 chaddr = (uintptr_t)dmp.b_rptr; 507 if (mdb_vread(&dp, sizeof (dp), chaddr) == -1) 508 break; 509 510 bbit = (SCTP_DATA_GET_BBIT(&dp) != 0); 511 ebit = (SCTP_DATA_GET_EBIT(&dp) != 0); 512 ubit = (SCTP_DATA_GET_UBIT(&dp) != 0); 513 514 mdb_printf("\t\t\tsid: %hu ssn: %hu tsn: %x " 515 "flags: %x (U=%d B=%d E=%d)\n", dp.sdh_sid, dp.sdh_ssn, 516 dp.sdh_tsn, dp.sdh_flags, ubit, bbit, ebit); 517 518 addr = (uintptr_t)dmp.b_next; 519 } while (addr != NULL); 520 521 return (DCMD_OK); 522 } 523 524 static int 525 sctp_instr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 526 { 527 sctp_instr_t sip; 528 529 if (!(flags & DCMD_ADDRSPEC)) 530 return (DCMD_USAGE); 531 532 if (mdb_vread(&sip, sizeof (sip), addr) == -1) 533 return (DCMD_ERR); 534 535 mdb_printf("%<b>%-?p%</b>\n\tmsglist\t%?p\tnmsgs\t%?d\n" 536 "\tnextseq\t%?d\treass\t%?p\n", addr, sip.istr_msgs, 537 sip.istr_nmsgs, sip.nextseq, sip.istr_reass); 538 mdb_set_dot(addr + sizeof (sip)); 539 540 return (sctp_reass_list((uintptr_t)sip.istr_reass, flags, ac, av)); 541 } 542 543 static const char * 544 state2str(sctp_t *sctp) 545 { 546 switch (sctp->sctp_state) { 547 case SCTPS_IDLE: return ("SCTPS_IDLE"); 548 case SCTPS_BOUND: return ("SCTPS_BOUND"); 549 case SCTPS_LISTEN: return ("SCTPS_LISTEN"); 550 case SCTPS_COOKIE_WAIT: return ("SCTPS_COOKIE_WAIT"); 551 case SCTPS_COOKIE_ECHOED: return ("SCTPS_COOKIE_ECHOED"); 552 case SCTPS_ESTABLISHED: return ("SCTPS_ESTABLISHED"); 553 case SCTPS_SHUTDOWN_PENDING: return ("SCTPS_SHUTDOWN_PENDING"); 554 case SCTPS_SHUTDOWN_SENT: return ("SCTPS_SHUTDOWN_SENT"); 555 case SCTPS_SHUTDOWN_RECEIVED: return ("SCTPS_SHUTDOWN_RECEIVED"); 556 case SCTPS_SHUTDOWN_ACK_SENT: return ("SCTPS_SHUTDOWN_ACK_SENT"); 557 default: return ("UNKNOWN STATE"); 558 } 559 } 560 561 static void 562 show_sctp_flags(sctp_t *sctp) 563 { 564 mdb_printf("\tunderstands_asconf\t%d\n", 565 sctp->sctp_understands_asconf); 566 mdb_printf("\tdebug\t\t\t%d\n", sctp->sctp_connp->conn_debug); 567 mdb_printf("\tcchunk_pend\t\t%d\n", sctp->sctp_cchunk_pend); 568 mdb_printf("\tdgram_errind\t\t%d\n", 569 sctp->sctp_connp->conn_dgram_errind); 570 571 mdb_printf("\tlinger\t\t\t%d\n", sctp->sctp_connp->conn_linger); 572 if (sctp->sctp_lingering) 573 return; 574 mdb_printf("\tlingering\t\t%d\n", sctp->sctp_lingering); 575 mdb_printf("\tloopback\t\t%d\n", sctp->sctp_loopback); 576 mdb_printf("\tforce_sack\t\t%d\n", sctp->sctp_force_sack); 577 578 mdb_printf("\tack_timer_runing\t%d\n", sctp->sctp_ack_timer_running); 579 mdb_printf("\trecvdstaddr\t\t%d\n", 580 sctp->sctp_connp->conn_recv_ancillary.crb_recvdstaddr); 581 mdb_printf("\thwcksum\t\t\t%d\n", sctp->sctp_hwcksum); 582 mdb_printf("\tunderstands_addip\t%d\n", sctp->sctp_understands_addip); 583 584 mdb_printf("\tbound_to_all\t\t%d\n", sctp->sctp_bound_to_all); 585 mdb_printf("\tcansleep\t\t%d\n", sctp->sctp_cansleep); 586 mdb_printf("\tdetached\t\t%d\n", sctp->sctp_detached); 587 mdb_printf("\tsend_adaptation\t\t%d\n", sctp->sctp_send_adaptation); 588 589 mdb_printf("\trecv_adaptation\t\t%d\n", sctp->sctp_recv_adaptation); 590 mdb_printf("\tndelay\t\t\t%d\n", sctp->sctp_ndelay); 591 mdb_printf("\tcondemned\t\t%d\n", sctp->sctp_condemned); 592 mdb_printf("\tchk_fast_rexmit\t\t%d\n", sctp->sctp_chk_fast_rexmit); 593 594 mdb_printf("\tprsctp_aware\t\t%d\n", sctp->sctp_prsctp_aware); 595 mdb_printf("\tlinklocal\t\t%d\n", sctp->sctp_linklocal); 596 mdb_printf("\trexmitting\t\t%d\n", sctp->sctp_rexmitting); 597 mdb_printf("\tzero_win_probe\t\t%d\n", sctp->sctp_zero_win_probe); 598 599 mdb_printf("\trecvsndrcvinfo\t\t%d\n", sctp->sctp_recvsndrcvinfo); 600 mdb_printf("\trecvassocevnt\t\t%d\n", sctp->sctp_recvassocevnt); 601 mdb_printf("\trecvpathevnt\t\t%d\n", sctp->sctp_recvpathevnt); 602 mdb_printf("\trecvsendfailevnt\t%d\n", sctp->sctp_recvsendfailevnt); 603 604 mdb_printf("\trecvpeerevnt\t\t%d\n", sctp->sctp_recvpeererr); 605 mdb_printf("\trecvchutdownevnt\t%d\n", sctp->sctp_recvshutdownevnt); 606 mdb_printf("\trecvcpdnevnt\t\t%d\n", sctp->sctp_recvpdevnt); 607 mdb_printf("\trecvcalevnt\t\t%d\n\n", sctp->sctp_recvalevnt); 608 } 609 610 /* 611 * Given a sctp_saddr_ipif_t, print out its address. This assumes 612 * that addr contains the sctp_addr_ipif_t structure already and this 613 * function does not need to read it in. 614 */ 615 /* ARGSUSED */ 616 static int 617 print_saddr(uintptr_t ptr, const void *addr, void *cbdata) 618 { 619 sctp_saddr_ipif_t *saddr = (sctp_saddr_ipif_t *)addr; 620 sctp_ipif_t ipif; 621 char *statestr; 622 623 /* Read in the sctp_ipif object */ 624 if (mdb_vread(&ipif, sizeof (ipif), (uintptr_t)saddr->saddr_ipifp) == 625 -1) { 626 mdb_warn("cannot read ipif at %p", saddr->saddr_ipifp); 627 return (WALK_ERR); 628 } 629 630 switch (ipif.sctp_ipif_state) { 631 case SCTP_IPIFS_CONDEMNED: 632 statestr = "Condemned"; 633 break; 634 case SCTP_IPIFS_INVALID: 635 statestr = "Invalid"; 636 break; 637 case SCTP_IPIFS_DOWN: 638 statestr = "Down"; 639 break; 640 case SCTP_IPIFS_UP: 641 statestr = "Up"; 642 break; 643 default: 644 statestr = "Unknown"; 645 break; 646 } 647 mdb_printf("\t%p\t%N% (%s", saddr->saddr_ipifp, &ipif.sctp_ipif_saddr, 648 statestr); 649 if (saddr->saddr_ipif_dontsrc == 1) 650 mdb_printf("/Dontsrc"); 651 if (saddr->saddr_ipif_unconfirmed == 1) 652 mdb_printf("/Unconfirmed"); 653 if (saddr->saddr_ipif_delete_pending == 1) 654 mdb_printf("/DeletePending"); 655 mdb_printf(")\n"); 656 mdb_printf("\t\t\tid %d zoneid %d IPIF flags %x\n", 657 ipif.sctp_ipif_id, 658 ipif.sctp_ipif_zoneid, ipif.sctp_ipif_flags); 659 return (WALK_NEXT); 660 } 661 662 /* 663 * Given a sctp_faddr_t, print out its address. This assumes that 664 * addr contains the sctp_faddr_t structure already and this function 665 * does not need to read it in. 666 */ 667 static int 668 print_faddr(uintptr_t ptr, const void *addr, void *cbdata) 669 { 670 char *statestr; 671 sctp_faddr_t *faddr = (sctp_faddr_t *)addr; 672 int *i = cbdata; 673 674 statestr = sctp_faddr_state(faddr->state); 675 676 mdb_printf("\t%d:\t%N\t%?p (%s)\n", (*i)++, &faddr->faddr, ptr, 677 statestr); 678 return (WALK_NEXT); 679 } 680 681 int 682 sctp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 683 { 684 sctp_t sctps, *sctp; 685 conn_t conns, *connp; 686 int i; 687 uint_t opts = 0; 688 uint_t paddr = 0; 689 in_port_t lport, fport; 690 691 if (!(flags & DCMD_ADDRSPEC)) 692 return (DCMD_USAGE); 693 694 if (mdb_vread(&sctps, sizeof (sctps), addr) == -1) { 695 mdb_warn("failed to read sctp_t at: %p\n", addr); 696 return (DCMD_ERR); 697 } 698 sctp = &sctps; 699 700 if (mdb_vread(&conns, sizeof (conns), 701 (uintptr_t)sctp->sctp_connp) == -1) { 702 mdb_warn("failed to read conn_t at: %p\n", sctp->sctp_connp); 703 return (DCMD_ERR); 704 } 705 706 connp = &conns; 707 708 connp->conn_sctp = sctp; 709 sctp->sctp_connp = connp; 710 711 if (mdb_getopts(argc, argv, 712 'a', MDB_OPT_SETBITS, MDB_SCTP_SHOW_ALL, &opts, 713 'f', MDB_OPT_SETBITS, MDB_SCTP_SHOW_FLAGS, &opts, 714 'h', MDB_OPT_SETBITS, MDB_SCTP_SHOW_HASH, &opts, 715 'o', MDB_OPT_SETBITS, MDB_SCTP_SHOW_OUT, &opts, 716 'i', MDB_OPT_SETBITS, MDB_SCTP_SHOW_IN, &opts, 717 'm', MDB_OPT_SETBITS, MDB_SCTP_SHOW_MISC, &opts, 718 'r', MDB_OPT_SETBITS, MDB_SCTP_SHOW_RTT, &opts, 719 'S', MDB_OPT_SETBITS, MDB_SCTP_SHOW_STATS, &opts, 720 'F', MDB_OPT_SETBITS, MDB_SCTP_SHOW_FLOW, &opts, 721 'H', MDB_OPT_SETBITS, MDB_SCTP_SHOW_HDR, &opts, 722 'p', MDB_OPT_SETBITS, MDB_SCTP_SHOW_PMTUD, &opts, 723 'R', MDB_OPT_SETBITS, MDB_SCTP_SHOW_RXT, &opts, 724 'C', MDB_OPT_SETBITS, MDB_SCTP_SHOW_CONN, &opts, 725 'c', MDB_OPT_SETBITS, MDB_SCTP_SHOW_CLOSE, &opts, 726 'e', MDB_OPT_SETBITS, MDB_SCTP_SHOW_EXT, &opts, 727 'P', MDB_OPT_SETBITS, 1, &paddr, 728 'd', MDB_OPT_SETBITS, MDB_SCTP_DUMP_ADDRS, &opts) != argc) { 729 return (DCMD_USAGE); 730 } 731 732 /* non-verbose faddrs, suitable for pipelines to sctp_faddr */ 733 if (paddr != 0) { 734 sctp_faddr_t faddr, *fp; 735 for (fp = sctp->sctp_faddrs; fp != NULL; fp = faddr.next) { 736 if (mdb_vread(&faddr, sizeof (faddr), (uintptr_t)fp) 737 == -1) { 738 mdb_warn("failed to read faddr at %p", 739 fp); 740 return (DCMD_ERR); 741 } 742 mdb_printf("%p\n", fp); 743 } 744 return (DCMD_OK); 745 } 746 747 mdb_nhconvert(&lport, &connp->conn_lport, sizeof (lport)); 748 mdb_nhconvert(&fport, &connp->conn_fport, sizeof (fport)); 749 mdb_printf("%<u>%p% %22s S=%-6hu D=%-6hu% STACK=%d ZONE=%d%</u>", addr, 750 state2str(sctp), lport, fport, 751 ns_to_stackid((uintptr_t)connp->conn_netstack), connp->conn_zoneid); 752 753 if (sctp->sctp_faddrs) { 754 sctp_faddr_t faddr; 755 if (mdb_vread(&faddr, sizeof (faddr), 756 (uintptr_t)sctp->sctp_faddrs) != -1) 757 mdb_printf("%<u> %N%</u>", &faddr.faddr); 758 } 759 mdb_printf("\n"); 760 761 if (opts & MDB_SCTP_DUMP_ADDRS) { 762 mdb_printf("%<b>Local and Peer Addresses%</b>\n"); 763 764 /* Display source addresses */ 765 mdb_printf("nsaddrs\t\t%?d\n", sctp->sctp_nsaddrs); 766 (void) mdb_pwalk("sctp_walk_saddr", print_saddr, NULL, addr); 767 768 /* Display peer addresses */ 769 mdb_printf("nfaddrs\t\t%?d\n", sctp->sctp_nfaddrs); 770 i = 1; 771 (void) mdb_pwalk("sctp_walk_faddr", print_faddr, &i, addr); 772 773 mdb_printf("lastfaddr\t%?p\tprimary\t\t%?p\n", 774 sctp->sctp_lastfaddr, sctp->sctp_primary); 775 mdb_printf("current\t\t%?p\tlastdata\t%?p\n", 776 sctp->sctp_current, sctp->sctp_lastdata); 777 } 778 779 if (opts & MDB_SCTP_SHOW_OUT) { 780 mdb_printf("%<b>Outbound Data%</b>\n"); 781 mdb_printf("xmit_head\t%?p\txmit_tail\t%?p\n", 782 sctp->sctp_xmit_head, sctp->sctp_xmit_tail); 783 mdb_printf("xmit_unsent\t%?p\txmit_unsent_tail%?p\n", 784 sctp->sctp_xmit_unsent, sctp->sctp_xmit_unsent_tail); 785 mdb_printf("xmit_unacked\t%?p\n", sctp->sctp_xmit_unacked); 786 mdb_printf("unacked\t\t%?u\tunsent\t\t%?ld\n", 787 sctp->sctp_unacked, sctp->sctp_unsent); 788 mdb_printf("ltsn\t\t%?x\tlastack_rxd\t%?x\n", 789 sctp->sctp_ltsn, sctp->sctp_lastack_rxd); 790 mdb_printf("recovery_tsn\t%?x\tadv_pap\t\t%?x\n", 791 sctp->sctp_recovery_tsn, sctp->sctp_adv_pap); 792 mdb_printf("num_ostr\t%?hu\tostrcntrs\t%?p\n", 793 sctp->sctp_num_ostr, sctp->sctp_ostrcntrs); 794 mdb_printf("pad_mp\t\t%?p\terr_chunks\t%?p\n", 795 sctp->sctp_pad_mp, sctp->sctp_err_chunks); 796 mdb_printf("err_len\t\t%?u\n", sctp->sctp_err_len); 797 798 mdb_printf("%<b>Default Send Parameters%</b>\n"); 799 mdb_printf("def_stream\t%?u\tdef_flags\t%?x\n", 800 sctp->sctp_def_stream, sctp->sctp_def_flags); 801 mdb_printf("def_ppid\t%?x\tdef_context\t%?x\n", 802 sctp->sctp_def_ppid, sctp->sctp_def_context); 803 mdb_printf("def_timetolive\t%?u\n", 804 sctp->sctp_def_timetolive); 805 } 806 807 if (opts & MDB_SCTP_SHOW_IN) { 808 mdb_printf("%<b>Inbound Data%</b>\n"); 809 mdb_printf("sack_info\t%?p\tsack_gaps\t%?d\n", 810 sctp->sctp_sack_info, sctp->sctp_sack_gaps); 811 dump_sack_info((uintptr_t)sctp->sctp_sack_info); 812 mdb_printf("ftsn\t\t%?x\tlastacked\t%?x\n", 813 sctp->sctp_ftsn, sctp->sctp_lastacked); 814 mdb_printf("istr_nmsgs\t%?d\tsack_toggle\t%?d\n", 815 sctp->sctp_istr_nmsgs, sctp->sctp_sack_toggle); 816 mdb_printf("ack_mp\t\t%?p\n", sctp->sctp_ack_mp); 817 mdb_printf("num_istr\t%?hu\tinstr\t\t%?p\n", 818 sctp->sctp_num_istr, sctp->sctp_instr); 819 mdb_printf("unord_reass\t%?p\n", sctp->sctp_uo_frags); 820 } 821 822 if (opts & MDB_SCTP_SHOW_RTT) { 823 mdb_printf("%<b>RTT Tracking%</b>\n"); 824 mdb_printf("rtt_tsn\t\t%?x\tout_time\t%?ld\n", 825 sctp->sctp_rtt_tsn, sctp->sctp_out_time); 826 } 827 828 if (opts & MDB_SCTP_SHOW_FLOW) { 829 mdb_printf("%<b>Flow Control%</b>\n"); 830 mdb_printf("tconn_sndbuf\t%?d\n" 831 "conn_sndlowat\t%?d\tfrwnd\t\t%?u\n" 832 "rwnd\t\t%?u\tinitial rwnd\t%?u\n" 833 "rxqueued\t%?u\tcwnd_max\t%?u\n", connp->conn_sndbuf, 834 connp->conn_sndlowat, sctp->sctp_frwnd, 835 sctp->sctp_rwnd, sctp->sctp_irwnd, sctp->sctp_rxqueued, 836 sctp->sctp_cwnd_max); 837 } 838 839 if (opts & MDB_SCTP_SHOW_HDR) { 840 mdb_printf("%<b>Composite Headers%</b>\n"); 841 mdb_printf("iphc\t\t%?p\tiphc6\t\t%?p\n" 842 "iphc_len\t%?d\tiphc6_len\t%?d\n" 843 "hdr_len\t\t%?d\thdr6_len\t%?d\n" 844 "ipha\t\t%?p\tip6h\t\t%?p\n" 845 "ip_hdr_len\t%?d\tip_hdr6_len\t%?d\n" 846 "sctph\t\t%?p\tsctph6\t\t%?p\n" 847 "lvtag\t\t%?x\tfvtag\t\t%?x\n", sctp->sctp_iphc, 848 sctp->sctp_iphc6, sctp->sctp_iphc_len, 849 sctp->sctp_iphc6_len, sctp->sctp_hdr_len, 850 sctp->sctp_hdr6_len, sctp->sctp_ipha, sctp->sctp_ip6h, 851 sctp->sctp_ip_hdr_len, sctp->sctp_ip_hdr6_len, 852 sctp->sctp_sctph, sctp->sctp_sctph6, sctp->sctp_lvtag, 853 sctp->sctp_fvtag); 854 } 855 856 if (opts & MDB_SCTP_SHOW_PMTUD) { 857 mdb_printf("%<b>PMTUd%</b>\n"); 858 mdb_printf("last_mtu_probe\t%?ld\tmtu_probe_intvl\t%?ld\n" 859 "mss\t\t%?u\n", 860 sctp->sctp_last_mtu_probe, sctp->sctp_mtu_probe_intvl, 861 sctp->sctp_mss); 862 } 863 864 if (opts & MDB_SCTP_SHOW_RXT) { 865 mdb_printf("%<b>Retransmit Info%</b>\n"); 866 mdb_printf("cookie_mp\t%?p\tstrikes\t\t%?d\n" 867 "max_init_rxt\t%?d\tpa_max_rxt\t%?d\n" 868 "pp_max_rxt\t%?d\trto_max\t\t%?u\n" 869 "rto_min\t\t%?u\trto_initial\t%?u\n" 870 "init_rto_max\t%?u\n" 871 "rxt_nxttsn\t%?u\trxt_maxtsn\t%?u\n", sctp->sctp_cookie_mp, 872 sctp->sctp_strikes, sctp->sctp_max_init_rxt, 873 sctp->sctp_pa_max_rxt, sctp->sctp_pp_max_rxt, 874 sctp->sctp_rto_max, sctp->sctp_rto_min, 875 sctp->sctp_rto_initial, sctp->sctp_rto_max_init, 876 sctp->sctp_rxt_nxttsn, sctp->sctp_rxt_maxtsn); 877 } 878 879 if (opts & MDB_SCTP_SHOW_CONN) { 880 mdb_printf("%<b>Connection State%</b>\n"); 881 mdb_printf("last_secret_update%?ld\n", 882 sctp->sctp_last_secret_update); 883 884 mdb_printf("secret\t\t"); 885 for (i = 0; i < SCTP_SECRET_LEN; i++) { 886 if (i % 2 == 0) 887 mdb_printf("0x%02x", sctp->sctp_secret[i]); 888 else 889 mdb_printf("%02x ", sctp->sctp_secret[i]); 890 } 891 mdb_printf("\n"); 892 mdb_printf("old_secret\t"); 893 for (i = 0; i < SCTP_SECRET_LEN; i++) { 894 if (i % 2 == 0) 895 mdb_printf("0x%02x", sctp->sctp_old_secret[i]); 896 else 897 mdb_printf("%02x ", sctp->sctp_old_secret[i]); 898 } 899 mdb_printf("\n"); 900 } 901 902 if (opts & MDB_SCTP_SHOW_STATS) { 903 mdb_printf("%<b>Stats Counters%</b>\n"); 904 mdb_printf("opkts\t\t%?llu\tobchunks\t%?llu\n" 905 "odchunks\t%?llu\toudchunks\t%?llu\n" 906 "rxtchunks\t%?llu\tT1expire\t%?lu\n" 907 "T2expire\t%?lu\tT3expire\t%?lu\n" 908 "msgcount\t%?llu\tprsctpdrop\t%?llu\n" 909 "AssocStartTime\t%?lu\n", 910 sctp->sctp_opkts, sctp->sctp_obchunks, 911 sctp->sctp_odchunks, sctp->sctp_oudchunks, 912 sctp->sctp_rxtchunks, sctp->sctp_T1expire, 913 sctp->sctp_T2expire, sctp->sctp_T3expire, 914 sctp->sctp_msgcount, sctp->sctp_prsctpdrop, 915 sctp->sctp_assoc_start_time); 916 mdb_printf("ipkts\t\t%?llu\tibchunks\t%?llu\n" 917 "idchunks\t%?llu\tiudchunks\t%?llu\n" 918 "fragdmsgs\t%?llu\treassmsgs\t%?llu\n", 919 sctp->sctp_ipkts, sctp->sctp_ibchunks, 920 sctp->sctp_idchunks, sctp->sctp_iudchunks, 921 sctp->sctp_fragdmsgs, sctp->sctp_reassmsgs); 922 } 923 924 if (opts & MDB_SCTP_SHOW_HASH) { 925 mdb_printf("%<b>Hash Tables%</b>\n"); 926 mdb_printf("conn_hash_next\t%?p\t", sctp->sctp_conn_hash_next); 927 mdb_printf("conn_hash_prev\t%?p\n", sctp->sctp_conn_hash_prev); 928 929 mdb_printf("listen_hash_next%?p\t", 930 sctp->sctp_listen_hash_next); 931 mdb_printf("listen_hash_prev%?p\n", 932 sctp->sctp_listen_hash_prev); 933 mdb_nhconvert(&lport, &connp->conn_lport, sizeof (lport)); 934 mdb_printf("[ listen_hash bucket\t%?d ]\n", 935 SCTP_LISTEN_HASH(lport)); 936 937 mdb_printf("conn_tfp\t%?p\t", sctp->sctp_conn_tfp); 938 mdb_printf("listen_tfp\t%?p\n", sctp->sctp_listen_tfp); 939 940 mdb_printf("bind_hash\t%?p\tptpbhn\t\t%?p\n", 941 sctp->sctp_bind_hash, sctp->sctp_ptpbhn); 942 mdb_printf("bind_lockp\t%?p\n", 943 sctp->sctp_bind_lockp); 944 mdb_printf("[ bind_hash bucket\t%?d ]\n", 945 SCTP_BIND_HASH(lport)); 946 } 947 948 if (opts & MDB_SCTP_SHOW_CLOSE) { 949 mdb_printf("%<b>Cleanup / Close%</b>\n"); 950 mdb_printf("shutdown_faddr\t%?p\tclient_errno\t%?d\n" 951 "lingertime\t%?d\trefcnt\t\t%?hu\n", 952 sctp->sctp_shutdown_faddr, sctp->sctp_client_errno, 953 connp->conn_lingertime, sctp->sctp_refcnt); 954 } 955 956 if (opts & MDB_SCTP_SHOW_MISC) { 957 mdb_printf("%<b>Miscellaneous%</b>\n"); 958 mdb_printf("bound_if\t%?u\theartbeat_mp\t%?p\n" 959 "family\t\t%?u\tipversion\t%?hu\n" 960 "hb_interval\t%?u\tautoclose\t%?d\n" 961 "active\t\t%?ld\ttx_adaptation_code%?x\n" 962 "rx_adaptation_code%?x\ttimer_mp\t%?p\n" 963 "partial_delivery_point\t%?d\n", 964 connp->conn_bound_if, sctp->sctp_heartbeat_mp, 965 connp->conn_family, 966 connp->conn_ipversion, 967 sctp->sctp_hb_interval, sctp->sctp_autoclose, 968 sctp->sctp_active, sctp->sctp_tx_adaptation_code, 969 sctp->sctp_rx_adaptation_code, sctp->sctp_timer_mp, 970 sctp->sctp_pd_point); 971 } 972 973 if (opts & MDB_SCTP_SHOW_EXT) { 974 mdb_printf("%<b>Extensions and Reliable Ctl Chunks%</b>\n"); 975 mdb_printf("cxmit_list\t%?p\tlcsn\t\t%?x\n" 976 "fcsn\t\t%?x\n", sctp->sctp_cxmit_list, sctp->sctp_lcsn, 977 sctp->sctp_fcsn); 978 } 979 980 if (opts & MDB_SCTP_SHOW_FLAGS) { 981 mdb_printf("%<b>Flags%</b>\n"); 982 show_sctp_flags(sctp); 983 } 984 985 return (DCMD_OK); 986 } 987 988 typedef struct fanout_walk_data { 989 int index; 990 int size; 991 uintptr_t sctp; 992 sctp_tf_t *fanout; 993 uintptr_t (*getnext)(sctp_t *); 994 } fanout_walk_data_t; 995 996 typedef struct fanout_init { 997 const char *nested_walker_name; 998 size_t offset; /* for what used to be a symbol */ 999 int (*getsize)(sctp_stack_t *); 1000 uintptr_t (*getnext)(sctp_t *); 1001 } fanout_init_t; 1002 1003 static uintptr_t 1004 listen_next(sctp_t *sctp) 1005 { 1006 return ((uintptr_t)sctp->sctp_listen_hash_next); 1007 } 1008 1009 /* ARGSUSED */ 1010 static int 1011 listen_size(sctp_stack_t *sctps) 1012 { 1013 return (SCTP_LISTEN_FANOUT_SIZE); 1014 } 1015 1016 static uintptr_t 1017 conn_next(sctp_t *sctp) 1018 { 1019 return ((uintptr_t)sctp->sctp_conn_hash_next); 1020 } 1021 1022 static int 1023 conn_size(sctp_stack_t *sctps) 1024 { 1025 int size; 1026 uintptr_t kaddr; 1027 1028 kaddr = (uintptr_t)&sctps->sctps_conn_hash_size; 1029 1030 if (mdb_vread(&size, sizeof (size), kaddr) == -1) { 1031 mdb_warn("can't read 'sctps_conn_hash_size' at %p", kaddr); 1032 return (1); 1033 } 1034 return (size); 1035 } 1036 1037 static uintptr_t 1038 bind_next(sctp_t *sctp) 1039 { 1040 return ((uintptr_t)sctp->sctp_bind_hash); 1041 } 1042 1043 /* ARGSUSED */ 1044 static int 1045 bind_size(sctp_stack_t *sctps) 1046 { 1047 return (SCTP_BIND_FANOUT_SIZE); 1048 } 1049 1050 static intptr_t 1051 find_next_hash_item(fanout_walk_data_t *fw) 1052 { 1053 sctp_tf_t tf; 1054 sctp_t sctp; 1055 1056 /* first try to continue down the hash chain */ 1057 if (fw->sctp != NULL) { 1058 /* try to get next in hash chain */ 1059 if (mdb_vread(&sctp, sizeof (sctp), fw->sctp) == -1) { 1060 mdb_warn("failed to read sctp at %p", fw->sctp); 1061 return (NULL); 1062 } 1063 fw->sctp = fw->getnext(&sctp); 1064 if (fw->sctp != NULL) 1065 return (fw->sctp); 1066 else 1067 /* end of chain; go to next bucket */ 1068 fw->index++; 1069 } 1070 1071 /* find a new hash chain, traversing the buckets */ 1072 for (; fw->index < fw->size; fw->index++) { 1073 /* read the current hash line for an sctp */ 1074 if (mdb_vread(&tf, sizeof (tf), 1075 (uintptr_t)(fw->fanout + fw->index)) == -1) { 1076 mdb_warn("failed to read tf at %p", 1077 fw->fanout + fw->index); 1078 return (NULL); 1079 } 1080 if (tf.tf_sctp != NULL) { 1081 /* start of a new chain */ 1082 fw->sctp = (uintptr_t)tf.tf_sctp; 1083 return (fw->sctp); 1084 } 1085 } 1086 return (NULL); 1087 } 1088 1089 static int 1090 fanout_stack_walk_init(mdb_walk_state_t *wsp) 1091 { 1092 fanout_walk_data_t *lw; 1093 fanout_init_t *fi = wsp->walk_arg; 1094 sctp_stack_t *sctps = (sctp_stack_t *)wsp->walk_addr; 1095 uintptr_t kaddr; 1096 1097 if (mdb_vread(&kaddr, sizeof (kaddr), 1098 wsp->walk_addr + fi->offset) == -1) { 1099 mdb_warn("can't read sctp fanout at %p", 1100 wsp->walk_addr + fi->offset); 1101 return (WALK_ERR); 1102 } 1103 1104 lw = mdb_alloc(sizeof (*lw), UM_SLEEP); 1105 lw->index = 0; 1106 lw->size = fi->getsize(sctps); 1107 lw->sctp = NULL; 1108 lw->fanout = (sctp_tf_t *)kaddr; 1109 lw->getnext = fi->getnext; 1110 1111 if ((wsp->walk_addr = find_next_hash_item(lw)) == NULL) { 1112 return (WALK_DONE); 1113 } 1114 wsp->walk_data = lw; 1115 return (WALK_NEXT); 1116 } 1117 1118 static int 1119 fanout_stack_walk_step(mdb_walk_state_t *wsp) 1120 { 1121 fanout_walk_data_t *fw = wsp->walk_data; 1122 uintptr_t addr = wsp->walk_addr; 1123 sctp_t sctp; 1124 int status; 1125 1126 if (mdb_vread(&sctp, sizeof (sctp), addr) == -1) { 1127 mdb_warn("failed to read sctp at %p", addr); 1128 return (WALK_DONE); 1129 } 1130 1131 status = wsp->walk_callback(addr, &sctp, wsp->walk_cbdata); 1132 if (status != WALK_NEXT) 1133 return (status); 1134 1135 if ((wsp->walk_addr = find_next_hash_item(fw)) == NULL) 1136 return (WALK_DONE); 1137 1138 return (WALK_NEXT); 1139 } 1140 1141 static void 1142 fanout_stack_walk_fini(mdb_walk_state_t *wsp) 1143 { 1144 fanout_walk_data_t *fw = wsp->walk_data; 1145 1146 mdb_free(fw, sizeof (*fw)); 1147 } 1148 1149 int 1150 fanout_walk_init(mdb_walk_state_t *wsp) 1151 { 1152 if (mdb_layered_walk("sctp_stacks", wsp) == -1) { 1153 mdb_warn("can't walk 'sctp_stacks'"); 1154 return (WALK_ERR); 1155 } 1156 1157 return (WALK_NEXT); 1158 } 1159 1160 int 1161 fanout_walk_step(mdb_walk_state_t *wsp) 1162 { 1163 fanout_init_t *fi = wsp->walk_arg; 1164 1165 if (mdb_pwalk(fi->nested_walker_name, wsp->walk_callback, 1166 wsp->walk_cbdata, wsp->walk_addr) == -1) { 1167 mdb_warn("couldn't walk '%s'for address %p", 1168 fi->nested_walker_name, wsp->walk_addr); 1169 return (WALK_ERR); 1170 } 1171 return (WALK_NEXT); 1172 } 1173 1174 int 1175 sctps_walk_init(mdb_walk_state_t *wsp) 1176 { 1177 1178 if (mdb_layered_walk("sctp_stacks", wsp) == -1) { 1179 mdb_warn("can't walk 'sctp_stacks'"); 1180 return (WALK_ERR); 1181 } 1182 1183 return (WALK_NEXT); 1184 } 1185 1186 int 1187 sctps_walk_step(mdb_walk_state_t *wsp) 1188 { 1189 uintptr_t kaddr; 1190 1191 kaddr = wsp->walk_addr + OFFSETOF(sctp_stack_t, sctps_g_list); 1192 if (mdb_pwalk("list", wsp->walk_callback, 1193 wsp->walk_cbdata, kaddr) == -1) { 1194 mdb_warn("couldn't walk 'list' for address %p", kaddr); 1195 return (WALK_ERR); 1196 } 1197 return (WALK_NEXT); 1198 } 1199 1200 static int 1201 sctp_walk_faddr_init(mdb_walk_state_t *wsp) 1202 { 1203 sctp_t sctp; 1204 1205 if (wsp->walk_addr == NULL) 1206 return (WALK_ERR); 1207 1208 if (mdb_vread(&sctp, sizeof (sctp), wsp->walk_addr) == -1) { 1209 mdb_warn("failed to read sctp at %p", wsp->walk_addr); 1210 return (WALK_ERR); 1211 } 1212 if ((wsp->walk_addr = (uintptr_t)sctp.sctp_faddrs) != NULL) 1213 return (WALK_NEXT); 1214 else 1215 return (WALK_DONE); 1216 } 1217 1218 static int 1219 sctp_walk_faddr_step(mdb_walk_state_t *wsp) 1220 { 1221 uintptr_t faddr_ptr = wsp->walk_addr; 1222 sctp_faddr_t sctp_faddr; 1223 int status; 1224 1225 if (mdb_vread(&sctp_faddr, sizeof (sctp_faddr_t), faddr_ptr) == -1) { 1226 mdb_warn("failed to read sctp_faddr_t at %p", faddr_ptr); 1227 return (WALK_ERR); 1228 } 1229 status = wsp->walk_callback(faddr_ptr, &sctp_faddr, wsp->walk_cbdata); 1230 if (status != WALK_NEXT) 1231 return (status); 1232 if ((faddr_ptr = (uintptr_t)sctp_faddr.next) == NULL) { 1233 return (WALK_DONE); 1234 } else { 1235 wsp->walk_addr = faddr_ptr; 1236 return (WALK_NEXT); 1237 } 1238 } 1239 1240 /* 1241 * Helper structure for sctp_walk_saddr. It stores the sctp_t being walked, 1242 * the current index to the sctp_saddrs[], and the current count of the 1243 * sctp_saddr_ipif_t list. 1244 */ 1245 typedef struct { 1246 sctp_t sctp; 1247 int hash_index; 1248 int cur_cnt; 1249 } saddr_walk_t; 1250 1251 static int 1252 sctp_walk_saddr_init(mdb_walk_state_t *wsp) 1253 { 1254 sctp_t *sctp; 1255 int i; 1256 saddr_walk_t *swalker; 1257 1258 if (wsp->walk_addr == NULL) 1259 return (WALK_ERR); 1260 1261 swalker = mdb_alloc(sizeof (saddr_walk_t), UM_SLEEP); 1262 sctp = &swalker->sctp; 1263 if (mdb_vread(sctp, sizeof (sctp_t), wsp->walk_addr) == -1) { 1264 mdb_warn("failed to read sctp at %p", wsp->walk_addr); 1265 mdb_free(swalker, sizeof (saddr_walk_t)); 1266 return (WALK_ERR); 1267 } 1268 1269 /* Find the first source address. */ 1270 for (i = 0; i < SCTP_IPIF_HASH; i++) { 1271 if (sctp->sctp_saddrs[i].ipif_count > 0) { 1272 list_t *addr_list; 1273 1274 addr_list = &sctp->sctp_saddrs[i].sctp_ipif_list; 1275 wsp->walk_addr = (uintptr_t)list_object(addr_list, 1276 addr_list->list_head.list_next); 1277 1278 /* Recode the current info */ 1279 swalker->hash_index = i; 1280 swalker->cur_cnt = 1; 1281 wsp->walk_data = swalker; 1282 1283 return (WALK_NEXT); 1284 } 1285 } 1286 return (WALK_DONE); 1287 } 1288 1289 static int 1290 sctp_walk_saddr_step(mdb_walk_state_t *wsp) 1291 { 1292 uintptr_t saddr_ptr = wsp->walk_addr; 1293 sctp_saddr_ipif_t saddr; 1294 saddr_walk_t *swalker; 1295 sctp_t *sctp; 1296 int status; 1297 int i, j; 1298 1299 if (mdb_vread(&saddr, sizeof (sctp_saddr_ipif_t), saddr_ptr) == -1) { 1300 mdb_warn("failed to read sctp_saddr_ipif_t at %p", saddr_ptr); 1301 return (WALK_ERR); 1302 } 1303 status = wsp->walk_callback(saddr_ptr, &saddr, wsp->walk_cbdata); 1304 if (status != WALK_NEXT) 1305 return (status); 1306 1307 swalker = (saddr_walk_t *)wsp->walk_data; 1308 sctp = &swalker->sctp; 1309 i = swalker->hash_index; 1310 j = swalker->cur_cnt; 1311 1312 /* 1313 * If there is still a source address in the current list, return it. 1314 * Otherwise, go to the next list in the sctp_saddrs[]. 1315 */ 1316 if (j++ < sctp->sctp_saddrs[i].ipif_count) { 1317 wsp->walk_addr = (uintptr_t)saddr.saddr_ipif.list_next; 1318 swalker->cur_cnt = j; 1319 return (WALK_NEXT); 1320 } else { 1321 list_t *lst; 1322 1323 for (i = i + 1; i < SCTP_IPIF_HASH; i++) { 1324 if (sctp->sctp_saddrs[i].ipif_count > 0) { 1325 lst = &sctp->sctp_saddrs[i].sctp_ipif_list; 1326 wsp->walk_addr = (uintptr_t)list_object( 1327 lst, lst->list_head.list_next); 1328 swalker->hash_index = i; 1329 swalker->cur_cnt = 1; 1330 return (WALK_NEXT); 1331 } 1332 } 1333 } 1334 return (WALK_DONE); 1335 } 1336 1337 static void 1338 sctp_walk_saddr_fini(mdb_walk_state_t *wsp) 1339 { 1340 saddr_walk_t *swalker = (saddr_walk_t *)wsp->walk_data; 1341 1342 mdb_free(swalker, sizeof (saddr_walk_t)); 1343 } 1344 1345 1346 typedef struct ill_walk_data { 1347 sctp_ill_hash_t ills[SCTP_ILL_HASH]; 1348 uint32_t count; 1349 } ill_walk_data_t; 1350 1351 typedef struct ipuf_walk_data { 1352 sctp_ipif_hash_t ipifs[SCTP_IPIF_HASH]; 1353 uint32_t count; 1354 } ipif_walk_data_t; 1355 1356 1357 int 1358 sctp_ill_walk_init(mdb_walk_state_t *wsp) 1359 { 1360 if (mdb_layered_walk("sctp_stacks", wsp) == -1) { 1361 mdb_warn("can't walk 'sctp_stacks'"); 1362 return (WALK_ERR); 1363 } 1364 1365 return (WALK_NEXT); 1366 } 1367 1368 int 1369 sctp_ill_walk_step(mdb_walk_state_t *wsp) 1370 { 1371 if (mdb_pwalk("sctp_stack_walk_ill", wsp->walk_callback, 1372 wsp->walk_cbdata, wsp->walk_addr) == -1) { 1373 mdb_warn("couldn't walk 'sctp_stack_walk_ill' for addr %p", 1374 wsp->walk_addr); 1375 return (WALK_ERR); 1376 } 1377 return (WALK_NEXT); 1378 } 1379 1380 /* 1381 * wsp->walk_addr is the address of sctps_ill_list 1382 */ 1383 static int 1384 sctp_stack_ill_walk_init(mdb_walk_state_t *wsp) 1385 { 1386 ill_walk_data_t iw; 1387 intptr_t i; 1388 uintptr_t kaddr, uaddr; 1389 size_t offset; 1390 1391 kaddr = wsp->walk_addr + OFFSETOF(sctp_stack_t, sctps_ills_count); 1392 if (mdb_vread(&iw.count, sizeof (iw.count), kaddr) == -1) { 1393 mdb_warn("can't read sctps_ills_count at %p", kaddr); 1394 return (WALK_ERR); 1395 } 1396 kaddr = wsp->walk_addr + OFFSETOF(sctp_stack_t, sctps_g_ills); 1397 1398 if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) { 1399 mdb_warn("can't read scpts_g_ills %p", kaddr); 1400 return (WALK_ERR); 1401 } 1402 if (mdb_vread(&iw.ills, sizeof (iw.ills), kaddr) == -1) { 1403 mdb_warn("failed to read 'sctps_g_ills'"); 1404 return (NULL); 1405 } 1406 1407 /* Find the first ill. */ 1408 for (i = 0; i < SCTP_ILL_HASH; i++) { 1409 if (iw.ills[i].ill_count > 0) { 1410 uaddr = (uintptr_t)&iw.ills[i].sctp_ill_list; 1411 offset = uaddr - (uintptr_t)&iw.ills; 1412 if (mdb_pwalk("list", wsp->walk_callback, 1413 wsp->walk_cbdata, kaddr+offset) == -1) { 1414 mdb_warn("couldn't walk 'list' for address %p", 1415 kaddr); 1416 return (WALK_ERR); 1417 } 1418 } 1419 } 1420 return (WALK_DONE); 1421 } 1422 1423 static int 1424 sctp_stack_ill_walk_step(mdb_walk_state_t *wsp) 1425 { 1426 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 1427 wsp->walk_cbdata)); 1428 } 1429 1430 int 1431 sctp_ipif_walk_init(mdb_walk_state_t *wsp) 1432 { 1433 if (mdb_layered_walk("sctp_stacks", wsp) == -1) { 1434 mdb_warn("can't walk 'sctp_stacks'"); 1435 return (WALK_ERR); 1436 } 1437 return (WALK_NEXT); 1438 } 1439 1440 int 1441 sctp_ipif_walk_step(mdb_walk_state_t *wsp) 1442 { 1443 if (mdb_pwalk("sctp_stack_walk_ipif", wsp->walk_callback, 1444 wsp->walk_cbdata, wsp->walk_addr) == -1) { 1445 mdb_warn("couldn't walk 'sctp_stack_walk_ipif' for addr %p", 1446 wsp->walk_addr); 1447 return (WALK_ERR); 1448 } 1449 return (WALK_NEXT); 1450 } 1451 1452 /* 1453 * wsp->walk_addr is the address of sctps_ipif_list 1454 */ 1455 static int 1456 sctp_stack_ipif_walk_init(mdb_walk_state_t *wsp) 1457 { 1458 ipif_walk_data_t iw; 1459 intptr_t i; 1460 uintptr_t kaddr, uaddr; 1461 size_t offset; 1462 1463 kaddr = wsp->walk_addr + OFFSETOF(sctp_stack_t, sctps_g_ipifs_count); 1464 if (mdb_vread(&iw.count, sizeof (iw.count), kaddr) == -1) { 1465 mdb_warn("can't read sctps_g_ipifs_count at %p", kaddr); 1466 return (WALK_ERR); 1467 } 1468 kaddr = wsp->walk_addr + OFFSETOF(sctp_stack_t, sctps_g_ipifs); 1469 1470 if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) { 1471 mdb_warn("can't read scpts_g_ipifs %p", kaddr); 1472 return (WALK_ERR); 1473 } 1474 if (mdb_vread(&iw.ipifs, sizeof (iw.ipifs), kaddr) == -1) { 1475 mdb_warn("failed to read 'sctps_g_ipifs'"); 1476 return (NULL); 1477 } 1478 1479 /* Find the first ipif. */ 1480 for (i = 0; i < SCTP_IPIF_HASH; i++) { 1481 if (iw.ipifs[i].ipif_count > 0) { 1482 uaddr = (uintptr_t)&iw.ipifs[i].sctp_ipif_list; 1483 offset = uaddr - (uintptr_t)&iw.ipifs; 1484 if (mdb_pwalk("list", wsp->walk_callback, 1485 wsp->walk_cbdata, kaddr+offset) == -1) { 1486 mdb_warn("couldn't walk 'list' for address %p", 1487 kaddr); 1488 return (WALK_ERR); 1489 } 1490 } 1491 } 1492 return (WALK_DONE); 1493 } 1494 1495 static int 1496 sctp_stack_ipif_walk_step(mdb_walk_state_t *wsp) 1497 { 1498 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 1499 wsp->walk_cbdata)); 1500 } 1501 1502 static void 1503 sctp_help(void) 1504 { 1505 mdb_printf("Print information for a given SCTP sctp_t\n\n"); 1506 mdb_printf("Options:\n"); 1507 mdb_printf("\t-a\t All the information\n"); 1508 mdb_printf("\t-f\t Flags\n"); 1509 mdb_printf("\t-h\t Hash Tables\n"); 1510 mdb_printf("\t-o\t Outbound Data\n"); 1511 mdb_printf("\t-i\t Inbound Data\n"); 1512 mdb_printf("\t-m\t Miscellaneous Information\n"); 1513 mdb_printf("\t-r\t RTT Tracking\n"); 1514 mdb_printf("\t-S\t Stats Counters\n"); 1515 mdb_printf("\t-F\t Flow Control\n"); 1516 mdb_printf("\t-H\t Composite Headers\n"); 1517 mdb_printf("\t-p\t PMTUD\n"); 1518 mdb_printf("\t-R\t Retransmit Information\n"); 1519 mdb_printf("\t-C\t Connection State\n"); 1520 mdb_printf("\t-c\t Cleanup / Close\n"); 1521 mdb_printf("\t-e\t Extensions and Reliable Control Chunks\n"); 1522 mdb_printf("\t-d\t Local and Peer addresses\n"); 1523 mdb_printf("\t-P\t Peer addresses\n"); 1524 } 1525 static const mdb_dcmd_t dcmds[] = { 1526 { "sctp", ":[-afhoimrSFHpRCcedP]", 1527 "display sctp control structure", sctp, sctp_help }, 1528 { "sctp_set", ":", "display a SCTP set", sctp_set }, 1529 { "sctp_faddr", ":", "display a faddr", sctp_faddr }, 1530 { "sctp_istr_msgs", ":", "display msg list on an instream", 1531 sctp_istr_msgs }, 1532 { "sctp_mdata_chunk", ":", "display a data chunk in an mblk", 1533 sctp_mdata_chunk }, 1534 { "sctp_xmit_list", ":", "display sctp xmit lists", sctp_xmit_list }, 1535 { "sctp_instr", ":", "display instr", sctp_instr }, 1536 { "sctp_reass_list", ":", "display reass list", sctp_reass_list }, 1537 { "sctp_uo_reass_list", ":", "display un-ordered reass list", 1538 sctp_uo_reass_list }, 1539 { NULL } 1540 }; 1541 1542 static const fanout_init_t listen_fanout_init = { 1543 "sctp_stack_listen_fanout", OFFSETOF(sctp_stack_t, sctps_listen_fanout), 1544 listen_size, listen_next 1545 }; 1546 1547 static const fanout_init_t conn_fanout_init = { 1548 "sctp_stack_conn_fanout", OFFSETOF(sctp_stack_t, sctps_conn_fanout), 1549 conn_size, conn_next 1550 }; 1551 1552 static const fanout_init_t bind_fanout_init = { 1553 "sctp_stack_bind_fanout", OFFSETOF(sctp_stack_t, sctps_bind_fanout), 1554 bind_size, bind_next 1555 }; 1556 1557 static const mdb_walker_t walkers[] = { 1558 { "sctps", "walk the full chain of sctps for all stacks", 1559 sctps_walk_init, sctps_walk_step, NULL }, 1560 { "sctp_listen_fanout", "walk the sctp listen fanout for all stacks", 1561 fanout_walk_init, fanout_walk_step, NULL, 1562 (void *)&listen_fanout_init }, 1563 { "sctp_conn_fanout", "walk the sctp conn fanout for all stacks", 1564 fanout_walk_init, fanout_walk_step, NULL, 1565 (void *)&conn_fanout_init }, 1566 { "sctp_bind_fanout", "walk the sctp bind fanout for all stacks", 1567 fanout_walk_init, fanout_walk_step, NULL, 1568 (void *)&bind_fanout_init }, 1569 { "sctp_stack_listen_fanout", 1570 "walk the sctp listen fanout for one stack", 1571 fanout_stack_walk_init, fanout_stack_walk_step, 1572 fanout_stack_walk_fini, 1573 (void *)&listen_fanout_init }, 1574 { "sctp_stack_conn_fanout", "walk the sctp conn fanout for one stack", 1575 fanout_stack_walk_init, fanout_stack_walk_step, 1576 fanout_stack_walk_fini, 1577 (void *)&conn_fanout_init }, 1578 { "sctp_stack_bind_fanout", "walk the sctp bind fanoutfor one stack", 1579 fanout_stack_walk_init, fanout_stack_walk_step, 1580 fanout_stack_walk_fini, 1581 (void *)&bind_fanout_init }, 1582 { "sctp_walk_faddr", "walk the peer address list of a given sctp_t", 1583 sctp_walk_faddr_init, sctp_walk_faddr_step, NULL }, 1584 { "sctp_walk_saddr", "walk the local address list of a given sctp_t", 1585 sctp_walk_saddr_init, sctp_walk_saddr_step, sctp_walk_saddr_fini }, 1586 { "sctp_walk_ill", "walk the sctp_g_ills list for all stacks", 1587 sctp_ill_walk_init, sctp_ill_walk_step, NULL }, 1588 { "sctp_walk_ipif", "walk the sctp_g_ipif list for all stacks", 1589 sctp_ipif_walk_init, sctp_ipif_walk_step, NULL }, 1590 { "sctp_stack_walk_ill", "walk the sctp_g_ills list for one stack", 1591 sctp_stack_ill_walk_init, sctp_stack_ill_walk_step, NULL }, 1592 { "sctp_stack_walk_ipif", "walk the sctp_g_ipif list for one stack", 1593 sctp_stack_ipif_walk_init, sctp_stack_ipif_walk_step, NULL }, 1594 { "sctp_stacks", "walk all the sctp_stack_t", 1595 sctp_stacks_walk_init, sctp_stacks_walk_step, NULL }, 1596 { NULL } 1597 }; 1598 1599 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 1600 1601 const mdb_modinfo_t * 1602 _mdb_init(void) 1603 { 1604 return (&modinfo); 1605 } 1606