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/mdb_modapi.h> 27 #include <sys/cpuvar.h> 28 #include <sys/conf.h> 29 #include <sys/file.h> 30 #include <sys/types.h> 31 #include <sys/taskq.h> 32 #include <sys/sysmacros.h> 33 #include <sys/socket.h> /* networking stuff */ 34 #include <sys/strsubr.h> /* networking stuff */ 35 #include <sys/nvpair.h> 36 #include <sys/sunldi.h> 37 #include <sys/stmf.h> 38 #include <sys/stmf_ioctl.h> 39 #include <sys/portif.h> 40 41 #define IDM_CONN_SM_STRINGS 42 #define IDM_TASK_SM_STRINGS 43 #define ISCSIT_TGT_SM_STRINGS 44 #define ISCSIT_SESS_SM_STRINGS 45 #define ISCSIT_LOGIN_SM_STRINGS 46 #define ISCSI_SESS_SM_STRINGS 47 #define ISCSI_CMD_SM_STRINGS 48 #define ISCSI_ICS_NAMES 49 #define ISCSI_LOGIN_STATE_NAMES 50 #include <sys/idm/idm.h> 51 #include <iscsit.h> 52 #include <iscsit_isns.h> 53 #include <iscsi.h> 54 55 /* 56 * We want to be able to print multiple levels of object hierarchy with a 57 * single dcmd information, and preferably also exclude intermediate 58 * levels if desired. For example some of the target objects have the 59 * following relationship: 60 * 61 * target --> session --> connection --> task 62 * 63 * The session dcmd should allow the printing of all associated tasks for the 64 * sessions without printing all the associated connections. To accomplish 65 * this the following structure contains a bit for each object type. Dcmds 66 * should invoked the functions for child objects if any bits are set 67 * in iscsi_dcmd_ctrl_t but the functions for the child object should only 68 * print data if their associated bit is set. 69 * 70 * Each dcmd should provide an external interface with the standard MDB API 71 * and an internal interface that accepts iscsi_dcmd_ctrl_t. To display 72 * child objects the dcmd calls the internal interface for the child object 73 * directly. Dcmds invoked from the command line will, of course, call the 74 * external interface. See iscsi_conn() and iscsi_conn_impl(). 75 */ 76 77 typedef struct { 78 union { 79 uint32_t idc_children; 80 struct { 81 uint32_t idc_tgt:1, 82 idc_tpgt:1, 83 idc_portal:1, 84 idc_sess:1, 85 idc_conn:1, 86 idc_print_ip:1, 87 idc_task:1, 88 idc_buffer:1, 89 idc_states:1, 90 idc_rc_audit:1, 91 idc_lun:1, 92 idc_hba:1; 93 } child; 94 } u; 95 boolean_t idc_ini; 96 boolean_t idc_tgt; 97 boolean_t idc_verbose; 98 boolean_t idc_header; 99 /* 100 * Our connection dcmd code works off the global connection lists 101 * in IDM since we want to know about connections even when they 102 * have not progressed to the point that they have an associated 103 * session. If we use "::iscsi_sess [-c]" then we only want to 104 * see connections associated with particular session. To avoid 105 * writing a separate set of code to print session-specific connection 106 * the session code should set the sessions kernel address in the 107 * following field. The connection code will then only print 108 * connections that match. 109 */ 110 uintptr_t idc_assoc_session; 111 } iscsi_dcmd_ctrl_t; 112 113 static int iscsi_walk_all_sess(iscsi_dcmd_ctrl_t *idc); 114 static int iscsi_walk_ini_sessions(uintptr_t array_addr); 115 static int iscsi_walk_all_conn(iscsi_dcmd_ctrl_t *idc); 116 static int iscsi_tgt_walk_cb(uintptr_t addr, const void *list_walker_data, 117 void *idc_void); 118 static int iscsi_tpgt_walk_cb(uintptr_t addr, const void *list_walker_data, 119 void *idc_void); 120 static int iscsi_tpg_walk_cb(uintptr_t addr, const void *list_walker_data, 121 void *idc_void); 122 static int iscsi_portal_walk_cb(uintptr_t addr, const void *list_walker_data, 123 void *idc_void); 124 static int iscsi_sess_walk_cb(uintptr_t addr, const void *list_walker_data, 125 void *idc_void); 126 static int iscsi_conn_walk_cb(uintptr_t addr, const void *list_walker_data, 127 void *idc_void); 128 static int iscsi_buffer_walk_cb(uintptr_t addr, const void *list_walker_data, 129 void *idc_void); 130 static int iscsi_tgt_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc); 131 static int iscsi_tpgt_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc); 132 static int iscsi_tpg_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc); 133 static int iscsi_portal_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc); 134 static int iscsi_sess_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc); 135 static int iscsi_conn_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc); 136 static void iscsi_print_iscsit_conn_data(idm_conn_t *ict); 137 static void iscsi_print_idm_conn_data(idm_conn_t *ict); 138 static int iscsi_task_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc); 139 static void iscsi_print_iscsit_task_data(idm_task_t *idt); 140 static int iscsi_buffer_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc); 141 static idm_conn_type_t idm_conn_type(uintptr_t addr); 142 static int iscsi_i_task_impl(idm_task_t *idt, uintptr_t addr, 143 iscsi_dcmd_ctrl_t *idc); 144 static int iscsi_refcnt_impl(uintptr_t addr); 145 static int iscsi_sm_audit_impl(uintptr_t addr); 146 static int iscsi_isns(uintptr_t addr, uint_t flags, int argc, 147 const mdb_arg_t *argv); 148 149 static const char *iscsi_idm_conn_event(unsigned int event); 150 static const char *iscsi_iscsit_tgt_event(unsigned int event); 151 static const char *iscsi_iscsit_sess_event(unsigned int event); 152 static const char *iscsi_iscsit_login_event(unsigned int event); 153 static const char *iscsi_iscsi_cmd_event(unsigned int event); 154 static const char *iscsi_iscsi_sess_event(unsigned int event); 155 static const char *iscsi_idm_conn_state(unsigned int state); 156 static const char *iscsi_idm_task_state(unsigned int state); 157 static const char *iscsi_iscsit_tgt_state(unsigned int state); 158 static const char *iscsi_iscsit_sess_state(unsigned int state); 159 static const char *iscsi_iscsit_login_state(unsigned int state); 160 static const char *iscsi_iscsi_cmd_state(unsigned int state); 161 static const char *iscsi_iscsi_sess_state(unsigned int state); 162 static const char *iscsi_iscsi_conn_state(unsigned int state); 163 static const char *iscsi_iscsi_login_state(unsigned int state); 164 165 static void iscsi_format_timestamp(char *ts_str, int strlen, 166 timespec_t *ts); 167 static char *iscsi_inet_ntop(int af, const void *addr, char *buf, int addrlen); 168 static void convert2ascii(char *, const in6_addr_t *); 169 static int sa_to_str(struct sockaddr_storage *sa, char *addr); 170 static int iscsi_isns_portal_cb(uintptr_t addr, const void *walker_data, 171 void *data); 172 173 #define PORTAL_STR_LEN (INET6_ADDRSTRLEN + 7) 174 175 /* 176 * ::iscsi_tgt [-scatgpbSRv] 177 * 178 * iscsi_tgt - Print out information associated with an iscsit target instance 179 * 180 * s Print associated session information 181 * c Print associated connection information 182 * a Print IP addresses with connection information 183 * t Print associated task information 184 * g Print associated TPG information 185 * p Print portals with TPG information 186 * b Print associated buffer information 187 * S Print recent state events and transitions 188 * R Print reference count audit data 189 * v Verbose output about the connection 190 */ 191 /*ARGSUSED*/ 192 static int 193 iscsi_tgt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 194 { 195 iscsi_dcmd_ctrl_t idc; 196 int buffer = 0, task = 0, print_ip = 0; 197 int tpgt = 0, conn = 0, sess = 0, portal = 0; 198 int states = 0, rc_audit = 0; 199 uintptr_t iscsit_global_addr, avl_addr, list_addr; 200 GElf_Sym sym; 201 202 bzero(&idc, sizeof (idc)); 203 if (mdb_getopts(argc, argv, 204 'a', MDB_OPT_SETBITS, TRUE, &print_ip, 205 'g', MDB_OPT_SETBITS, TRUE, &tpgt, 206 's', MDB_OPT_SETBITS, TRUE, &sess, 207 'c', MDB_OPT_SETBITS, TRUE, &conn, 208 't', MDB_OPT_SETBITS, TRUE, &task, 209 'b', MDB_OPT_SETBITS, TRUE, &buffer, 210 'p', MDB_OPT_SETBITS, TRUE, &portal, 211 'S', MDB_OPT_SETBITS, TRUE, &states, 212 'R', MDB_OPT_SETBITS, TRUE, &rc_audit, 213 'v', MDB_OPT_SETBITS, TRUE, &idc.idc_verbose, 214 NULL) != argc) 215 return (DCMD_USAGE); 216 217 idc.u.child.idc_tgt = 1; 218 idc.u.child.idc_print_ip = print_ip; 219 idc.u.child.idc_tpgt = tpgt; 220 idc.u.child.idc_portal = portal; 221 idc.u.child.idc_sess = sess; 222 idc.u.child.idc_conn = conn; 223 idc.u.child.idc_task = task; 224 idc.u.child.idc_buffer = buffer; 225 idc.u.child.idc_states = states; 226 idc.u.child.idc_rc_audit = rc_audit; 227 228 if (DCMD_HDRSPEC(flags)) 229 idc.idc_header = 1; 230 231 /* 232 * If no address was specified on the command line, we 233 * print out all tgtions 234 */ 235 if (!(flags & DCMD_ADDRSPEC)) { 236 if (mdb_lookup_by_name("iscsit_global", &sym) == -1) { 237 mdb_warn("failed to find symbol 'iscsit_global'"); 238 return (DCMD_ERR); 239 } 240 iscsit_global_addr = (uintptr_t)sym.st_value; 241 avl_addr = iscsit_global_addr + 242 offsetof(iscsit_global_t, global_target_list); 243 if (mdb_pwalk("avl", iscsi_tgt_walk_cb, &idc, avl_addr) == -1) { 244 mdb_warn("avl walk failed for global target tree"); 245 return (DCMD_ERR); 246 } 247 list_addr = iscsit_global_addr + 248 offsetof(iscsit_global_t, global_deleted_target_list); 249 if (mdb_pwalk("list", iscsi_tgt_walk_cb, 250 &idc, list_addr) == -1) { 251 mdb_warn("list walk failed for deleted target list"); 252 return (DCMD_ERR); 253 } 254 return (DCMD_OK); 255 } else { 256 return (iscsi_tgt_impl(addr, &idc)); 257 } 258 /*NOTREACHED*/ 259 } 260 261 static int 262 iscsi_tpg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 263 { 264 iscsi_dcmd_ctrl_t idc; 265 uintptr_t iscsit_global_addr, avl_addr; 266 GElf_Sym sym; 267 268 bzero(&idc, sizeof (idc)); 269 if (mdb_getopts(argc, argv, 270 'v', MDB_OPT_SETBITS, TRUE, &idc.idc_verbose, 271 NULL) != argc) 272 return (DCMD_USAGE); 273 274 idc.u.child.idc_portal = 1; /* Always print portals */ 275 if (DCMD_HDRSPEC(flags)) 276 idc.idc_header = 1; 277 278 /* 279 * If no address was specified on the command line, we 280 * print out all tgtions 281 */ 282 if (!(flags & DCMD_ADDRSPEC)) { 283 if (mdb_lookup_by_name("iscsit_global", &sym) == -1) { 284 mdb_warn("failed to find symbol 'iscsit_global'"); 285 return (DCMD_ERR); 286 } 287 iscsit_global_addr = (uintptr_t)sym.st_value; 288 avl_addr = iscsit_global_addr + 289 offsetof(iscsit_global_t, global_tpg_list); 290 if (mdb_pwalk("avl", iscsi_tpg_walk_cb, &idc, avl_addr) == -1) { 291 mdb_warn("avl walk failed for global target tree"); 292 return (DCMD_ERR); 293 } 294 return (DCMD_OK); 295 } else { 296 return (iscsi_tpg_impl(addr, &idc)); 297 } 298 /*NOTREACHED*/ 299 } 300 301 /* 302 * ::iscsi_sess [-bctvIT] 303 * 304 * iscsi_sess - Print out information associated with an iSCSI session 305 * 306 * I Print only initiator sessions 307 * T Print only target sessions 308 * c Print associated connection information 309 * a Print IP addresses with connection information 310 * t Print associated task information 311 * b Print associated buffer information 312 * S Print recent state events and transitions 313 * R Print reference count audit data 314 * v Verbose output about the connection 315 */ 316 /*ARGSUSED*/ 317 static int 318 iscsi_sess(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 319 { 320 iscsi_dcmd_ctrl_t idc; 321 int buffer = 0, task = 0, conn = 0, print_ip = 0; 322 int states = 0, rc_audit = 0; 323 324 bzero(&idc, sizeof (idc)); 325 if (mdb_getopts(argc, argv, 326 'I', MDB_OPT_SETBITS, TRUE, &idc.idc_ini, 327 'T', MDB_OPT_SETBITS, TRUE, &idc.idc_tgt, 328 'a', MDB_OPT_SETBITS, TRUE, &print_ip, 329 'c', MDB_OPT_SETBITS, TRUE, &conn, 330 't', MDB_OPT_SETBITS, TRUE, &task, 331 'b', MDB_OPT_SETBITS, TRUE, &buffer, 332 'S', MDB_OPT_SETBITS, TRUE, &states, 333 'R', MDB_OPT_SETBITS, TRUE, &rc_audit, 334 'v', MDB_OPT_SETBITS, TRUE, &idc.idc_verbose, 335 NULL) != argc) 336 return (DCMD_USAGE); 337 338 idc.u.child.idc_sess = 1; 339 idc.u.child.idc_print_ip = print_ip; 340 idc.u.child.idc_conn = conn; 341 idc.u.child.idc_task = task; 342 idc.u.child.idc_buffer = buffer; 343 idc.u.child.idc_states = states; 344 idc.u.child.idc_rc_audit = rc_audit; 345 if (DCMD_HDRSPEC(flags)) 346 idc.idc_header = 1; 347 348 /* 349 * If no address was specified on the command line, we 350 * print out all sessions 351 */ 352 if (!(flags & DCMD_ADDRSPEC)) { 353 return (iscsi_walk_all_sess(&idc)); 354 } else { 355 return (iscsi_sess_impl(addr, &idc)); 356 } 357 /*NOTREACHED*/ 358 } 359 360 361 362 /* 363 * ::iscsi_conn [-btvIT] 364 * 365 * iscsi_conn - Print out information associated with an iSCSI connection 366 * 367 * I Print only initiator connections 368 * T Print only target connections 369 * a Print IP addresses with connection information 370 * t Print associated task information 371 * b Print associated buffer information 372 * S Print recent state events and transitions 373 * R Print reference count audit data 374 * v Verbose output about the connection 375 */ 376 /*ARGSUSED*/ 377 static int 378 iscsi_conn(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 379 { 380 iscsi_dcmd_ctrl_t idc; 381 int buffer = 0, task = 0, print_ip = 0; 382 int states = 0, rc_audit = 0; 383 384 bzero(&idc, sizeof (idc)); 385 if (mdb_getopts(argc, argv, 386 'I', MDB_OPT_SETBITS, TRUE, &idc.idc_ini, 387 'T', MDB_OPT_SETBITS, TRUE, &idc.idc_tgt, 388 'a', MDB_OPT_SETBITS, TRUE, &print_ip, 389 't', MDB_OPT_SETBITS, TRUE, &task, 390 'b', MDB_OPT_SETBITS, TRUE, &buffer, 391 'S', MDB_OPT_SETBITS, TRUE, &states, 392 'R', MDB_OPT_SETBITS, TRUE, &rc_audit, 393 'v', MDB_OPT_SETBITS, TRUE, &idc.idc_verbose, 394 NULL) != argc) 395 return (DCMD_USAGE); 396 397 idc.u.child.idc_conn = 1; 398 idc.u.child.idc_print_ip = print_ip; 399 idc.u.child.idc_task = task; 400 idc.u.child.idc_buffer = buffer; 401 idc.u.child.idc_states = states; 402 idc.u.child.idc_rc_audit = rc_audit; 403 if (DCMD_HDRSPEC(flags)) 404 idc.idc_header = 1; 405 406 /* 407 * If no address was specified on the command line, we 408 * print out all connections 409 */ 410 if (!(flags & DCMD_ADDRSPEC)) { 411 return (iscsi_walk_all_conn(&idc)); 412 } else { 413 return (iscsi_conn_impl(addr, &idc)); 414 } 415 /*NOTREACHED*/ 416 } 417 418 /* 419 * ::iscsi_task [-bv] 420 * 421 * iscsi_task - Print out information associated with an iSCSI task 422 * 423 * b Print associated buffer information 424 * S Print recent state events and transitions 425 * R Print reference count audit data 426 * v Verbose output about the connection 427 */ 428 /*ARGSUSED*/ 429 static int 430 iscsi_task(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 431 { 432 iscsi_dcmd_ctrl_t idc; 433 int buffer = 0; 434 int states = 0, rc_audit = 0; 435 436 bzero(&idc, sizeof (idc)); 437 if (mdb_getopts(argc, argv, 438 'b', MDB_OPT_SETBITS, TRUE, &buffer, 439 'S', MDB_OPT_SETBITS, TRUE, &states, 440 'R', MDB_OPT_SETBITS, TRUE, &rc_audit, 441 'v', MDB_OPT_SETBITS, TRUE, &idc.idc_verbose, 442 NULL) != argc) 443 return (DCMD_USAGE); 444 445 idc.u.child.idc_conn = 0; 446 idc.u.child.idc_task = 1; 447 idc.u.child.idc_buffer = buffer; 448 idc.u.child.idc_states = states; 449 idc.u.child.idc_rc_audit = rc_audit; 450 if (DCMD_HDRSPEC(flags)) 451 idc.idc_header = 1; 452 453 /* 454 * If no address was specified on the command line, we 455 * print out all connections 456 */ 457 if (!(flags & DCMD_ADDRSPEC)) { 458 return (iscsi_walk_all_conn(&idc)); 459 } else { 460 return (iscsi_task_impl(addr, &idc)); 461 } 462 /*NOTREACHED*/ 463 } 464 465 /* 466 * ::iscsi_refcnt 467 * 468 * iscsi_refcnt - Dump an idm_refcnt_t structure 469 * 470 */ 471 /*ARGSUSED*/ 472 static int 473 iscsi_refcnt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 474 { 475 if (!(flags & DCMD_ADDRSPEC)) { 476 return (DCMD_ERR); 477 } else { 478 return (iscsi_refcnt_impl(addr)); 479 } 480 /*NOTREACHED*/ 481 } 482 483 /* 484 * ::iscsi_states 485 * 486 * iscsi_states - Dump events and state transitions recoreded in an 487 * idm_sm_audit_t structure 488 * 489 */ 490 /*ARGSUSED*/ 491 static int 492 iscsi_states(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 493 { 494 if (!(flags & DCMD_ADDRSPEC)) { 495 return (DCMD_ERR); 496 } else { 497 return (iscsi_sm_audit_impl(addr)); 498 } 499 /*NOTREACHED*/ 500 } 501 502 /* 503 * Helper function to list all the initiator sessions 504 */ 505 static int 506 iscsi_walk_ini_sessions(uintptr_t array_vaddr) 507 { 508 iscsi_hba_t ihp; 509 int i; 510 int array_size; 511 struct i_ddi_soft_state *ss; 512 iscsi_sess_t *isp; 513 514 ss = (struct i_ddi_soft_state *)mdb_alloc(sizeof (*ss), 515 UM_SLEEP|UM_GC); 516 if (mdb_vread(ss, sizeof (*ss), array_vaddr) != sizeof (*ss)) { 517 mdb_warn("Cannot read softstate struct (Invalid pointer?).\n"); 518 return (DCMD_ERR); 519 } 520 array_size = ss->n_items * (sizeof (void *)); 521 array_vaddr = (uintptr_t)ss->array; 522 ss->array = mdb_alloc(array_size, UM_SLEEP|UM_GC); 523 if (mdb_vread(ss->array, array_size, array_vaddr) != array_size) { 524 mdb_warn("Corrupted softstate struct.\n"); 525 return (DCMD_ERR); 526 } 527 for (i = 0; i < ss->n_items; i++) { 528 if (ss->array[i] == 0) 529 continue; 530 531 if (mdb_vread(&ihp, sizeof (ihp), (uintptr_t)ss->array[i]) 532 != sizeof (ihp)) { 533 mdb_warn("Corrupted softstate struct.\n"); 534 return (DCMD_ERR); 535 } 536 mdb_printf("iscsi_hba %p sessions: \n", ihp); 537 mdb_printf("%<u>%-19s %-4s %-8s%</u>\n", 538 "Session", "Type", "State"); 539 for (isp = ihp.hba_sess_list; isp; ) { 540 iscsi_sess_t sess; 541 if ((mdb_vread(&sess, sizeof (iscsi_sess_t), 542 (uintptr_t)isp)) != sizeof (iscsi_sess_t)) { 543 mdb_warn("Failed to read session\n"); 544 return (DCMD_ERR); 545 } 546 mdb_printf("%-19p %-4d %-8d\n", isp, 547 sess.sess_type, 548 sess.sess_state); 549 isp = sess.sess_next; 550 } 551 } 552 return (DCMD_OK); 553 } 554 555 static int 556 iscsi_walk_all_sess(iscsi_dcmd_ctrl_t *idc) 557 { 558 uintptr_t iscsit_global_addr; 559 uintptr_t avl_addr; 560 uintptr_t list_addr; 561 GElf_Sym sym; 562 uintptr_t adr; 563 /* Initiator sessions */ 564 if (idc->idc_ini) { 565 if (mdb_readvar(&adr, "iscsi_state") == -1) { 566 567 mdb_warn("state variable iscsi_state not found.\n"); 568 mdb_warn("Is the driver loaded ?\n"); 569 return (DCMD_ERR); 570 } 571 return (iscsi_walk_ini_sessions(adr)); 572 } 573 /* Target sessions */ 574 /* Walk discovery sessions */ 575 if (mdb_lookup_by_name("iscsit_global", &sym) == -1) { 576 mdb_warn("failed to find symbol 'iscsit_global'"); 577 return (DCMD_ERR); 578 } 579 iscsit_global_addr = (uintptr_t)sym.st_value; 580 avl_addr = iscsit_global_addr + 581 offsetof(iscsit_global_t, global_discovery_sessions); 582 if (mdb_pwalk("avl", iscsi_sess_walk_cb, idc, avl_addr) == -1) { 583 mdb_warn("avl walk failed for discovery sessions"); 584 return (DCMD_ERR); 585 } 586 587 /* Walk targets printing all session info */ 588 avl_addr = iscsit_global_addr + 589 offsetof(iscsit_global_t, global_target_list); 590 if (mdb_pwalk("avl", iscsi_tgt_walk_cb, idc, avl_addr) == -1) { 591 mdb_warn("avl walk failed for target/session tree"); 592 return (DCMD_ERR); 593 } 594 595 /* Walk deleting targets printing all session info */ 596 list_addr = iscsit_global_addr + 597 offsetof(iscsit_global_t, global_deleted_target_list); 598 if (mdb_pwalk("list", iscsi_tgt_walk_cb, idc, list_addr) == -1) { 599 mdb_warn("list walk failed for deleted target list"); 600 return (DCMD_ERR); 601 } 602 603 return (DCMD_OK); 604 } 605 606 static int 607 iscsi_walk_all_conn(iscsi_dcmd_ctrl_t *idc) 608 { 609 uintptr_t idm_global_addr; 610 uintptr_t list_addr; 611 GElf_Sym sym; 612 613 /* Walk initiator connections */ 614 if (mdb_lookup_by_name("idm", &sym) == -1) { 615 mdb_warn("failed to find symbol 'idm'"); 616 return (DCMD_ERR); 617 } 618 idm_global_addr = (uintptr_t)sym.st_value; 619 /* Walk connection list associated with the initiator */ 620 list_addr = idm_global_addr + offsetof(idm_global_t, idm_ini_conn_list); 621 if (mdb_pwalk("list", iscsi_conn_walk_cb, idc, list_addr) == -1) { 622 mdb_warn("list walk failed for initiator connections"); 623 return (DCMD_ERR); 624 } 625 626 /* Walk connection list associated with the target */ 627 list_addr = idm_global_addr + offsetof(idm_global_t, idm_tgt_conn_list); 628 if (mdb_pwalk("list", iscsi_conn_walk_cb, idc, list_addr) == -1) { 629 mdb_warn("list walk failed for target service instances"); 630 return (DCMD_ERR); 631 } 632 633 return (DCMD_OK); 634 } 635 636 /*ARGSUSED*/ 637 static int 638 iscsi_tpg_walk_cb(uintptr_t addr, const void *list_walker_data, 639 void *idc_void) 640 { 641 /* We don't particularly care about the list walker data */ 642 iscsi_dcmd_ctrl_t *idc = idc_void; 643 int rc; 644 645 rc = iscsi_tpg_impl(addr, idc); 646 647 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR); 648 } 649 650 /*ARGSUSED*/ 651 static int 652 iscsi_tgt_walk_cb(uintptr_t addr, const void *list_walker_data, 653 void *idc_void) 654 { 655 /* We don't particularly care about the list walker data */ 656 iscsi_dcmd_ctrl_t *idc = idc_void; 657 int rc; 658 659 rc = iscsi_tgt_impl(addr, idc); 660 661 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR); 662 } 663 664 /*ARGSUSED*/ 665 static int 666 iscsi_tpgt_walk_cb(uintptr_t addr, const void *list_walker_data, 667 void *idc_void) 668 { 669 /* We don't particularly care about the list walker data */ 670 iscsi_dcmd_ctrl_t *idc = idc_void; 671 int rc; 672 673 rc = iscsi_tpgt_impl(addr, idc); 674 675 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR); 676 } 677 678 /*ARGSUSED*/ 679 static int 680 iscsi_portal_walk_cb(uintptr_t addr, const void *list_walker_data, 681 void *idc_void) 682 { 683 /* We don't particularly care about the list walker data */ 684 iscsi_dcmd_ctrl_t *idc = idc_void; 685 int rc; 686 687 rc = iscsi_portal_impl(addr, idc); 688 689 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR); 690 } 691 692 /*ARGSUSED*/ 693 static int 694 iscsi_sess_walk_cb(uintptr_t addr, const void *list_walker_data, 695 void *idc_void) 696 { 697 /* We don't particularly care about the list walker data */ 698 iscsi_dcmd_ctrl_t *idc = idc_void; 699 int rc; 700 701 rc = iscsi_sess_impl(addr, idc); 702 703 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR); 704 } 705 706 /*ARGSUSED*/ 707 static int 708 iscsi_sess_conn_walk_cb(uintptr_t addr, const void *list_walker_data, 709 void *idc_void) 710 { 711 /* We don't particularly care about the list walker data */ 712 iscsi_dcmd_ctrl_t *idc = idc_void; 713 iscsit_conn_t ict; 714 int rc; 715 716 /* 717 * This function is different from iscsi_conn_walk_cb because 718 * we get an iscsit_conn_t instead of an idm_conn_t 719 * 720 * Read iscsit_conn_t, use to get idm_conn_t pointer 721 */ 722 if (mdb_vread(&ict, sizeof (iscsit_conn_t), addr) != 723 sizeof (iscsit_conn_t)) { 724 return (DCMD_ERR); 725 } 726 rc = iscsi_conn_impl((uintptr_t)ict.ict_ic, idc); 727 728 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR); 729 } 730 731 /*ARGSUSED*/ 732 static int 733 iscsi_conn_walk_cb(uintptr_t addr, const void *list_walker_data, 734 void *idc_void) 735 { 736 /* We don't particularly care about the list walker data */ 737 iscsi_dcmd_ctrl_t *idc = idc_void; 738 int rc; 739 740 rc = iscsi_conn_impl(addr, idc); 741 742 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR); 743 } 744 745 /*ARGSUSED*/ 746 static int 747 iscsi_buffer_walk_cb(uintptr_t addr, const void *list_walker_data, 748 void *idc_void) 749 { 750 /* We don't particularly care about the list walker data */ 751 iscsi_dcmd_ctrl_t *idc = idc_void; 752 int rc; 753 754 rc = iscsi_buffer_impl(addr, idc); 755 756 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR); 757 } 758 759 static int 760 iscsi_tgt_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc) 761 { 762 iscsit_tgt_t tgt; 763 uintptr_t avl_addr, rc_addr, states_addr; 764 char tgt_name[MAX_ISCSI_NODENAMELEN]; 765 int verbose, states, rc_audit; 766 767 /* 768 * Read iscsit_tgt_t 769 */ 770 if (mdb_vread(&tgt, sizeof (iscsit_tgt_t), addr) != 771 sizeof (iscsit_tgt_t)) { 772 return (DCMD_ERR); 773 } 774 775 /* 776 * Read target name if available 777 */ 778 if ((tgt.target_name == NULL) || 779 (mdb_readstr(tgt_name, sizeof (tgt_name), 780 (uintptr_t)tgt.target_name) == -1)) { 781 strcpy(tgt_name, "N/A"); 782 } 783 784 /* 785 * Brief output 786 * 787 * iscsit_tgt_t pointer 788 * iscsit_tgt_t.target_stmf_state 789 * iscsit_tgt_t.target_sess_list.avl_numnodes (session count) 790 * iscsit_tgt_t.target_name; 791 */ 792 793 verbose = idc->idc_verbose; 794 states = idc->u.child.idc_states; 795 rc_audit = idc->u.child.idc_rc_audit; 796 797 /* For now we will ignore the verbose flag */ 798 if (idc->u.child.idc_tgt) { 799 /* Print target data */ 800 if (idc->idc_header) { 801 mdb_printf("%<u>%-19s %-4s %-8s%</u>\n", 802 "iscsit_tgt_t", "Sess", "State"); 803 } 804 mdb_printf("%-19p %-4d %-8d\n", addr, 805 tgt.target_sess_list.avl_numnodes, 806 tgt.target_state); 807 mdb_printf(" %s\n", tgt_name); 808 } 809 810 idc->idc_header = 0; 811 idc->idc_verbose = 0; 812 813 /* 814 * Print states if requested 815 */ 816 if (idc->u.child.idc_tgt && states) { 817 states_addr = addr + offsetof(iscsit_tgt_t, target_state_audit); 818 819 (void) mdb_inc_indent(4); 820 mdb_printf("State History:\n"); 821 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK) 822 return (DCMD_ERR); 823 idc->u.child.idc_states = 0; 824 (void) mdb_dec_indent(4); 825 } 826 827 /* 828 * Print refcnt audit data if requested 829 */ 830 if (idc->u.child.idc_tgt && rc_audit) { 831 (void) mdb_inc_indent(4); 832 mdb_printf("target_sess_refcnt:\n"); 833 rc_addr = addr + 834 offsetof(iscsit_tgt_t, target_sess_refcnt); 835 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) 836 return (DCMD_ERR); 837 838 mdb_printf("target_refcnt:\n"); 839 rc_addr = addr + 840 offsetof(iscsit_tgt_t, target_refcnt); 841 842 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) 843 return (DCMD_ERR); 844 idc->u.child.idc_rc_audit = 0; 845 (void) mdb_dec_indent(4); 846 } 847 848 /* Any child objects to walk? */ 849 if (idc->u.child.idc_tpgt || idc->u.child.idc_sess || 850 idc->u.child.idc_conn || idc->u.child.idc_task || 851 idc->u.child.idc_buffer) { 852 /* Walk TPGT tree */ 853 idc->idc_header = 1; 854 (void) mdb_inc_indent(4); 855 avl_addr = addr + 856 offsetof(iscsit_tgt_t, target_tpgt_list); 857 if (mdb_pwalk("avl", iscsi_tpgt_walk_cb, idc, 858 avl_addr) == -1) { 859 mdb_warn("target tpgt list walk failed"); 860 (void) mdb_dec_indent(4); 861 return (DCMD_ERR); 862 } 863 (void) mdb_dec_indent(4); 864 865 /* Walk sess tree */ 866 idc->idc_header = 1; 867 (void) mdb_inc_indent(4); 868 avl_addr = addr + offsetof(iscsit_tgt_t, target_sess_list); 869 if (mdb_pwalk("avl", iscsi_sess_walk_cb, idc, 870 avl_addr) == -1) { 871 mdb_warn("target sess list walk failed"); 872 (void) mdb_dec_indent(4); 873 return (DCMD_ERR); 874 } 875 (void) mdb_dec_indent(4); 876 877 idc->idc_header = 0; 878 } 879 880 idc->idc_verbose = verbose; 881 idc->u.child.idc_states = states; 882 idc->u.child.idc_rc_audit = rc_audit; 883 return (DCMD_OK); 884 } 885 886 static int 887 iscsi_tpgt_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc) 888 { 889 iscsit_tpgt_t tpgt; 890 iscsit_tpg_t tpg; 891 uintptr_t avl_addr, tpg_addr; 892 893 /* 894 * Read iscsit_tpgt_t 895 */ 896 if (mdb_vread(&tpgt, sizeof (iscsit_tpgt_t), addr) != 897 sizeof (iscsit_tpgt_t)) { 898 return (DCMD_ERR); 899 } 900 901 tpg_addr = (uintptr_t)tpgt.tpgt_tpg; 902 903 /* 904 * Read iscsit_tpg_t 905 */ 906 if (mdb_vread(&tpg, sizeof (iscsit_tpg_t), tpg_addr) != 907 sizeof (iscsit_tpg_t)) { 908 return (DCMD_ERR); 909 } 910 911 /* 912 * Brief output 913 * 914 * iscsit_tpgt_t pointer 915 * iscsit_tpg_t pointer 916 * iscsit_tpg_t.tpg_name 917 * iscsit_tpgt_t.tpgt_tag; 918 */ 919 920 /* For now we will ignore the verbose flag */ 921 if (idc->u.child.idc_tpgt) { 922 /* Print target data */ 923 if (idc->idc_header) { 924 mdb_printf("%<u>%-?s %-?s %-18s %-6s%</u>\n", 925 "iscsit_tpgt_t", "iscsit_tpg_t", "Name", "Tag"); 926 } 927 mdb_printf("%?p %?p %-18s 0x%04x\n", addr, tpgt.tpgt_tpg, 928 tpg.tpg_name, tpgt.tpgt_tag); 929 } 930 931 /* 932 * Assume for now that anyone interested in TPGT wants to see the 933 * portals as well. 934 */ 935 idc->idc_header = 1; 936 (void) mdb_inc_indent(4); 937 avl_addr = tpg_addr + offsetof(iscsit_tpg_t, tpg_portal_list); 938 if (mdb_pwalk("avl", iscsi_portal_walk_cb, idc, avl_addr) == -1) { 939 mdb_warn("portal list walk failed"); 940 (void) mdb_dec_indent(4); 941 return (DCMD_ERR); 942 } 943 (void) mdb_dec_indent(4); 944 idc->idc_header = 0; 945 946 return (DCMD_OK); 947 } 948 949 static int 950 iscsi_tpg_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc) 951 { 952 iscsit_tpg_t tpg; 953 uintptr_t avl_addr; 954 955 /* 956 * Read iscsit_tpg_t 957 */ 958 if (mdb_vread(&tpg, sizeof (iscsit_tpg_t), addr) != 959 sizeof (iscsit_tpg_t)) { 960 return (DCMD_ERR); 961 } 962 963 /* 964 * Brief output 965 * 966 * iscsit_tpgt_t pointer 967 * iscsit_tpg_t pointer 968 * iscsit_tpg_t.tpg_name 969 * iscsit_tpgt_t.tpgt_tag; 970 */ 971 972 /* For now we will ignore the verbose flag */ 973 974 /* Print target data */ 975 if (idc->idc_header) { 976 mdb_printf("%<u>%-?s %-18s%</u>\n", 977 "iscsit_tpg_t", "Name"); 978 } 979 mdb_printf("%?p %-18s\n", addr, tpg.tpg_name); 980 981 982 /* 983 * Assume for now that anyone interested in TPG wants to see the 984 * portals as well. 985 */ 986 idc->idc_header = 1; 987 (void) mdb_inc_indent(4); 988 avl_addr = addr + offsetof(iscsit_tpg_t, tpg_portal_list); 989 if (mdb_pwalk("avl", iscsi_portal_walk_cb, idc, avl_addr) == -1) { 990 mdb_warn("portal list walk failed"); 991 (void) mdb_dec_indent(4); 992 return (DCMD_ERR); 993 } 994 (void) mdb_dec_indent(4); 995 idc->idc_header = 0; 996 997 return (DCMD_OK); 998 } 999 1000 static int 1001 iscsi_portal_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc) 1002 { 1003 iscsit_portal_t portal; 1004 char portal_addr[PORTAL_STR_LEN]; 1005 if (idc->u.child.idc_portal) { 1006 /* 1007 * Read iscsit_portal_t 1008 */ 1009 if (mdb_vread(&portal, sizeof (iscsit_portal_t), addr) != 1010 sizeof (iscsit_portal_t)) { 1011 return (DCMD_ERR); 1012 } 1013 1014 /* Print portal data */ 1015 if (idc->idc_header) { 1016 mdb_printf("%<u>%-?s %-?s %-30s%</u>\n", 1017 "iscsit_portal_t", "idm_svc_t", "IP:Port"); 1018 } 1019 sa_to_str(&portal.portal_addr, portal_addr); 1020 mdb_printf("%?p %?p %s\n", addr, portal.portal_svc, 1021 portal_addr); 1022 } 1023 1024 return (DCMD_OK); 1025 } 1026 1027 static int 1028 iscsi_sess_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc) 1029 { 1030 iscsit_sess_t ist; 1031 uintptr_t list_addr, states_addr, rc_addr; 1032 char ini_name[80]; 1033 char tgt_name[80]; 1034 int verbose, states, rc_audit; 1035 1036 /* 1037 * Read iscsit_sess_t 1038 */ 1039 if (mdb_vread(&ist, sizeof (iscsit_sess_t), addr) != 1040 sizeof (iscsit_sess_t)) { 1041 return (DCMD_ERR); 1042 } 1043 1044 /* 1045 * Brief output 1046 * 1047 * iscsit_sess_t pointer 1048 * iscsit_sess_t.ist_state/iscsit_sess_t.ist_ffp_conn_count 1049 * iscsit_sess_t.ist_tsih 1050 * iscsit_sess_t.ist_initiator_name 1051 */ 1052 1053 verbose = idc->idc_verbose; 1054 states = idc->u.child.idc_states; 1055 rc_audit = idc->u.child.idc_rc_audit; 1056 1057 if (idc->u.child.idc_sess) { 1058 if (verbose) { 1059 /* 1060 * Read initiator name if available 1061 */ 1062 if ((ist.ist_initiator_name == NULL) || 1063 (mdb_readstr(ini_name, sizeof (ini_name), 1064 (uintptr_t)ist.ist_initiator_name) == -1)) { 1065 strcpy(ini_name, "N/A"); 1066 } 1067 1068 /* 1069 * Read target name if available 1070 */ 1071 if ((ist.ist_target_name == NULL) || 1072 (mdb_readstr(tgt_name, sizeof (tgt_name), 1073 (uintptr_t)ist.ist_target_name) == -1)) { 1074 strcpy(tgt_name, "N/A"); 1075 } 1076 1077 mdb_printf("Session %p\n", addr); 1078 mdb_printf("%16s: %d\n", "State", 1079 ist.ist_state); 1080 mdb_printf("%16s: %d\n", "Last State", 1081 ist.ist_last_state); 1082 mdb_printf("%16s: %d\n", "FFP Connections", 1083 ist.ist_ffp_conn_count); 1084 mdb_printf("%16s: %02x%02x%02x%02x%02x%02x\n", "ISID", 1085 ist.ist_isid[0], ist.ist_isid[1], ist.ist_isid[2], 1086 ist.ist_isid[3], ist.ist_isid[4], ist.ist_isid[5]); 1087 mdb_printf("%16s: 0x%04x\n", "TSIH", 1088 ist.ist_tsih); 1089 mdb_printf("%16s: %s\n", "Initiator IQN", 1090 ini_name); 1091 mdb_printf("%16s: %s\n", "Target IQN", 1092 tgt_name); 1093 mdb_printf("%16s: %08x\n", "ExpCmdSN", 1094 ist.ist_expcmdsn); 1095 mdb_printf("%16s: %08x\n", "MaxCmdSN", 1096 ist.ist_maxcmdsn); 1097 } else { 1098 /* Print session data */ 1099 if (idc->idc_header) { 1100 mdb_printf("%<u>%-?s %10s %-12s %-6s%</u>\n", 1101 "iscsit_sess_t", "State/Conn", "ISID", 1102 "TSIH"); 1103 } 1104 mdb_printf("%?p %4d/%-4d %02x%02x%02x%02x%02x%02x " 1105 "0x%04x\n", addr, 1106 ist.ist_state, ist.ist_ffp_conn_count, 1107 ist.ist_isid[0], ist.ist_isid[1], ist.ist_isid[2], 1108 ist.ist_isid[3], ist.ist_isid[4], ist.ist_isid[5], 1109 ist.ist_tsih); 1110 } 1111 idc->idc_header = 0; 1112 } 1113 1114 idc->idc_verbose = 0; 1115 1116 /* 1117 * Print states if requested 1118 */ 1119 if (states) { 1120 states_addr = addr + offsetof(iscsit_sess_t, ist_state_audit); 1121 1122 (void) mdb_inc_indent(4); 1123 mdb_printf("State History:\n"); 1124 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK) 1125 return (DCMD_ERR); 1126 1127 /* Don't print state history for child objects */ 1128 idc->u.child.idc_states = 0; 1129 (void) mdb_dec_indent(4); 1130 } 1131 1132 /* 1133 * Print refcnt audit data if requested 1134 */ 1135 if (rc_audit) { 1136 (void) mdb_inc_indent(4); 1137 mdb_printf("Reference History:\n"); 1138 rc_addr = addr + 1139 offsetof(iscsit_sess_t, ist_refcnt); 1140 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) 1141 return (DCMD_ERR); 1142 1143 /* Don't print audit data for child objects */ 1144 idc->u.child.idc_rc_audit = 0; 1145 (void) mdb_dec_indent(4); 1146 } 1147 1148 /* Any child objects to walk? */ 1149 if (idc->u.child.idc_conn || idc->u.child.idc_task || 1150 idc->u.child.idc_buffer) { 1151 /* Walk conn list */ 1152 idc->idc_header = 1; 1153 (void) mdb_inc_indent(4); 1154 list_addr = addr + offsetof(iscsit_sess_t, ist_conn_list); 1155 if (mdb_pwalk("list", iscsi_sess_conn_walk_cb, idc, 1156 list_addr) == -1) { 1157 mdb_warn("session conn list walk failed"); 1158 (void) mdb_dec_indent(4); 1159 return (DCMD_ERR); 1160 } 1161 (void) mdb_dec_indent(4); 1162 idc->idc_header = 0; 1163 } 1164 1165 idc->idc_verbose = verbose; 1166 idc->u.child.idc_states = states; 1167 idc->u.child.idc_rc_audit = rc_audit; 1168 1169 return (DCMD_OK); 1170 } 1171 1172 static int 1173 iscsi_conn_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc) 1174 { 1175 uintptr_t idm_global_addr, states_addr, rc_addr; 1176 uintptr_t task_addr, task_ptr; 1177 GElf_Sym sym; 1178 idm_task_t idt; 1179 idm_conn_t ic; 1180 char *conn_type; 1181 int task_idx; 1182 char laddr[PORTAL_STR_LEN]; 1183 char raddr[PORTAL_STR_LEN]; 1184 int verbose, states, rc_audit; 1185 1186 /* 1187 * Get pointer to task table 1188 */ 1189 1190 if (mdb_lookup_by_name("idm", &sym) == -1) { 1191 mdb_warn("failed to find symbol 'idm'"); 1192 return (DCMD_ERR); 1193 } 1194 1195 idm_global_addr = (uintptr_t)sym.st_value; 1196 1197 if (mdb_vread(&task_ptr, sizeof (uintptr_t), 1198 idm_global_addr + offsetof(idm_global_t, idm_taskid_table)) != 1199 sizeof (uintptr_t)) { 1200 mdb_warn("Failed to read address of task table"); 1201 return (DCMD_ERR); 1202 } 1203 1204 /* 1205 * Read idm_conn_t 1206 */ 1207 if (mdb_vread(&ic, sizeof (idm_conn_t), addr) != sizeof (idm_conn_t)) { 1208 return (DCMD_ERR); 1209 } 1210 conn_type = (ic.ic_conn_type == CONN_TYPE_INI) ? "Ini" : 1211 (ic.ic_conn_type == CONN_TYPE_TGT) ? "Tgt" : "Unk"; 1212 1213 /* 1214 * Brief output 1215 * 1216 * idm_conn_t pointer 1217 * idm_conn_t.ic_conn_type 1218 * idm_conn_t.ic_statet+idm_conn_t.ic_ffp 1219 */ 1220 1221 verbose = idc->idc_verbose; 1222 states = idc->u.child.idc_states; 1223 rc_audit = idc->u.child.idc_rc_audit; 1224 1225 if (idc->u.child.idc_conn) { 1226 if (idc->idc_verbose) { 1227 mdb_printf("IDM Conn %p\n", addr); 1228 if (ic.ic_conn_type == CONN_TYPE_TGT) { 1229 iscsi_print_iscsit_conn_data(&ic); 1230 } else { 1231 iscsi_print_idm_conn_data(&ic); 1232 } 1233 } else { 1234 /* Print connection data */ 1235 if (idc->idc_header) { 1236 mdb_printf("%<u>%-?s %-6s %-10s %12s%</u>\n", 1237 "idm_conn_t", "Type", "Transport", 1238 "State/FFP"); 1239 } 1240 mdb_printf("%?p %-6s %-10s %6d/%-6d\n", addr, conn_type, 1241 (ic.ic_transport_type == 1242 IDM_TRANSPORT_TYPE_ISER) ? "ISER_IB" : 1243 (ic.ic_transport_type == 1244 IDM_TRANSPORT_TYPE_SOCKETS) ? "SOCKETS" : 1245 "N/A", 1246 ic.ic_state, ic.ic_ffp); 1247 if (idc->u.child.idc_print_ip) { 1248 sa_to_str(&ic.ic_laddr, laddr); 1249 sa_to_str(&ic.ic_raddr, raddr); 1250 mdb_printf(" L%s R%s\n", 1251 laddr, raddr); 1252 } 1253 } 1254 } 1255 idc->idc_header = 0; 1256 1257 idc->idc_verbose = 0; 1258 1259 /* 1260 * Print states if requested 1261 */ 1262 if (states) { 1263 states_addr = addr + offsetof(idm_conn_t, ic_state_audit); 1264 1265 (void) mdb_inc_indent(4); 1266 mdb_printf("State History:\n"); 1267 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK) 1268 return (DCMD_ERR); 1269 1270 /* Don't print state history for child objects */ 1271 idc->u.child.idc_states = 0; 1272 (void) mdb_dec_indent(4); 1273 } 1274 1275 /* 1276 * Print refcnt audit data if requested 1277 */ 1278 if (rc_audit) { 1279 (void) mdb_inc_indent(4); 1280 mdb_printf("Reference History:\n"); 1281 rc_addr = addr + offsetof(idm_conn_t, ic_refcnt); 1282 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) 1283 return (DCMD_ERR); 1284 1285 /* Don't print audit data for child objects */ 1286 idc->u.child.idc_rc_audit = 0; 1287 (void) mdb_dec_indent(4); 1288 } 1289 1290 task_idx = 0; 1291 1292 /* Any child objects to walk? */ 1293 if (idc->u.child.idc_task || idc->u.child.idc_buffer) { 1294 idc->idc_header = 1; 1295 while (task_idx < IDM_TASKIDS_MAX) { 1296 1297 /* 1298 * Read the next idm_task_t 1299 */ 1300 1301 if (mdb_vread(&task_addr, sizeof (uintptr_t), 1302 task_ptr) != sizeof (uintptr_t)) { 1303 mdb_warn("Failed to read task pointer"); 1304 return (DCMD_ERR); 1305 } 1306 1307 if (task_addr == NULL) { 1308 task_ptr += sizeof (uintptr_t); 1309 task_idx++; 1310 continue; 1311 } 1312 1313 if (mdb_vread(&idt, sizeof (idm_task_t), task_addr) 1314 != sizeof (idm_task_t)) { 1315 mdb_warn("Failed to read task pointer"); 1316 return (DCMD_ERR); 1317 } 1318 1319 if (((uintptr_t)idt.idt_ic == addr) && 1320 (idt.idt_state != TASK_IDLE)) { 1321 (void) mdb_inc_indent(4); 1322 if (iscsi_i_task_impl(&idt, task_addr, idc) 1323 == -1) { 1324 mdb_warn("Failed to walk connection " 1325 "task tree"); 1326 (void) mdb_dec_indent(4); 1327 return (DCMD_ERR); 1328 } 1329 (void) mdb_dec_indent(4); 1330 } 1331 1332 task_ptr += sizeof (uintptr_t); 1333 task_idx++; 1334 } 1335 idc->idc_header = 0; 1336 } 1337 1338 idc->idc_verbose = verbose; 1339 idc->u.child.idc_states = states; 1340 idc->u.child.idc_rc_audit = rc_audit; 1341 1342 return (DCMD_OK); 1343 } 1344 1345 static void 1346 iscsi_print_iscsit_conn_data(idm_conn_t *ic) 1347 { 1348 iscsit_conn_t ict; 1349 char *csg; 1350 char *nsg; 1351 1352 iscsi_print_idm_conn_data(ic); 1353 1354 if (mdb_vread(&ict, sizeof (iscsit_conn_t), 1355 (uintptr_t)ic->ic_handle) != sizeof (iscsit_conn_t)) { 1356 mdb_printf("**Failed to read conn private data\n"); 1357 return; 1358 } 1359 1360 if (ict.ict_login_sm.icl_login_state != ILS_LOGIN_DONE) { 1361 switch (ict.ict_login_sm.icl_login_csg) { 1362 case ISCSI_SECURITY_NEGOTIATION_STAGE: 1363 csg = "Security"; 1364 break; 1365 case ISCSI_OP_PARMS_NEGOTIATION_STAGE: 1366 csg = "Operational"; 1367 break; 1368 case ISCSI_FULL_FEATURE_PHASE: 1369 csg = "FFP"; 1370 break; 1371 default: 1372 csg = "Unknown"; 1373 } 1374 switch (ict.ict_login_sm.icl_login_nsg) { 1375 case ISCSI_SECURITY_NEGOTIATION_STAGE: 1376 nsg = "Security"; 1377 break; 1378 case ISCSI_OP_PARMS_NEGOTIATION_STAGE: 1379 nsg = "Operational"; 1380 break; 1381 case ISCSI_FULL_FEATURE_PHASE: 1382 nsg = "FFP"; 1383 break; 1384 default: 1385 nsg = "Unknown"; 1386 } 1387 mdb_printf("%20s: %d\n", "Login State", 1388 ict.ict_login_sm.icl_login_state); 1389 mdb_printf("%20s: %d\n", "Login Last State", 1390 ict.ict_login_sm.icl_login_last_state); 1391 mdb_printf("%20s: %s\n", "CSG", csg); 1392 mdb_printf("%20s: %s\n", "NSG", nsg); 1393 mdb_printf("%20s: %d\n", "Transit", 1394 ict.ict_login_sm.icl_login_transit >> 7); 1395 mdb_printf("%20s: %p\n", "Request nvlist", 1396 ict.ict_login_sm.icl_request_nvlist); 1397 mdb_printf("%20s: %p\n", "Response nvlist", 1398 ict.ict_login_sm.icl_response_nvlist); 1399 mdb_printf("%20s: %p\n", "Negotiated nvlist", 1400 ict.ict_login_sm.icl_negotiated_values); 1401 if (ict.ict_login_sm.icl_login_state == ILS_LOGIN_ERROR) { 1402 mdb_printf("%20s: 0x%02x\n", "Error Class", 1403 ict.ict_login_sm.icl_login_resp_err_class); 1404 mdb_printf("%20s: 0x%02x\n", "Error Detail", 1405 ict.ict_login_sm.icl_login_resp_err_detail); 1406 } 1407 } 1408 mdb_printf("%20s: 0x%04x\n", "CID", ict.ict_cid); 1409 mdb_printf("%20s: 0x%08x\n", "StatSN", ict.ict_statsn); 1410 } 1411 1412 static void 1413 iscsi_print_idm_conn_data(idm_conn_t *ic) 1414 { 1415 char laddr[PORTAL_STR_LEN]; 1416 char raddr[PORTAL_STR_LEN]; 1417 1418 sa_to_str(&ic->ic_laddr, laddr); 1419 sa_to_str(&ic->ic_raddr, raddr); 1420 1421 mdb_printf("%20s: %s\n", "Conn Type", 1422 ((ic->ic_conn_type == CONN_TYPE_TGT) ? "Target" : 1423 ((ic->ic_conn_type == CONN_TYPE_INI) ? "Initiator" : 1424 "Unknown"))); 1425 if (ic->ic_conn_type == CONN_TYPE_TGT) { 1426 mdb_printf("%20s: %p\n", "Svc. Binding", 1427 ic->ic_svc_binding); 1428 } 1429 mdb_printf("%20s: %s\n", "Transport", 1430 (ic->ic_transport_type == IDM_TRANSPORT_TYPE_ISER) ? "ISER_IB" : 1431 (ic->ic_transport_type == IDM_TRANSPORT_TYPE_SOCKETS) ? "SOCKETS" : 1432 "N/A"); 1433 1434 mdb_printf("%20s: %s\n", "Local IP", laddr); 1435 mdb_printf("%20s: %s\n", "Remote IP", raddr); 1436 mdb_printf("%20s: %d\n", "State", 1437 ic->ic_state); 1438 mdb_printf("%20s: %d\n", "Last State", 1439 ic->ic_last_state); 1440 mdb_printf("%20s: %d %s\n", "Refcount", 1441 ic->ic_refcnt.ir_refcnt, 1442 (ic->ic_refcnt.ir_waiting == REF_NOWAIT) ? "" : 1443 ((ic->ic_refcnt.ir_waiting == REF_WAIT_SYNC) ? "REF_WAIT_SYNC" : 1444 ((ic->ic_refcnt.ir_waiting == REF_WAIT_ASYNC) ? "REF_WAIT_ASYNC" : 1445 "UNKNOWN"))); 1446 } 1447 1448 static int 1449 iscsi_i_task_impl(idm_task_t *idt, uintptr_t addr, iscsi_dcmd_ctrl_t *idc) 1450 { 1451 uintptr_t list_addr, rc_addr; 1452 idm_conn_type_t conn_type; 1453 int verbose, states, rc_audit; 1454 1455 conn_type = idm_conn_type((uintptr_t)idt->idt_ic); 1456 1457 verbose = idc->idc_verbose; 1458 states = idc->u.child.idc_states; 1459 rc_audit = idc->u.child.idc_rc_audit; 1460 1461 if (idc->u.child.idc_task) { 1462 if (verbose) { 1463 mdb_printf("Task %p\n", addr); 1464 (void) mdb_inc_indent(2); 1465 if (conn_type == CONN_TYPE_TGT) { 1466 iscsi_print_iscsit_task_data(idt); 1467 } 1468 (void) mdb_dec_indent(2); 1469 } else { 1470 /* Print task data */ 1471 if (idc->idc_header) { 1472 mdb_printf( 1473 "%<u>%-?s %-16s %-4s %-8s %-8s%</u>\n", 1474 "Tasks:", "State", "Ref", 1475 (conn_type == CONN_TYPE_TGT ? "TTT" : 1476 (conn_type == CONN_TYPE_INI ? "ITT" : 1477 "TT")), "Handle"); 1478 } 1479 mdb_printf("%?p %-16s %04x %08x %08x\n", addr, 1480 idm_ts_name[idt->idt_state], 1481 idt->idt_refcnt.ir_refcnt, 1482 idt->idt_tt, idt->idt_client_handle); 1483 } 1484 } 1485 idc->idc_header = 0; 1486 idc->idc_verbose = 0; 1487 1488 /* 1489 * Print states if requested 1490 */ 1491 #if 0 1492 if (states) { 1493 states_addr = addr + offsetof(idm_task_t, idt_state_audit); 1494 1495 (void) mdb_inc_indent(4); 1496 mdb_printf("State History:\n"); 1497 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK) 1498 return (DCMD_ERR); 1499 1500 /* Don't print state history for child objects */ 1501 idc->u.child.idc_states = 0; 1502 (void) mdb_dec_indent(4); 1503 } 1504 #endif 1505 1506 /* 1507 * Print refcnt audit data if requested 1508 */ 1509 if (rc_audit) { 1510 (void) mdb_inc_indent(4); 1511 mdb_printf("Reference History:\n"); 1512 rc_addr = addr + 1513 offsetof(idm_task_t, idt_refcnt); 1514 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) 1515 return (DCMD_ERR); 1516 1517 /* Don't print audit data for child objects */ 1518 idc->u.child.idc_rc_audit = 0; 1519 (void) mdb_dec_indent(4); 1520 } 1521 1522 1523 /* Buffers are leaf objects */ 1524 if (idc->u.child.idc_buffer) { 1525 /* Walk in buffer list */ 1526 (void) mdb_inc_indent(2); 1527 mdb_printf("In buffers:\n"); 1528 idc->idc_header = 1; 1529 (void) mdb_inc_indent(2); 1530 list_addr = addr + offsetof(idm_task_t, idt_inbufv); 1531 if (mdb_pwalk("list", iscsi_buffer_walk_cb, idc, list_addr) == 1532 -1) { 1533 mdb_warn("list walk failed for task in buffers"); 1534 (void) mdb_dec_indent(4); 1535 return (DCMD_ERR); 1536 } 1537 (void) mdb_dec_indent(2); 1538 /* Walk out buffer list */ 1539 mdb_printf("Out buffers:\n"); 1540 idc->idc_header = 1; 1541 (void) mdb_inc_indent(2); 1542 list_addr = addr + offsetof(idm_task_t, idt_outbufv); 1543 if (mdb_pwalk("list", iscsi_buffer_walk_cb, idc, list_addr) == 1544 -1) { 1545 mdb_warn("list walk failed for task out buffers\n"); 1546 (void) mdb_dec_indent(2); 1547 return (DCMD_ERR); 1548 } 1549 (void) mdb_dec_indent(4); 1550 } 1551 1552 idc->idc_verbose = verbose; 1553 idc->u.child.idc_states = states; 1554 idc->u.child.idc_rc_audit = rc_audit; 1555 1556 return (DCMD_OK); 1557 } 1558 1559 static int 1560 iscsi_task_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc) 1561 { 1562 idm_task_t idt; 1563 1564 /* 1565 * Read idm_conn_t 1566 */ 1567 if (mdb_vread(&idt, sizeof (idm_task_t), addr) != sizeof (idm_task_t)) { 1568 return (DCMD_ERR); 1569 } 1570 1571 return (iscsi_i_task_impl(&idt, addr, idc)); 1572 } 1573 1574 #define ISCSI_CDB_INDENT 16 1575 1576 static void 1577 iscsi_print_iscsit_task_data(idm_task_t *idt) 1578 { 1579 iscsit_task_t itask; 1580 boolean_t good_scsi_task = B_TRUE; 1581 scsi_task_t scsi_task; 1582 1583 if (mdb_vread(&itask, sizeof (iscsit_task_t), 1584 (uintptr_t)idt->idt_private) != sizeof (iscsit_task_t)) { 1585 mdb_printf("**Failed to read idt_private data\n"); 1586 return; 1587 } 1588 1589 if (mdb_vread(&scsi_task, sizeof (scsi_task_t), 1590 (uintptr_t)itask.it_stmf_task) != sizeof (scsi_task_t)) { 1591 good_scsi_task = B_FALSE; 1592 } 1593 1594 mdb_printf("%20s: %s(%d)\n", "State", 1595 idt->idt_state > TASK_MAX_STATE ? 1596 "UNKNOWN" : idm_ts_name[idt->idt_state], 1597 idt->idt_state); 1598 mdb_printf("%20s: %d/%d\n", "STMF abort/IDM aborted", 1599 itask.it_stmf_abort, itask.it_aborted); 1600 mdb_printf("%20s: %p/%p/%p%s\n", 1601 "iscsit/STMF/LU", idt->idt_private, 1602 itask.it_stmf_task, good_scsi_task ? scsi_task.task_lu_private : 0, 1603 good_scsi_task ? "" : "**"); 1604 if (good_scsi_task) { 1605 mdb_printf("%20s: %08x/%08x\n", "ITT/TTT", 1606 itask.it_itt, itask.it_ttt); 1607 mdb_printf("%20s: %08x\n", "CmdSN", 1608 itask.it_cmdsn); 1609 mdb_printf("%20s: %02x %02x %02x %02x %02x %02x %02x %02x\n", 1610 "LU number", 1611 scsi_task.task_lun_no[0], scsi_task.task_lun_no[1], 1612 scsi_task.task_lun_no[2], scsi_task.task_lun_no[3], 1613 scsi_task.task_lun_no[4], scsi_task.task_lun_no[5], 1614 scsi_task.task_lun_no[6], scsi_task.task_lun_no[7]); 1615 mdb_printf(" CDB (%d bytes):\n", 1616 scsi_task.task_cdb_length); 1617 (void) mdb_inc_indent(ISCSI_CDB_INDENT); 1618 if (mdb_dumpptr((uintptr_t)scsi_task.task_cdb, 1619 scsi_task.task_cdb_length, 1620 MDB_DUMP_RELATIVE | MDB_DUMP_TRIM | 1621 MDB_DUMP_GROUP(1), 1622 (mdb_dumpptr_cb_t)mdb_vread, NULL)) { 1623 mdb_printf("** Invalid CDB addr (%p)\n", 1624 scsi_task.task_cdb); 1625 } 1626 (void) mdb_dec_indent(ISCSI_CDB_INDENT); 1627 mdb_printf("%20s: %d/%d\n", "STMF cur/max bufs", 1628 scsi_task.task_cur_nbufs, 1629 scsi_task.task_max_nbufs); 1630 mdb_printf("%20s: 0x%08x/0x%08x/0x%08x\n", "Bytes Exp/Cmd/Done", 1631 scsi_task.task_expected_xfer_length, 1632 scsi_task.task_cmd_xfer_length, 1633 scsi_task.task_nbytes_transferred); 1634 mdb_printf("%20s: 0x%x/0x%x\n", "TX-ini start/done", 1635 idt->idt_tx_to_ini_start, 1636 idt->idt_tx_to_ini_done); 1637 mdb_printf("%20s: 0x%x/0x%x\n", "RX-ini start/done", 1638 idt->idt_rx_from_ini_start, 1639 idt->idt_rx_from_ini_done); 1640 } 1641 } 1642 1643 static int 1644 iscsi_buffer_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc) 1645 { 1646 idm_buf_t idb; 1647 1648 /* 1649 * Read idm_buf_t 1650 */ 1651 if (mdb_vread(&idb, sizeof (idm_buf_t), addr) != sizeof (idm_buf_t)) { 1652 return (DCMD_ERR); 1653 } 1654 1655 1656 if (idc->idc_header) { 1657 mdb_printf("%<u>%-?s %?s/%-8s %8s %8s %8s%</u>\n", 1658 "idm_buf_t", "Mem Rgn", "Length", 1659 "Rel Off", "Xfer Len", "Exp. Off"); 1660 } 1661 idc->idc_header = 0; 1662 1663 /* Print buffer data */ 1664 mdb_printf("%?p %?p/%08x %8x %8x %08x\n", addr, 1665 idb.idb_buf, idb.idb_buflen, 1666 idb.idb_bufoffset, idb.idb_xfer_len, 1667 idb.idb_exp_offset); 1668 1669 1670 /* Buffers are leaf objects */ 1671 1672 return (DCMD_OK); 1673 } 1674 1675 static int 1676 iscsi_refcnt_impl(uintptr_t addr) 1677 { 1678 idm_refcnt_t refcnt; 1679 refcnt_audit_buf_t *anb; 1680 int ctr; 1681 1682 /* 1683 * Print refcnt info 1684 */ 1685 if (mdb_vread(&refcnt, sizeof (idm_refcnt_t), addr) != 1686 sizeof (idm_refcnt_t)) { 1687 return (DCMD_ERR); 1688 } 1689 1690 anb = &refcnt.ir_audit_buf; 1691 1692 ctr = anb->anb_max_index + 1; 1693 anb->anb_index--; 1694 anb->anb_index &= anb->anb_max_index; 1695 1696 while (ctr) { 1697 refcnt_audit_record_t *anr; 1698 1699 anr = anb->anb_records + anb->anb_index; 1700 1701 if (anr->anr_depth) { 1702 char c[MDB_SYM_NAMLEN]; 1703 GElf_Sym sym; 1704 int i; 1705 1706 mdb_printf("\nRefCnt: %u\t", anr->anr_refcnt); 1707 1708 for (i = 0; i < anr->anr_depth; i++) { 1709 if (mdb_lookup_by_addr(anr->anr_stack[i], 1710 MDB_SYM_FUZZY, c, sizeof (c), 1711 &sym) == -1) { 1712 continue; 1713 } 1714 mdb_printf("%s+0x%1x", c, 1715 anr->anr_stack[i] - 1716 (uintptr_t)sym.st_value); 1717 ++i; 1718 break; 1719 } 1720 1721 while (i < anr->anr_depth) { 1722 if (mdb_lookup_by_addr(anr->anr_stack[i], 1723 MDB_SYM_FUZZY, c, sizeof (c), 1724 &sym) == -1) { 1725 ++i; 1726 continue; 1727 } 1728 mdb_printf("\n\t\t%s+0x%1x", c, 1729 anr->anr_stack[i] - 1730 (uintptr_t)sym.st_value); 1731 ++i; 1732 } 1733 mdb_printf("\n"); 1734 } 1735 anb->anb_index--; 1736 anb->anb_index &= anb->anb_max_index; 1737 ctr--; 1738 } 1739 1740 return (DCMD_OK); 1741 } 1742 1743 static int 1744 iscsi_sm_audit_impl(uintptr_t addr) 1745 { 1746 sm_audit_buf_t audit_buf; 1747 int ctr; 1748 const char *event_name; 1749 const char *state_name; 1750 const char *new_state_name; 1751 char ts_string[40]; 1752 /* 1753 * Print refcnt info 1754 */ 1755 if (mdb_vread(&audit_buf, sizeof (sm_audit_buf_t), addr) != 1756 sizeof (sm_audit_buf_t)) { 1757 return (DCMD_ERR); 1758 } 1759 1760 ctr = audit_buf.sab_max_index + 1; 1761 audit_buf.sab_index++; 1762 audit_buf.sab_index &= audit_buf.sab_max_index; 1763 1764 while (ctr) { 1765 sm_audit_record_t *sar; 1766 1767 sar = audit_buf.sab_records + audit_buf.sab_index; 1768 1769 iscsi_format_timestamp(ts_string, 40, &sar->sar_timestamp); 1770 1771 switch (sar->sar_type) { 1772 case SAR_STATE_EVENT: 1773 switch (sar->sar_sm_type) { 1774 case SAS_IDM_CONN: 1775 state_name = 1776 iscsi_idm_conn_state(sar->sar_state); 1777 event_name = 1778 iscsi_idm_conn_event(sar->sar_event); 1779 break; 1780 case SAS_ISCSIT_TGT: 1781 state_name = 1782 iscsi_iscsit_tgt_state(sar->sar_state); 1783 event_name = 1784 iscsi_iscsit_tgt_event(sar->sar_event); 1785 break; 1786 case SAS_ISCSIT_SESS: 1787 state_name = 1788 iscsi_iscsit_sess_state(sar->sar_state); 1789 event_name = 1790 iscsi_iscsit_sess_event(sar->sar_event); 1791 break; 1792 case SAS_ISCSIT_LOGIN: 1793 state_name = 1794 iscsi_iscsit_login_state(sar->sar_state); 1795 event_name = 1796 iscsi_iscsit_login_event(sar->sar_event); 1797 break; 1798 case SAS_ISCSI_CMD: 1799 state_name = 1800 iscsi_iscsi_cmd_state(sar->sar_state); 1801 event_name= 1802 iscsi_iscsi_cmd_event(sar->sar_event); 1803 break; 1804 case SAS_ISCSI_SESS: 1805 state_name = 1806 iscsi_iscsi_sess_state(sar->sar_state); 1807 event_name= 1808 iscsi_iscsi_sess_event(sar->sar_event); 1809 break; 1810 default: 1811 state_name = event_name = "N/A"; 1812 break; 1813 } 1814 mdb_printf("%s|%s (%d)\n\t%9s %s (%d) %p\n", 1815 ts_string, state_name, sar->sar_state, 1816 "Event", event_name, 1817 sar->sar_event, sar->sar_event_info); 1818 1819 break; 1820 case SAR_STATE_CHANGE: 1821 switch (sar->sar_sm_type) { 1822 case SAS_IDM_CONN: 1823 state_name = 1824 iscsi_idm_conn_state(sar->sar_state); 1825 new_state_name = 1826 iscsi_idm_conn_state(sar->sar_new_state); 1827 break; 1828 case SAS_IDM_TASK: 1829 state_name = 1830 iscsi_idm_task_state(sar->sar_state); 1831 new_state_name = 1832 iscsi_idm_task_state(sar->sar_new_state); 1833 break; 1834 case SAS_ISCSIT_TGT: 1835 state_name = 1836 iscsi_iscsit_tgt_state(sar->sar_state); 1837 new_state_name = 1838 iscsi_iscsit_tgt_state(sar->sar_new_state); 1839 break; 1840 case SAS_ISCSIT_SESS: 1841 state_name = 1842 iscsi_iscsit_sess_state(sar->sar_state); 1843 new_state_name = 1844 iscsi_iscsit_sess_state(sar->sar_new_state); 1845 break; 1846 case SAS_ISCSIT_LOGIN: 1847 state_name = 1848 iscsi_iscsit_login_state(sar->sar_state); 1849 new_state_name = 1850 iscsi_iscsit_login_state( 1851 sar->sar_new_state); 1852 break; 1853 case SAS_ISCSI_CMD: 1854 state_name = 1855 iscsi_iscsi_cmd_state(sar->sar_state); 1856 new_state_name= 1857 iscsi_iscsi_cmd_state(sar->sar_new_state); 1858 break; 1859 case SAS_ISCSI_SESS: 1860 state_name = 1861 iscsi_iscsi_sess_state(sar->sar_state); 1862 new_state_name= 1863 iscsi_iscsi_sess_state(sar->sar_new_state); 1864 break; 1865 case SAS_ISCSI_CONN: 1866 state_name = 1867 iscsi_iscsi_conn_state(sar->sar_state); 1868 new_state_name= 1869 iscsi_iscsi_conn_state(sar->sar_new_state); 1870 break; 1871 case SAS_ISCSI_LOGIN: 1872 state_name = 1873 iscsi_iscsi_login_state(sar->sar_state); 1874 new_state_name= 1875 iscsi_iscsi_login_state(sar->sar_new_state); 1876 break; 1877 default: 1878 break; 1879 } 1880 mdb_printf("%s|%s (%d)\n\t%9s %s (%d)\n", 1881 ts_string, state_name, sar->sar_state, 1882 "New State", new_state_name, sar->sar_new_state); 1883 default: 1884 state_name = new_state_name = "N/A"; 1885 break; 1886 } 1887 1888 audit_buf.sab_index++; 1889 audit_buf.sab_index &= audit_buf.sab_max_index; 1890 ctr--; 1891 } 1892 1893 return (DCMD_OK); 1894 } 1895 1896 static const char * 1897 iscsi_idm_conn_event(unsigned int event) 1898 { 1899 return ((event < CE_MAX_EVENT) ? idm_ce_name[event] : "N/A"); 1900 } 1901 1902 static const char * 1903 iscsi_iscsit_tgt_event(unsigned int event) 1904 { 1905 return ((event < TE_MAX_EVENT) ? iscsit_te_name[event] : "N/A"); 1906 } 1907 1908 static const char * 1909 iscsi_iscsit_sess_event(unsigned int event) 1910 { 1911 return ((event < SE_MAX_EVENT) ? iscsit_se_name[event] : "N/A"); 1912 } 1913 1914 static const char * 1915 iscsi_iscsit_login_event(unsigned int event) 1916 { 1917 return ((event < ILE_MAX_EVENT) ? iscsit_ile_name[event] : "N/A"); 1918 } 1919 1920 static const char * 1921 iscsi_iscsi_cmd_event(unsigned int event) 1922 { 1923 return ((event < ISCSI_CMD_EVENT_MAX) ? 1924 iscsi_cmd_event_names[event] : "N/A"); 1925 } 1926 1927 static const char * 1928 iscsi_iscsi_sess_event(unsigned int event) 1929 { 1930 1931 return ((event < ISCSI_SESS_EVENT_MAX) ? 1932 iscsi_sess_event_names[event] : "N/A"); 1933 } 1934 1935 static const char * 1936 iscsi_idm_conn_state(unsigned int state) 1937 { 1938 return ((state < CS_MAX_STATE) ? idm_cs_name[state] : "N/A"); 1939 } 1940 1941 /*ARGSUSED*/ 1942 static const char * 1943 iscsi_idm_task_state(unsigned int state) 1944 { 1945 return ("N/A"); 1946 } 1947 1948 static const char * 1949 iscsi_iscsit_tgt_state(unsigned int state) 1950 { 1951 return ((state < TS_MAX_STATE) ? iscsit_ts_name[state] : "N/A"); 1952 } 1953 1954 static const char * 1955 iscsi_iscsit_sess_state(unsigned int state) 1956 { 1957 return ((state < SS_MAX_STATE) ? iscsit_ss_name[state] : "N/A"); 1958 } 1959 1960 static const char * 1961 iscsi_iscsit_login_state(unsigned int state) 1962 { 1963 return ((state < ILS_MAX_STATE) ? iscsit_ils_name[state] : "N/A"); 1964 } 1965 1966 static const char * 1967 iscsi_iscsi_cmd_state(unsigned int state) 1968 { 1969 return ((state < ISCSI_CMD_STATE_MAX) ? 1970 iscsi_cmd_state_names[state] : "N/A"); 1971 } 1972 1973 static const char * 1974 iscsi_iscsi_sess_state(unsigned int state) 1975 { 1976 return ((state < ISCSI_SESS_STATE_MAX) ? 1977 iscsi_sess_state_names[state] : "N/A"); 1978 } 1979 1980 static const char * 1981 iscsi_iscsi_conn_state(unsigned int state) 1982 { 1983 return ((state < ISCSI_CONN_STATE_MAX) ? iscsi_ics_name[state] : "N/A"); 1984 } 1985 1986 static const char * 1987 iscsi_iscsi_login_state(unsigned int state) 1988 { 1989 return ((state < LOGIN_MAX) ? iscsi_login_state_names[state] : "N/A"); 1990 } 1991 1992 1993 /* 1994 * Retrieve connection type given a kernel address 1995 */ 1996 static idm_conn_type_t 1997 idm_conn_type(uintptr_t addr) 1998 { 1999 idm_conn_type_t result = 0; /* Unknown */ 2000 uintptr_t idm_conn_type_addr; 2001 2002 idm_conn_type_addr = addr + offsetof(idm_conn_t, ic_conn_type); 2003 (void) mdb_vread(&result, sizeof (result), idm_conn_type_addr); 2004 2005 return (result); 2006 } 2007 2008 /* 2009 * Convert a sockaddr to the string representation, suitable for 2010 * storing in an nvlist or printing out in a list. 2011 */ 2012 static int 2013 sa_to_str(struct sockaddr_storage *sa, char *buf) 2014 { 2015 char pbuf[7]; 2016 const char *bufp; 2017 struct sockaddr_in *sin; 2018 struct sockaddr_in6 *sin6; 2019 uint16_t port; 2020 2021 if (!sa || !buf) { 2022 return (EINVAL); 2023 } 2024 2025 buf[0] = '\0'; 2026 2027 if (sa->ss_family == AF_INET) { 2028 sin = (struct sockaddr_in *)sa; 2029 bufp = iscsi_inet_ntop(AF_INET, 2030 (const void *)&(sin->sin_addr.s_addr), 2031 buf, PORTAL_STR_LEN); 2032 if (bufp == NULL) { 2033 return (-1); 2034 } 2035 mdb_nhconvert(&port, &sin->sin_port, sizeof (uint16_t)); 2036 } else if (sa->ss_family == AF_INET6) { 2037 strlcat(buf, "[", sizeof (buf)); 2038 sin6 = (struct sockaddr_in6 *)sa; 2039 bufp = iscsi_inet_ntop(AF_INET6, 2040 (const void *)&sin6->sin6_addr.s6_addr, 2041 &buf[1], PORTAL_STR_LEN - 1); 2042 if (bufp == NULL) { 2043 return (-1); 2044 } 2045 strlcat(buf, "]", PORTAL_STR_LEN); 2046 mdb_nhconvert(&port, &sin->sin_port, sizeof (uint16_t)); 2047 } else { 2048 return (EINVAL); 2049 } 2050 2051 2052 mdb_snprintf(pbuf, sizeof (pbuf), ":%u", port); 2053 strlcat(buf, pbuf, PORTAL_STR_LEN); 2054 2055 return (0); 2056 } 2057 2058 2059 static void 2060 iscsi_format_timestamp(char *ts_str, int strlen, timespec_t *ts) 2061 { 2062 mdb_snprintf(ts_str, strlen, "%Y:%03d:%03d:%03d", ts->tv_sec, 2063 (ts->tv_nsec / 1000000) % 1000, (ts->tv_nsec / 1000) % 1000, 2064 ts->tv_nsec % 1000); 2065 } 2066 2067 /* 2068 * Help information for the iscsi_isns dcmd 2069 */ 2070 static void 2071 iscsi_isns_help(void) 2072 { 2073 mdb_printf("iscsi_isns:\n"); 2074 mdb_inc_indent(4); 2075 mdb_printf("-e: Print ESI information\n"); 2076 mdb_printf("-p: Print portal information\n"); 2077 mdb_printf("-s: Print iSNS server information\n"); 2078 mdb_printf("-t: Print target information\n"); 2079 mdb_printf("-v: Add verbosity to the other options' output\n"); 2080 mdb_dec_indent(4); 2081 } 2082 2083 /* ARGSUSED */ 2084 static int 2085 iscsi_isns_esi_cb(uintptr_t addr, const void *walker_data, void *data) 2086 { 2087 iscsi_dcmd_ctrl_t *idc = (iscsi_dcmd_ctrl_t *)data; 2088 isns_esi_tinfo_t tinfo; 2089 2090 if (mdb_vread(&tinfo, sizeof (isns_esi_tinfo_t), addr) != 2091 sizeof (isns_esi_tinfo_t)) { 2092 return (WALK_ERR); 2093 } 2094 2095 mdb_printf("ESI portal : 0x%p\n", tinfo.esi_portal); 2096 if (idc->idc_verbose) { 2097 mdb_inc_indent(4); 2098 iscsi_isns_portal_cb((uintptr_t)tinfo.esi_portal, NULL, data); 2099 mdb_dec_indent(4); 2100 } 2101 mdb_printf("ESI thread/thr did : 0x%p / %d\n", tinfo.esi_thread, 2102 tinfo.esi_thread_did); 2103 mdb_printf("ESI sonode : 0x%p\n", tinfo.esi_so); 2104 mdb_printf("ESI port : %d\n", tinfo.esi_port); 2105 mdb_printf("ESI thread running : %s\n", 2106 (tinfo.esi_thread_running) ? "Yes" : "No"); 2107 if (!tinfo.esi_thread_running) { 2108 mdb_printf("ESI thread failed : %s\n", 2109 (tinfo.esi_thread_failed) ? "Yes" : "No"); 2110 } 2111 mdb_printf("ESI registered : %s\n\n", 2112 (tinfo.esi_registered) ? "Yes" : "No"); 2113 2114 return (WALK_NEXT); 2115 } 2116 2117 static int 2118 iscsi_isns_esi(iscsi_dcmd_ctrl_t *idc) 2119 { 2120 GElf_Sym sym; 2121 uintptr_t esi_list; 2122 2123 if (mdb_lookup_by_name("esi_list", &sym) == -1) { 2124 mdb_warn("failed to find symbol 'esi_list'"); 2125 return (DCMD_ERR); 2126 } 2127 2128 esi_list = (uintptr_t)sym.st_value; 2129 idc->idc_header = 1; 2130 2131 if (mdb_pwalk("list", iscsi_isns_esi_cb, idc, esi_list) == -1) { 2132 mdb_warn("avl walk failed for esi_list"); 2133 return (DCMD_ERR); 2134 } 2135 2136 return (0); 2137 } 2138 2139 /* ARGSUSED */ 2140 static int 2141 iscsi_isns_portal_cb(uintptr_t addr, const void *walker_data, void *data) 2142 { 2143 iscsi_dcmd_ctrl_t *idc = (iscsi_dcmd_ctrl_t *)data; 2144 isns_portal_list_t portal; 2145 char portal_addr[PORTAL_STR_LEN]; 2146 struct sockaddr_storage *ss; 2147 2148 if (mdb_vread(&portal, sizeof (isns_portal_list_t), addr) != 2149 sizeof (isns_portal_list_t)) { 2150 return (WALK_ERR); 2151 } 2152 2153 ss = &portal.portal_addr; 2154 sa_to_str(ss, portal_addr); 2155 mdb_printf("Portal IP address "); 2156 2157 if (ss->ss_family == AF_INET) { 2158 mdb_printf("(v4): %s", portal_addr); 2159 } else { 2160 mdb_printf("(v6): %s", portal_addr); 2161 } 2162 2163 if (portal.portal_iscsit == NULL) { 2164 mdb_printf(" (Default portal)\n"); 2165 } else { 2166 mdb_printf("\n"); 2167 } 2168 2169 if ((portal.portal_iscsit != NULL) && (idc->idc_verbose)) { 2170 iscsi_portal_impl((uintptr_t)portal.portal_iscsit, idc); 2171 } 2172 2173 mdb_printf("Portal ESI info: 0x%p\n\n", portal.portal_esi); 2174 2175 return (WALK_NEXT); 2176 } 2177 2178 static int 2179 iscsi_isns_portals(iscsi_dcmd_ctrl_t *idc) 2180 { 2181 GElf_Sym sym; 2182 uintptr_t portal_list; 2183 2184 if (mdb_lookup_by_name("portal_list", &sym) == -1) { 2185 mdb_warn("failed to find symbol 'portal_list'"); 2186 return (DCMD_ERR); 2187 } 2188 2189 portal_list = (uintptr_t)sym.st_value; 2190 idc->idc_header = 1; 2191 2192 if (mdb_pwalk("list", iscsi_isns_portal_cb, idc, portal_list) == -1) { 2193 mdb_warn("avl walk failed for portal_list"); 2194 return (DCMD_ERR); 2195 } 2196 2197 return (0); 2198 } 2199 2200 /* ARGSUSED */ 2201 static int 2202 iscsi_isns_targets_cb(uintptr_t addr, const void *walker_data, void *data) 2203 { 2204 iscsi_dcmd_ctrl_t *idc = (iscsi_dcmd_ctrl_t *)data; 2205 isns_target_t itarget; 2206 int rc = 0; 2207 2208 if (mdb_vread(&itarget, sizeof (isns_target_t), addr) != 2209 sizeof (isns_target_t)) { 2210 return (WALK_ERR); 2211 } 2212 2213 idc->idc_header = 1; 2214 2215 mdb_printf("Target: %p\n", itarget.target); 2216 mdb_inc_indent(4); 2217 mdb_printf("Registered: %s\n", 2218 (itarget.target_registered) ? "Yes" : "No"); 2219 2220 rc = iscsi_tgt_impl((uintptr_t)itarget.target, idc); 2221 2222 mdb_dec_indent(4); 2223 2224 if (rc == DCMD_OK) { 2225 return (WALK_NEXT); 2226 } 2227 2228 return (WALK_ERR); 2229 } 2230 2231 static int 2232 iscsi_isns_targets(iscsi_dcmd_ctrl_t *idc) 2233 { 2234 GElf_Sym sym; 2235 uintptr_t isns_target_list; 2236 2237 if (mdb_lookup_by_name("isns_target_list", &sym) == -1) { 2238 mdb_warn("failed to find symbol 'isns_target_list'"); 2239 return (DCMD_ERR); 2240 } 2241 2242 isns_target_list = (uintptr_t)sym.st_value; 2243 idc->idc_header = 1; 2244 idc->u.child.idc_tgt = 1; 2245 2246 if (mdb_pwalk("avl", iscsi_isns_targets_cb, idc, 2247 isns_target_list) == -1) { 2248 mdb_warn("avl walk failed for isns_target_list"); 2249 return (DCMD_ERR); 2250 } 2251 2252 return (0); 2253 } 2254 2255 /* ARGSUSED */ 2256 static int 2257 iscsi_isns_servers_cb(uintptr_t addr, const void *walker_data, void *data) 2258 { 2259 GElf_Sym sym; 2260 iscsit_isns_svr_t server; 2261 char server_addr[PORTAL_STR_LEN]; 2262 struct sockaddr_storage *ss; 2263 clock_t lbolt; 2264 2265 if (mdb_vread(&server, sizeof (iscsit_isns_svr_t), addr) != 2266 sizeof (iscsit_isns_svr_t)) { 2267 return (WALK_ERR); 2268 } 2269 2270 if (mdb_lookup_by_name("lbolt", &sym) == -1) { 2271 mdb_warn("failed to find symbol 'lbolt'"); 2272 return (DCMD_ERR); 2273 } 2274 2275 if (mdb_vread(&lbolt, sizeof (clock_t), sym.st_value) != 2276 sizeof (clock_t)) { 2277 return (WALK_ERR); 2278 } 2279 2280 mdb_printf("iSNS server %p:\n", addr); 2281 mdb_inc_indent(4); 2282 ss = &server.svr_sa; 2283 sa_to_str(ss, server_addr); 2284 2285 mdb_printf("IP address "); 2286 if (ss->ss_family == AF_INET) { 2287 mdb_printf("(v4): %s\n", server_addr); 2288 } else { 2289 mdb_printf("(v6): %s\n", server_addr); 2290 } 2291 2292 mdb_printf("Last ESI message : %d seconds ago\n", 2293 ((lbolt - server.svr_last_msg) / 100)); 2294 mdb_printf("Client registered: %s\n", 2295 (server.svr_registered) ? "Yes" : "No"); 2296 mdb_dec_indent(4); 2297 2298 return (WALK_ERR); 2299 } 2300 2301 static int 2302 iscsi_isns_servers(iscsi_dcmd_ctrl_t *idc) 2303 { 2304 uintptr_t iscsit_global_addr; 2305 uintptr_t list_addr; 2306 GElf_Sym sym; 2307 2308 if (mdb_lookup_by_name("iscsit_global", &sym) == -1) { 2309 mdb_warn("failed to find symbol 'iscsit_global'"); 2310 return (DCMD_ERR); 2311 } 2312 2313 iscsit_global_addr = (uintptr_t)sym.st_value; 2314 idc->idc_header = 1; 2315 list_addr = iscsit_global_addr + 2316 offsetof(iscsit_global_t, global_isns_cfg.isns_svrs); 2317 2318 if (mdb_pwalk("list", iscsi_isns_servers_cb, idc, list_addr) == -1) { 2319 mdb_warn("list walk failed for iSNS servers"); 2320 return (DCMD_ERR); 2321 } 2322 2323 return (0); 2324 } 2325 2326 /* ARGSUSED */ 2327 static int 2328 iscsi_isns(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2329 { 2330 iscsi_dcmd_ctrl_t idc; 2331 int portals = 0, esi = 0, targets = 0, verbose = 0, servers = 0; 2332 2333 if (flags & DCMD_ADDRSPEC) { 2334 mdb_warn("iscsi_isns is only a global dcmd."); 2335 return (DCMD_ERR); 2336 } 2337 2338 bzero(&idc, sizeof (idc)); 2339 if (mdb_getopts(argc, argv, 2340 'e', MDB_OPT_SETBITS, TRUE, &esi, 2341 'p', MDB_OPT_SETBITS, TRUE, &portals, 2342 's', MDB_OPT_SETBITS, TRUE, &servers, 2343 't', MDB_OPT_SETBITS, TRUE, &targets, 2344 'v', MDB_OPT_SETBITS, TRUE, &verbose, 2345 NULL) != argc) 2346 return (DCMD_USAGE); 2347 2348 if ((esi + portals + targets + servers) > 1) { 2349 mdb_printf("Only one of e, p, s, and t must be provided"); 2350 return (DCMD_ERR); 2351 } 2352 2353 if ((esi | portals | targets | servers) == 0) { 2354 mdb_printf("Exactly one of e, p, s, or t must be provided"); 2355 return (DCMD_ERR); 2356 } 2357 2358 idc.idc_verbose = verbose; 2359 2360 if (esi) { 2361 return (iscsi_isns_esi(&idc)); 2362 } 2363 2364 if (portals) { 2365 return (iscsi_isns_portals(&idc)); 2366 } 2367 2368 if (servers) { 2369 return (iscsi_isns_servers(&idc)); 2370 } 2371 2372 return (iscsi_isns_targets(&idc)); 2373 } 2374 2375 /* 2376 * iscsi_inet_ntop -- Convert an IPv4 or IPv6 address in binary form into 2377 * printable form, and return a pointer to that string. Caller should 2378 * provide a buffer of correct length to store string into. 2379 * Note: this routine is kernel version of inet_ntop. It has similar 2380 * format as iscsi_inet_ntop() defined in rfc2553. But it does not do 2381 * error handling operations exactly as rfc2553 defines. This function 2382 * is used by kernel inet directory routines only for debugging. 2383 * This iscsi_inet_ntop() function, does not return NULL if third argument 2384 * is NULL. The reason is simple that we don't want kernel to panic 2385 * as the output of this function is directly fed to ip<n>dbg macro. 2386 * Instead it uses a local buffer for destination address for 2387 * those calls which purposely pass NULL ptr for the destination 2388 * buffer. This function is thread-safe when the caller passes a non- 2389 * null buffer with the third argument. 2390 */ 2391 /* ARGSUSED */ 2392 2393 #define OK_16PTR(p) (!((uintptr_t)(p) & 0x1)) 2394 #if defined(__x86) 2395 #define OK_32PTR(p) OK_16PTR(p) 2396 #else 2397 #define OK_32PTR(p) (!((uintptr_t)(p) & 0x3)) 2398 #endif 2399 2400 char * 2401 iscsi_inet_ntop(int af, const void *addr, char *buf, int addrlen) 2402 { 2403 static char local_buf[PORTAL_STR_LEN]; 2404 static char *err_buf1 = "<badaddr>"; 2405 static char *err_buf2 = "<badfamily>"; 2406 in6_addr_t *v6addr; 2407 uchar_t *v4addr; 2408 char *caddr; 2409 2410 /* 2411 * We don't allow thread unsafe iscsi_inet_ntop calls, they 2412 * must pass a non-null buffer pointer. For DEBUG mode 2413 * we use the ASSERT() and for non-debug kernel it will 2414 * silently allow it for now. Someday we should remove 2415 * the static buffer from this function. 2416 */ 2417 2418 ASSERT(buf != NULL); 2419 if (buf == NULL) 2420 buf = local_buf; 2421 buf[0] = '\0'; 2422 2423 /* Let user know politely not to send NULL or unaligned addr */ 2424 if (addr == NULL || !(OK_32PTR(addr))) { 2425 return (err_buf1); 2426 } 2427 2428 2429 #define UC(b) (((int)b) & 0xff) 2430 switch (af) { 2431 case AF_INET: 2432 ASSERT(addrlen >= INET_ADDRSTRLEN); 2433 v4addr = (uchar_t *)addr; 2434 (void) mdb_snprintf(buf, INET6_ADDRSTRLEN, 2435 "%03d.%03d.%03d.%03d", 2436 UC(v4addr[0]), UC(v4addr[1]), UC(v4addr[2]), UC(v4addr[3])); 2437 return (buf); 2438 2439 case AF_INET6: 2440 ASSERT(addrlen >= INET6_ADDRSTRLEN); 2441 v6addr = (in6_addr_t *)addr; 2442 if (IN6_IS_ADDR_V4MAPPED(v6addr)) { 2443 caddr = (char *)addr; 2444 (void) mdb_snprintf(buf, INET6_ADDRSTRLEN, 2445 "::ffff:%d.%d.%d.%d", 2446 UC(caddr[12]), UC(caddr[13]), 2447 UC(caddr[14]), UC(caddr[15])); 2448 } else if (IN6_IS_ADDR_V4COMPAT(v6addr)) { 2449 caddr = (char *)addr; 2450 (void) mdb_snprintf(buf, INET6_ADDRSTRLEN, 2451 "::%d.%d.%d.%d", 2452 UC(caddr[12]), UC(caddr[13]), UC(caddr[14]), 2453 UC(caddr[15])); 2454 } else if (IN6_IS_ADDR_UNSPECIFIED(v6addr)) { 2455 (void) mdb_snprintf(buf, INET6_ADDRSTRLEN, "::"); 2456 } else { 2457 convert2ascii(buf, v6addr); 2458 } 2459 return (buf); 2460 2461 default: 2462 return (err_buf2); 2463 } 2464 #undef UC 2465 } 2466 2467 /* 2468 * 2469 * v6 formats supported 2470 * General format xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx 2471 * The short hand notation :: is used for COMPAT addr 2472 * Other forms : fe80::xxxx:xxxx:xxxx:xxxx 2473 */ 2474 static void 2475 convert2ascii(char *buf, const in6_addr_t *addr) 2476 { 2477 int hexdigits; 2478 int head_zero = 0; 2479 int tail_zero = 0; 2480 /* tempbuf must be big enough to hold ffff:\0 */ 2481 char tempbuf[6]; 2482 char *ptr; 2483 uint16_t out_addr_component; 2484 uint16_t *addr_component; 2485 size_t len; 2486 boolean_t first = B_FALSE; 2487 boolean_t med_zero = B_FALSE; 2488 boolean_t end_zero = B_FALSE; 2489 2490 addr_component = (uint16_t *)addr; 2491 ptr = buf; 2492 2493 /* First count if trailing zeroes higher in number */ 2494 for (hexdigits = 0; hexdigits < 8; hexdigits++) { 2495 if (*addr_component == 0) { 2496 if (hexdigits < 4) 2497 head_zero++; 2498 else 2499 tail_zero++; 2500 } 2501 addr_component++; 2502 } 2503 addr_component = (uint16_t *)addr; 2504 if (tail_zero > head_zero && (head_zero + tail_zero) != 7) 2505 end_zero = B_TRUE; 2506 2507 for (hexdigits = 0; hexdigits < 8; hexdigits++) { 2508 2509 /* if entry is a 0 */ 2510 2511 if (*addr_component == 0) { 2512 if (!first && *(addr_component + 1) == 0) { 2513 if (end_zero && (hexdigits < 4)) { 2514 *ptr++ = '0'; 2515 *ptr++ = ':'; 2516 } else { 2517 /* 2518 * address starts with 0s .. 2519 * stick in leading ':' of pair 2520 */ 2521 if (hexdigits == 0) 2522 *ptr++ = ':'; 2523 /* add another */ 2524 *ptr++ = ':'; 2525 first = B_TRUE; 2526 med_zero = B_TRUE; 2527 } 2528 } else if (first && med_zero) { 2529 if (hexdigits == 7) 2530 *ptr++ = ':'; 2531 addr_component++; 2532 continue; 2533 } else { 2534 *ptr++ = '0'; 2535 *ptr++ = ':'; 2536 } 2537 addr_component++; 2538 continue; 2539 } 2540 if (med_zero) 2541 med_zero = B_FALSE; 2542 2543 tempbuf[0] = '\0'; 2544 mdb_nhconvert(&out_addr_component, addr_component, 2545 sizeof (uint16_t)); 2546 (void) mdb_snprintf(tempbuf, 6, "%x:", out_addr_component); 2547 len = strlen(tempbuf); 2548 bcopy(tempbuf, ptr, len); 2549 ptr = ptr + len; 2550 addr_component++; 2551 } 2552 *--ptr = '\0'; 2553 } 2554 2555 2556 /* 2557 * MDB module linkage information: 2558 * 2559 * We declare a list of structures describing our dcmds, a list of structures 2560 * describing our walkers and a function named _mdb_init to return a pointer 2561 * to our module information. 2562 */ 2563 static const mdb_dcmd_t dcmds[] = { 2564 { "iscsi_tgt", "[-agsctbSRv]", 2565 "iSCSI target information", iscsi_tgt }, 2566 { "iscsi_tpg", "[-v]", 2567 "iSCSI target portal group information", iscsi_tpg }, 2568 { "iscsi_sess", "[-abtvcSRIT]", 2569 "iSCSI session information", iscsi_sess }, 2570 { "iscsi_conn", "[-abtvSRIT]", 2571 "iSCSI connection information", iscsi_conn }, 2572 { "iscsi_task", "[-bSRv]", 2573 "iSCSI task information", iscsi_task }, 2574 { "iscsi_refcnt", "", 2575 "Print audit informtion for idm_refcnt_t", iscsi_refcnt }, 2576 { "iscsi_states", "", 2577 "Dump events and state transitions recorded in an\t" 2578 "\t\tidm_sm_audit_t structure", iscsi_states }, 2579 { "iscsi_isns", "[-epstv]", 2580 "Print iscsit iSNS information", iscsi_isns, iscsi_isns_help }, 2581 { NULL } 2582 }; 2583 2584 /* 2585 * No walkers for now. Initiator might need some since it doesn't use list_t 2586 */ 2587 2588 static const mdb_modinfo_t modinfo = { 2589 MDB_API_VERSION, dcmds, NULL 2590 }; 2591 2592 const mdb_modinfo_t * 2593 _mdb_init(void) 2594 { 2595 return (&modinfo); 2596 } 2597