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