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