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