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/cpuvar.h> 27 #include <sys/types.h> 28 #include <sys/conf.h> 29 #include <sys/file.h> 30 #include <sys/ddi.h> 31 #include <sys/sunddi.h> 32 #include <sys/socket.h> 33 #include <inet/tcp.h> 34 #include <sys/sdt.h> 35 36 #include <sys/stmf.h> 37 #include <sys/stmf_ioctl.h> 38 #include <sys/portif.h> 39 #include <sys/idm/idm.h> 40 #include <sys/idm/idm_so.h> 41 #include <sys/iscsit/iscsit_common.h> 42 #include <sys/iscsit/isns_protocol.h> 43 #include <iscsit.h> 44 #include <iscsit_isns.h> 45 #include <sys/ksocket.h> 46 47 /* 48 * iscsit_isns.c -- isns client that is part of the iscsit server 49 * 50 * The COMSTAR iSCSI target uses four pieces of iSNS functionality: 51 * - DevAttrReg to notify the iSNS server of our targets and portals. 52 * - DeregDev to notify when a target goes away or we shut down 53 * - DevAttrQry (self-query) to see if iSNS server still knows us. 54 * - Request ESI probes from iSNS server as a keepalive mechanism 55 * 56 * We send only two kinds of DevAttrReg messages. 57 * 58 * REPLACE-ALL the info the iSNS server knows about us: 59 * Set Flag in PDU header to ISNS_FLAG_REPLACE_REG 60 * Set "source" to same iSCSI target each time 61 * EID (Entity Identifier) == our DNS name 62 * "Delimiter" 63 * Object operated on = EID 64 * "Entity Portals" owned by this "network entity" 65 * List of targets 66 * (Targets with TPGT are followed by PGT and PG portal info) 67 * 68 * UPDATE-EXISTING - used to register/change one target at a time 69 * Flag for replace reg not set 70 * Source and EID and Delimiter and Object Operated On as above 71 * Single Target 72 * (Targets with TPGT are followed by PGT and PG portal info) 73 * 74 * Interfaces to iscsit 75 * 76 * iscsit_isns_init -- called when iscsi/target service goes online 77 * iscsit_isns_fini -- called when iscsi/target service goes offline 78 * iscsit_isns_register -- a new target comes online 79 * iscsit_isns_deregister -- target goes offline 80 * iscsit_isns_target_update -- called when a target is modified 81 * iscsit_isns_portal_online -- called when defining a new portal 82 * iscsit_isns_portal_offline -- no longer using a portal 83 * 84 * Copying Data Structures 85 * 86 * The above routines copy all the data they need, so iscsit can 87 * proceed without interfering with us. This is moving in the 88 * direction of having this isns_client be a standalone user-mode 89 * program. Specifically, we copy the target name, alias, and 90 * tpgt+portal information. 91 * 92 * The iscsit_isns_mutex protects the shadow copies of target and portal 93 * information. The ISNS_GLOBAL_LOCK protects the iSNS run time structures 94 * that the monitor thread uses. The routine isnst_copy_global_status_changes 95 * has to acquire both locks and copy all the required information from the 96 * global structs to the per-server structs. Once it completes, the monitor 97 * thread should run completely off the per-server copies. 98 * 99 * Global State vs Per-Server state 100 * There is a global list of targets and portals that is kept updated 101 * by iscsit. Each svr keeps its own list of targets that have been 102 * announced to the iSNS server. 103 * 104 * Invariants 105 * 106 * 1) If svr->svr_registered, then there is some itarget with 107 * itarget->target_registered. 108 * 2) If itarget->target_delete_needed, then also itarget->target_registered. 109 * (Corollary: Any time you remove the last registered target, you have 110 * to send an unregister-all message.) 111 * 3) If a target has a non-default portal, then the portal goes online 112 * before the target goes online, and comes offline afterwards. 113 * (This is enforced by the iscsit state machines.) 114 */ 115 /* local defines */ 116 #define MAX_XID (2^16) 117 #define ISNS_IDLE_TIME 60 118 #define MAX_RETRY (3) 119 #define ISNS_RCV_TIMER_SECONDS 5 120 121 #define VALID_NAME(NAME, LEN) \ 122 ((LEN) > 0 && (NAME)[0] != 0 && (NAME)[(LEN) - 1] == 0) 123 124 125 #define ISNST_LOG if (iscsit_isns_logging) cmn_err 126 127 static kmutex_t isns_monitor_mutex; 128 volatile kthread_t *isns_monitor_thr_id; 129 static kt_did_t isns_monitor_thr_did; 130 static boolean_t isns_monitor_thr_running; 131 132 static kcondvar_t isns_idle_cv; 133 134 static uint16_t xid; 135 #define GET_XID() atomic_inc_16_nv(&xid) 136 137 static clock_t monitor_idle_interval; 138 139 /* The ISNS_GLOBAL_LOCK protects the per-server data structures */ 140 #define ISNS_GLOBAL_LOCK() \ 141 mutex_enter(&iscsit_global.global_isns_cfg.isns_mutex) 142 143 #define ISNS_GLOBAL_LOCK_HELD() \ 144 MUTEX_HELD(&iscsit_global.global_isns_cfg.isns_mutex) 145 146 #define ISNS_GLOBAL_UNLOCK() \ 147 mutex_exit(&iscsit_global.global_isns_cfg.isns_mutex) 148 149 /* 150 * "Configurable" parameters (set in /etc/system for now). 151 */ 152 boolean_t iscsit_isns_logging = B_FALSE; 153 154 155 /* 156 * If fail this many times to send an update to the server, then 157 * declare the server non-responsive and reregister everything with 158 * the server when we next connect. 159 */ 160 int isns_max_retry = MAX_RETRY; 161 162 /* 163 * The use of ESI probes to all active portals is not appropriate in 164 * all network environments, since the iSNS server may not have 165 * connectivity to all portals, so we turn it off by default. 166 */ 167 boolean_t isns_use_esi = B_FALSE; 168 169 /* 170 * Interval to request ESI probes at, in seconds. The server is free 171 * to specify a different frequency in its response. 172 */ 173 int isns_default_esi_interval = ISNS_DEFAULT_ESI_INTERVAL; 174 175 176 /* 177 * Registration Period -- we guarantee to check in with iSNS server at 178 * least this often. Used when ESI probes are turned off. 179 */ 180 int isns_registration_period = ISNS_DEFAULT_REGISTRATION_PERIOD; 181 182 /* 183 * Socket connect, PDU receive, and PDU send must complete 184 * within this number of microseconds. 185 */ 186 uint32_t isns_timeout_usec = ISNS_RCV_TIMER_SECONDS * 1000000; 187 188 189 /* 190 * iSNS Message size -- we start with the max that can fit into one PDU. 191 * If the message doesn't fit, we will expand at run time to a higher 192 * value. This parameter could be set in /etc/system if some particular 193 * installation knows it always goes over the standard limit. 194 */ 195 uint32_t isns_message_buf_size = ISNSP_MAX_PDU_SIZE; 196 197 /* 198 * Number of seconds to wait after isnst_monitor thread starts up 199 * before sending first DevAttrReg message. 200 */ 201 int isns_initial_delay = ISNS_INITIAL_DELAY; 202 203 /* 204 * Because of a bug in the isns server, we cannot send a modify 205 * operation that changes the target's TPGTs. So just replace all. 206 * If the iSNS server does not have this bug, clear this flag. 207 * Changes take effect on each modify_target operation 208 */ 209 boolean_t isns_modify_must_replace = B_TRUE; 210 211 /* If PDU sizes ever go over the following, we need to rearchitect */ 212 #define ISNST_MAX_MSG_SIZE (16 * ISNSP_MAX_PDU_SIZE) 213 214 /* 215 * iSNS ESI thread state 216 */ 217 static isns_esi_tinfo_t esi; 218 219 /* 220 * Our list of targets. Kept in lock-step synch with iscsit. 221 * The iscsit_isns_mutex protects the global data structures that are 222 * kept in lock-step with iscsit. 223 * NOTE: Now that isnst runs independently of iscsit, we could remove the 224 * shadow copies of iscsit structures, such as isns_target_list and 225 * isns_tpg_portals, and have isnst_copy_global_status_changes reconcile 226 * isnst directly with the iscsit data structures. 227 */ 228 static kmutex_t iscsit_isns_mutex; 229 static avl_tree_t isns_target_list; 230 static boolean_t isns_targets_changed; 231 232 /* 233 * List of portals from TPGs. Protected by iscsit_isns_mutex. 234 */ 235 static boolean_t isns_portals_changed; 236 static avl_tree_t isns_tpg_portals; 237 static boolean_t default_portal_online; 238 239 /* List of all portals. Protected by ISNS_GLOBAL_LOCK */ 240 static avl_tree_t isns_all_portals; 241 static int num_default_portals; 242 static int num_tpg_portals; 243 244 /* 245 * Our entity identifier (fully-qualified hostname). Passed in from libiscsit. 246 */ 247 static char *isns_eid = NULL; 248 249 /* 250 * in6addr_any is currently all zeroes, but use the macro in case this 251 * ever changes. 252 */ 253 static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; 254 255 static void 256 isnst_start(); 257 258 static void 259 isnst_stop(); 260 261 static void 262 iscsit_set_isns(boolean_t state); 263 264 static void 265 iscsit_add_isns(it_portal_t *cfg_svr); 266 267 static void 268 isnst_mark_delete_isns(iscsit_isns_svr_t *svr); 269 270 static void 271 isnst_finish_delete_isns(iscsit_isns_svr_t *svr); 272 273 static iscsit_isns_svr_t * 274 iscsit_isns_svr_lookup(struct sockaddr_storage *sa); 275 276 static void 277 isnst_monitor(void *arg); 278 279 static int 280 isnst_monitor_one_server(iscsit_isns_svr_t *svr, boolean_t enabled); 281 282 static void 283 isnst_monitor_awaken(void); 284 285 static boolean_t 286 isnst_update_server_timestamp(struct sockaddr_storage *sa); 287 288 static void 289 isnst_copy_global_status_changes(void); 290 291 static void 292 isnst_mark_deleted_targets(iscsit_isns_svr_t *svr); 293 294 static int 295 isnst_update_one_server(iscsit_isns_svr_t *svr, isns_target_t *target, 296 isns_reg_type_t reg); 297 298 static boolean_t isnst_retry_registration(int rsp_status_code); 299 300 static int isnst_register(iscsit_isns_svr_t *svr, isns_target_t *itarget, 301 isns_reg_type_t regtype); 302 static int isnst_deregister(iscsit_isns_svr_t *svr, isns_target_t *itarget); 303 304 static size_t 305 isnst_make_dereg_pdu(iscsit_isns_svr_t *svr, isns_pdu_t **pdu, 306 isns_target_t *itarge); 307 308 static int isnst_keepalive(iscsit_isns_svr_t *svr); 309 static size_t 310 isnst_make_keepalive_pdu(iscsit_isns_svr_t *svr, isns_pdu_t **pdu); 311 312 static isns_target_t *isnst_get_registered_source(iscsit_isns_svr_t *srv); 313 314 static int 315 isnst_verify_rsp(iscsit_isns_svr_t *svr, isns_pdu_t *pdu, 316 isns_pdu_t *rsp, size_t rsp_size); 317 318 static uint16_t 319 isnst_pdu_get_op(isns_pdu_t *pdu, uint8_t **pp); 320 321 static size_t 322 isnst_make_reg_pdu(isns_pdu_t **pdu, isns_target_t *target, 323 iscsit_isns_svr_t *svr, isns_reg_type_t regtype); 324 325 static int 326 isnst_reg_pdu_add_entity_portals(isns_pdu_t *pdu, size_t pdu_size); 327 328 static int 329 isnst_reg_pdu_add_pg(isns_pdu_t *pdu, size_t pdu_size, isns_target_t *target); 330 331 static int 332 isnst_add_default_pg(isns_pdu_t *pdu, size_t pdu_size, 333 avl_tree_t *null_portal_list); 334 335 static int 336 isnst_add_tpg_pg(isns_pdu_t *pdu, size_t pdu_size, 337 isns_tpgt_t *tig, avl_tree_t *null_portal_list); 338 339 static int 340 isnst_add_null_pg(isns_pdu_t *pdu, size_t pdu_size, 341 avl_tree_t *null_portal_list); 342 343 static int 344 isnst_add_portal_attr(isns_pdu_t *pdu, size_t pdu_size, 345 uint32_t ip_attr_id, uint32_t port_attr_id, 346 struct sockaddr_storage *ss, boolean_t esi_info); 347 348 static size_t 349 isnst_create_pdu_header(uint16_t func_id, isns_pdu_t **pdu, uint16_t flags); 350 351 static int 352 isnst_add_attr(isns_pdu_t *pdu, 353 size_t max_pdu_size, 354 uint32_t attr_id, 355 uint32_t attr_len, 356 void *attr_data, 357 uint32_t attr_numeric_data); 358 359 static int 360 isnst_send_pdu(void *so, isns_pdu_t *pdu); 361 362 static size_t 363 isnst_rcv_pdu(void *so, isns_pdu_t **pdu); 364 365 static void * 366 isnst_open_so(struct sockaddr_storage *sa); 367 368 static void 369 isnst_close_so(void *); 370 371 static void 372 isnst_esi_thread(void *arg); 373 374 static void 375 isnst_handle_esi_req(ksocket_t so, isns_pdu_t *pdu, size_t pl_size); 376 377 static void isnst_esi_start(void); 378 static void isnst_esi_stop(void); 379 static isns_target_t *isnst_latch_to_target_list(isns_target_t *target, 380 avl_tree_t *list); 381 static void isnst_clear_target_list(iscsit_isns_svr_t *svr); 382 static void isnst_clear_from_target_list(isns_target_t *target, 383 avl_tree_t *target_list); 384 static int isnst_tgt_avl_compare(const void *t1, const void *t2); 385 static void isnst_set_server_status(iscsit_isns_svr_t *svr, 386 boolean_t registered); 387 static void isnst_monitor_start(void); 388 static void isnst_monitor_stop(void); 389 390 static void 391 isnst_monitor_default_portal_list(void); 392 393 static int 394 isnst_find_default_portals(idm_addr_list_t *alist); 395 396 static int 397 isnst_add_default_portals(idm_addr_list_t *alist); 398 399 static void 400 isnst_clear_default_portals(void); 401 402 403 static void 404 isnst_clear_portal_list(avl_tree_t *portal_list); 405 406 static void 407 isnst_copy_portal_list(avl_tree_t *t1, avl_tree_t *t2); 408 409 static isns_portal_t * 410 isnst_lookup_portal(struct sockaddr_storage *sa); 411 412 static isns_portal_t * 413 isnst_add_to_portal_list(struct sockaddr_storage *sa, avl_tree_t *portal_list); 414 415 static void 416 isnst_remove_from_portal_list(struct sockaddr_storage *sa, 417 avl_tree_t *portal_list); 418 419 static int 420 isnst_portal_avl_compare(const void *t1, const void *t2); 421 422 423 424 425 426 427 it_cfg_status_t 428 isnst_config_merge(it_config_t *cfg) 429 { 430 boolean_t new_isns_state = B_FALSE; 431 iscsit_isns_svr_t *isns_svr, *next_isns_svr; 432 it_portal_t *cfg_isns_svr; 433 434 ISNS_GLOBAL_LOCK(); 435 436 /* 437 * Determine whether iSNS is enabled in the new config. 438 * Isns property may not be set up yet. 439 */ 440 (void) nvlist_lookup_boolean_value(cfg->config_global_properties, 441 PROP_ISNS_ENABLED, &new_isns_state); 442 443 /* Delete iSNS servers that are no longer part of the config */ 444 for (isns_svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs); 445 isns_svr != NULL; 446 isns_svr = next_isns_svr) { 447 next_isns_svr = list_next( 448 &iscsit_global.global_isns_cfg.isns_svrs, isns_svr); 449 if (it_sns_svr_lookup(cfg, &isns_svr->svr_sa) == NULL) 450 isnst_mark_delete_isns(isns_svr); 451 } 452 453 /* Add new iSNS servers */ 454 for (cfg_isns_svr = cfg->config_isns_svr_list; 455 cfg_isns_svr != NULL; 456 cfg_isns_svr = cfg_isns_svr->next) { 457 isns_svr = iscsit_isns_svr_lookup(&cfg_isns_svr->portal_addr); 458 if (isns_svr == NULL) { 459 iscsit_add_isns(cfg_isns_svr); 460 } else if (isns_svr->svr_delete_needed) { 461 /* 462 * If reactivating a server that was being 463 * deleted, turn it into a reset. 464 */ 465 isns_svr->svr_delete_needed = B_FALSE; 466 isns_svr->svr_reset_needed = B_TRUE; 467 } 468 } 469 470 /* 471 * There is no "modify case" since the user specifies a complete 472 * server list each time. A modify is the same as a remove+add. 473 */ 474 475 /* Start/Stop iSNS if necessary */ 476 iscsit_set_isns(new_isns_state); 477 478 ISNS_GLOBAL_UNLOCK(); 479 480 481 /* Wake up the monitor thread to complete the state change */ 482 isnst_monitor_awaken(); 483 484 return (0); 485 } 486 487 int 488 iscsit_isns_init(iscsit_hostinfo_t *hostinfo) 489 { 490 mutex_init(&iscsit_global.global_isns_cfg.isns_mutex, NULL, 491 MUTEX_DEFAULT, NULL); 492 493 ISNS_GLOBAL_LOCK(); 494 mutex_init(&iscsit_isns_mutex, NULL, MUTEX_DEFAULT, NULL); 495 496 iscsit_global.global_isns_cfg.isns_state = B_FALSE; 497 list_create(&iscsit_global.global_isns_cfg.isns_svrs, 498 sizeof (iscsit_isns_svr_t), offsetof(iscsit_isns_svr_t, svr_ln)); 499 avl_create(&isns_tpg_portals, isnst_portal_avl_compare, 500 sizeof (isns_portal_t), offsetof(isns_portal_t, portal_node)); 501 avl_create(&isns_all_portals, isnst_portal_avl_compare, 502 sizeof (isns_portal_t), offsetof(isns_portal_t, portal_node)); 503 num_default_portals = 0; 504 if (hostinfo->length > ISCSIT_MAX_HOSTNAME_LEN) 505 hostinfo->length = ISCSIT_MAX_HOSTNAME_LEN; 506 isns_eid = kmem_alloc(hostinfo->length, KM_SLEEP); 507 (void) strlcpy(isns_eid, hostinfo->fqhn, hostinfo->length); 508 avl_create(&isns_target_list, isnst_tgt_avl_compare, 509 sizeof (isns_target_t), offsetof(isns_target_t, target_node)); 510 511 /* initialize isns client */ 512 mutex_init(&isns_monitor_mutex, NULL, MUTEX_DEFAULT, NULL); 513 mutex_init(&esi.esi_mutex, NULL, MUTEX_DEFAULT, NULL); 514 isns_monitor_thr_id = NULL; 515 monitor_idle_interval = ISNS_IDLE_TIME * drv_usectohz(1000000); 516 cv_init(&isns_idle_cv, NULL, CV_DEFAULT, NULL); 517 cv_init(&esi.esi_cv, NULL, CV_DEFAULT, NULL); 518 xid = 0; 519 ISNS_GLOBAL_UNLOCK(); 520 521 return (0); 522 } 523 524 void 525 iscsit_isns_fini() 526 { 527 ISNS_GLOBAL_LOCK(); 528 529 /* 530 * The following call to iscsit_set_isns waits until all the 531 * iSNS servers have been fully deactivated and the monitor and esi 532 * threads have stopped. 533 */ 534 iscsit_set_isns(B_FALSE); 535 536 /* Clean up data structures */ 537 mutex_destroy(&isns_monitor_mutex); 538 cv_destroy(&isns_idle_cv); 539 mutex_destroy(&esi.esi_mutex); 540 cv_destroy(&esi.esi_cv); 541 mutex_destroy(&iscsit_isns_mutex); 542 543 /* 544 * Free our EID and target list. 545 */ 546 547 if (isns_eid) { 548 kmem_free(isns_eid, strlen(isns_eid) + 1); 549 isns_eid = NULL; 550 } 551 552 iscsit_global.global_isns_cfg.isns_state = B_FALSE; 553 avl_destroy(&isns_target_list); 554 list_destroy(&iscsit_global.global_isns_cfg.isns_svrs); 555 avl_destroy(&isns_tpg_portals); 556 avl_destroy(&isns_all_portals); 557 num_default_portals = 0; 558 ISNS_GLOBAL_UNLOCK(); 559 560 mutex_destroy(&iscsit_global.global_isns_cfg.isns_mutex); 561 } 562 563 static void 564 iscsit_set_isns(boolean_t state) 565 { 566 iscsit_isns_svr_t *svr; 567 568 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 569 570 /* 571 * Update state and isns stop flag 572 */ 573 if (iscsit_global.global_isns_cfg.isns_state != state) { 574 /* reset retry count for all servers */ 575 for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs); 576 svr != NULL; 577 svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, 578 svr)) { 579 svr->svr_retry_count = 0; 580 } 581 582 iscsit_global.global_isns_cfg.isns_state = state; 583 584 if (state) { 585 isnst_start(); 586 } else { 587 isnst_stop(); 588 } 589 } 590 } 591 592 void 593 iscsit_add_isns(it_portal_t *cfg_svr) 594 { 595 iscsit_isns_svr_t *svr; 596 597 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 598 599 svr = kmem_zalloc(sizeof (iscsit_isns_svr_t), KM_SLEEP); 600 bcopy(&cfg_svr->portal_addr, &svr->svr_sa, 601 sizeof (struct sockaddr_storage)); 602 avl_create(&svr->svr_target_list, isnst_tgt_avl_compare, 603 sizeof (isns_target_t), offsetof(isns_target_t, target_node)); 604 svr->svr_esi_interval = isns_default_esi_interval; 605 606 /* put it on the global isns server list */ 607 list_insert_tail(&iscsit_global.global_isns_cfg.isns_svrs, svr); 608 } 609 610 void 611 isnst_mark_delete_isns(iscsit_isns_svr_t *svr) 612 { 613 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 614 615 /* If monitor thread not running, finish delete here */ 616 if (iscsit_global.global_isns_cfg.isns_state == B_FALSE) { 617 isnst_finish_delete_isns(svr); 618 } else { 619 svr->svr_delete_needed = B_TRUE; 620 } 621 622 } 623 624 void 625 isnst_finish_delete_isns(iscsit_isns_svr_t *svr) 626 { 627 628 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 629 isnst_clear_target_list(svr); 630 631 list_remove(&iscsit_global.global_isns_cfg.isns_svrs, svr); 632 /* free the memory */ 633 avl_destroy(&svr->svr_target_list); 634 kmem_free(svr, sizeof (*svr)); 635 } 636 637 static iscsit_isns_svr_t * 638 iscsit_isns_svr_lookup(struct sockaddr_storage *sa) 639 { 640 iscsit_isns_svr_t *svr; 641 it_portal_t portal1; 642 643 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 644 645 bcopy(sa, &portal1.portal_addr, sizeof (struct sockaddr_storage)); 646 647 for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs); 648 svr != NULL; 649 svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, svr)) { 650 if (it_sa_compare(&svr->svr_sa, sa) == 0) 651 return (svr); 652 } 653 654 return (NULL); 655 } 656 657 static isns_target_info_t * 658 isnst_create_target_info(iscsit_tgt_t *target) 659 { 660 661 isns_target_info_t *ti; 662 isns_tpgt_t *tig; 663 isns_tpgt_addr_t *tip; 664 iscsit_tpgt_t *tpgt; 665 iscsit_tpg_t *tpg; 666 iscsit_portal_t *tp; 667 char *str; 668 669 /* Cannot hold the iscsit_isns_mutex here! */ 670 ASSERT(! mutex_owned(&iscsit_isns_mutex)); 671 672 ti = kmem_zalloc(sizeof (isns_target_info_t), KM_SLEEP); 673 list_create(&ti->ti_tpgt_list, 674 sizeof (isns_tpgt_t), offsetof(isns_tpgt_t, ti_tpgt_ln)); 675 idm_refcnt_init(&ti->ti_refcnt, ti); 676 677 mutex_enter(&target->target_mutex); 678 (void) strncpy(ti->ti_tgt_name, target->target_name, 679 MAX_ISCSI_NODENAMELEN); 680 681 682 if (nvlist_lookup_string(target->target_props, PROP_ALIAS, 683 &str) == 0) { 684 (void) strncpy(ti->ti_tgt_alias, str, MAX_ISCSI_NODENAMELEN); 685 } 686 687 tpgt = avl_first(&target->target_tpgt_list); 688 ASSERT(tpgt != NULL); 689 do { 690 tig = kmem_zalloc(sizeof (isns_tpgt_t), KM_SLEEP); 691 list_create(&tig->ti_portal_list, sizeof (isns_tpgt_addr_t), 692 offsetof(isns_tpgt_addr_t, portal_ln)); 693 tig->ti_tpgt_tag = tpgt->tpgt_tag; 694 695 /* 696 * Only need portal list for non-default portal. 697 */ 698 if (tpgt->tpgt_tag != ISCSIT_DEFAULT_TPGT) { 699 tpg = tpgt->tpgt_tpg; 700 701 mutex_enter(&tpg->tpg_mutex); 702 703 tp = avl_first(&tpg->tpg_portal_list); 704 do { 705 tip = kmem_zalloc(sizeof (isns_tpgt_addr_t), 706 KM_SLEEP); 707 bcopy(&tp->portal_addr, &tip->portal_addr, 708 sizeof (tip->portal_addr)); 709 list_insert_tail(&tig->ti_portal_list, tip); 710 711 tp = AVL_NEXT(&tpg->tpg_portal_list, tp); 712 } while (tp != NULL); 713 mutex_exit(&tpg->tpg_mutex); 714 } 715 list_insert_tail(&ti->ti_tpgt_list, tig); 716 tpgt = AVL_NEXT(&target->target_tpgt_list, tpgt); 717 } while (tpgt != NULL); 718 mutex_exit(&target->target_mutex); 719 720 return (ti); 721 } 722 723 static void 724 isnst_clear_target_info_cb(void *arg) 725 { 726 isns_target_info_t *ti = (isns_target_info_t *)arg; 727 isns_tpgt_t *tig; 728 isns_tpgt_addr_t *tip; 729 730 while ((tig = list_remove_head(&ti->ti_tpgt_list)) != NULL) { 731 while ((tip = list_remove_head(&tig->ti_portal_list)) != NULL) { 732 kmem_free(tip, sizeof (isns_tpgt_addr_t)); 733 } 734 list_destroy(&tig->ti_portal_list); 735 kmem_free(tig, sizeof (isns_tpgt_t)); 736 } 737 list_destroy(&ti->ti_tpgt_list); 738 idm_refcnt_destroy(&ti->ti_refcnt); 739 kmem_free(ti, sizeof (isns_target_info_t)); 740 } 741 742 743 /* 744 * iscsit_isns_register 745 * called by iscsit when a target goes online 746 */ 747 int 748 iscsit_isns_register(iscsit_tgt_t *target) 749 { 750 isns_target_t *itarget, tmptgt; 751 avl_index_t where; 752 isns_target_info_t *ti; 753 754 /* Create TI struct outside of isns_mutex */ 755 ti = isnst_create_target_info(target); 756 757 mutex_enter(&iscsit_isns_mutex); 758 759 tmptgt.target = target; 760 if ((itarget = (isns_target_t *)avl_find(&isns_target_list, 761 &tmptgt, &where)) == NULL) { 762 itarget = kmem_zalloc(sizeof (isns_target_t), KM_SLEEP); 763 764 itarget->target = target; 765 avl_insert(&isns_target_list, (void *)itarget, where); 766 } else { 767 ASSERT(0); 768 } 769 770 /* Copy the target info so it will last beyond deregister */ 771 itarget->target_info = ti; 772 idm_refcnt_hold(&ti->ti_refcnt); 773 774 isns_targets_changed = B_TRUE; 775 776 mutex_exit(&iscsit_isns_mutex); 777 778 isnst_monitor_awaken(); 779 return (0); 780 } 781 782 /* 783 * iscsit_isns_deregister 784 * called by iscsit when a target goes offline 785 */ 786 int 787 iscsit_isns_deregister(iscsit_tgt_t *target) 788 { 789 isns_target_t *itarget, tmptgt; 790 isns_target_info_t *ti; 791 792 tmptgt.target = target; 793 794 mutex_enter(&iscsit_isns_mutex); 795 796 itarget = avl_find(&isns_target_list, &tmptgt, NULL); 797 ASSERT(itarget != NULL); 798 ti = itarget->target_info; 799 800 /* 801 * The main thread is done with the target_info object. 802 * Make sure the delete callback is called when 803 * all the svrs are done with it. 804 */ 805 idm_refcnt_rele(&ti->ti_refcnt); 806 idm_refcnt_async_wait_ref(&ti->ti_refcnt, 807 (idm_refcnt_cb_t *)&isnst_clear_target_info_cb); 808 809 itarget->target_info = NULL; 810 avl_remove(&isns_target_list, itarget); 811 kmem_free(itarget, sizeof (isns_target_t)); 812 813 isns_targets_changed = B_TRUE; 814 815 mutex_exit(&iscsit_isns_mutex); 816 817 isnst_monitor_awaken(); 818 return (0); 819 } 820 821 /* 822 * iscsit_isns_target_update 823 * This function is called by iscsit when a target's configuration 824 * has changed. 825 */ 826 827 void 828 iscsit_isns_target_update(iscsit_tgt_t *target) 829 { 830 isns_target_t *itarget, tmptgt; 831 isns_target_info_t *ti; 832 833 /* Create new TI struct outside of isns_mutex */ 834 ti = isnst_create_target_info(target); 835 836 mutex_enter(&iscsit_isns_mutex); 837 838 /* 839 * If iscsit calls us to modify a target, that target should 840 * already exist in the isns_svr_list. 841 */ 842 tmptgt.target = target; 843 itarget = avl_find(&isns_target_list, &tmptgt, NULL); 844 if (itarget == NULL) { 845 /* 846 * If target-update gets called while the target is still 847 * offline, then there is nothing to do. The target will be 848 * completely registered when it comes online. 849 */ 850 mutex_exit(&iscsit_isns_mutex); 851 /* Remove the old target_info struct */ 852 isnst_clear_target_info_cb(ti); 853 return; 854 } 855 856 /* Remove the old target_info struct */ 857 idm_refcnt_rele(&itarget->target_info->ti_refcnt); 858 idm_refcnt_async_wait_ref(&itarget->target_info->ti_refcnt, 859 (idm_refcnt_cb_t *)&isnst_clear_target_info_cb); 860 861 /* Link to new target_info struct */ 862 itarget->target_info = ti; 863 idm_refcnt_hold(&ti->ti_refcnt); 864 865 itarget->target_update_needed = B_TRUE; 866 867 isns_targets_changed = B_TRUE; 868 869 mutex_exit(&iscsit_isns_mutex); 870 871 isnst_monitor_awaken(); 872 } 873 874 static void 875 isnst_start() 876 { 877 ISNST_LOG(CE_NOTE, "**** isnst_start"); 878 879 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 880 881 /* 882 * Start ESI thread(s) 883 */ 884 isnst_esi_start(); 885 886 /* 887 * Create a thread for monitoring server communications 888 */ 889 isnst_monitor_start(); 890 } 891 892 static void 893 isnst_stop() 894 { 895 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 896 ISNST_LOG(CE_NOTE, "**** isnst_stop"); 897 898 899 ISNS_GLOBAL_UNLOCK(); 900 isnst_esi_stop(); 901 isnst_monitor_stop(); 902 ISNS_GLOBAL_LOCK(); 903 } 904 905 static void 906 isnst_monitor_start(void) 907 { 908 ISNST_LOG(CE_NOTE, "isnst_monitor_start"); 909 910 911 mutex_enter(&isns_monitor_mutex); 912 ASSERT(!isns_monitor_thr_running); 913 isns_monitor_thr_id = thread_create(NULL, 0, 914 isnst_monitor, NULL, 0, &p0, TS_RUN, minclsyspri); 915 while (!isns_monitor_thr_running) 916 cv_wait(&isns_idle_cv, &isns_monitor_mutex); 917 mutex_exit(&isns_monitor_mutex); 918 } 919 920 static void 921 isnst_monitor_stop(void) 922 { 923 ISNST_LOG(CE_NOTE, "isnst_monitor_stop"); 924 925 mutex_enter(&isns_monitor_mutex); 926 if (isns_monitor_thr_running) { 927 isns_monitor_thr_running = B_FALSE; 928 cv_signal(&isns_idle_cv); 929 mutex_exit(&isns_monitor_mutex); 930 931 thread_join(isns_monitor_thr_did); 932 return; 933 } 934 mutex_exit(&isns_monitor_mutex); 935 } 936 937 /* 938 * isnst_update_server_timestamp 939 * 940 * When we receive an ESI request, update the timestamp for the server. 941 * If we don't receive one for the specified period of time, we'll attempt 942 * to re-register. 943 * 944 */ 945 static boolean_t 946 isnst_update_server_timestamp(struct sockaddr_storage *ss) 947 { 948 iscsit_isns_svr_t *svr; 949 950 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 951 952 /* 953 * Find the server and update the timestamp 954 */ 955 for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs); 956 svr != NULL; 957 svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, svr)) { 958 /* 959 * Note that the port number in incoming probe will be 960 * different than the iSNS server's port number. 961 */ 962 if (idm_ss_compare(ss, &svr->svr_sa, 963 B_TRUE /* v4_mapped_as_v4 */, 964 B_FALSE /* don't compare_ports */) == 0) { 965 break; 966 } 967 } 968 969 if (svr != NULL) { 970 /* Update the timestamp we keep for this server */ 971 svr->svr_last_msg = ddi_get_lbolt(); 972 /* 973 * If we receive ESI probe from a server we are not 974 * registered to, then cause a re-reg attempt. 975 */ 976 if (!svr->svr_registered) { 977 isnst_monitor_awaken(); 978 } 979 return (B_TRUE); 980 } 981 982 return (B_FALSE); 983 } 984 985 986 /* 987 * isnst_monitor_all_servers -- loop through all servers 988 */ 989 990 991 static void 992 isnst_monitor_all_servers() 993 { 994 iscsit_isns_svr_t *svr, *next_svr; 995 boolean_t enabled; 996 list_t *svr_list; 997 int rc; 998 999 svr_list = &iscsit_global.global_isns_cfg.isns_svrs; 1000 1001 ISNS_GLOBAL_LOCK(); 1002 1003 isnst_copy_global_status_changes(); 1004 1005 enabled = iscsit_global.global_isns_cfg.isns_state; 1006 for (svr = list_head(svr_list); svr != NULL; svr = next_svr) { 1007 next_svr = list_next(svr_list, svr); 1008 1009 rc = isnst_monitor_one_server(svr, enabled); 1010 if (rc != 0) { 1011 svr->svr_retry_count++; 1012 if (svr->svr_registered && 1013 svr->svr_retry_count > isns_max_retry) { 1014 char server_buf[IDM_SA_NTOP_BUFSIZ]; 1015 1016 if (! svr->svr_reset_needed) { 1017 ISNST_LOG(CE_WARN, 1018 "isnst: iSNS server %s" 1019 " not responding (rc=%d).", 1020 idm_sa_ntop(&svr->svr_sa, 1021 server_buf, sizeof (server_buf)), 1022 rc); 1023 svr->svr_reset_needed = B_TRUE; 1024 } 1025 } 1026 } else { 1027 svr->svr_retry_count = 0; 1028 } 1029 /* 1030 * If we have finished unregistering this server, 1031 * it is now OK to delete it. 1032 */ 1033 if (svr->svr_delete_needed == B_TRUE && 1034 svr->svr_registered == B_FALSE) { 1035 isnst_finish_delete_isns(svr); 1036 } 1037 } 1038 ISNS_GLOBAL_UNLOCK(); 1039 } 1040 1041 static void 1042 isnst_monitor_awaken(void) 1043 { 1044 mutex_enter(&isns_monitor_mutex); 1045 if (isns_monitor_thr_running) { 1046 DTRACE_PROBE(iscsit__isns__monitor__awaken); 1047 cv_signal(&isns_idle_cv); 1048 } 1049 mutex_exit(&isns_monitor_mutex); 1050 } 1051 1052 /* 1053 * isnst_monitor -- the monitor thread for iSNS 1054 */ 1055 /*ARGSUSED*/ 1056 static void 1057 isnst_monitor(void *arg) 1058 { 1059 mutex_enter(&isns_monitor_mutex); 1060 isns_monitor_thr_did = curthread->t_did; 1061 isns_monitor_thr_running = B_TRUE; 1062 cv_signal(&isns_idle_cv); 1063 1064 /* 1065 * Start with a short pause (5 sec) to allow all targets 1066 * to be registered before we send register-all. This is 1067 * purely an optimization to cut down on the number of 1068 * messages we send to the iSNS server. 1069 */ 1070 mutex_exit(&isns_monitor_mutex); 1071 delay(drv_usectohz(isns_initial_delay * 1000000)); 1072 mutex_enter(&isns_monitor_mutex); 1073 1074 /* Force an initialization of isns_all_portals */ 1075 mutex_enter(&iscsit_isns_mutex); 1076 isns_portals_changed = B_TRUE; 1077 mutex_exit(&iscsit_isns_mutex); 1078 1079 while (isns_monitor_thr_running) { 1080 1081 /* Update servers */ 1082 mutex_exit(&isns_monitor_mutex); 1083 isnst_monitor_all_servers(); 1084 mutex_enter(&isns_monitor_mutex); 1085 1086 /* If something needs attention, go right to the top */ 1087 mutex_enter(&iscsit_isns_mutex); 1088 if (isns_targets_changed || isns_portals_changed) { 1089 DTRACE_PROBE(iscsit__isns__monitor__reenter); 1090 mutex_exit(&iscsit_isns_mutex); 1091 /* isns_monitor_mutex still held */ 1092 continue; 1093 } 1094 mutex_exit(&iscsit_isns_mutex); 1095 1096 /* 1097 * Keep running until isns_monitor_thr_running is set to 1098 * B_FALSE. 1099 */ 1100 if (! isns_monitor_thr_running) 1101 break; 1102 1103 DTRACE_PROBE(iscsit__isns__monitor__sleep); 1104 (void) cv_reltimedwait(&isns_idle_cv, &isns_monitor_mutex, 1105 monitor_idle_interval, TR_CLOCK_TICK); 1106 DTRACE_PROBE1(iscsit__isns__monitor__wakeup, 1107 boolean_t, isns_monitor_thr_running); 1108 } 1109 1110 mutex_exit(&isns_monitor_mutex); 1111 1112 /* Update the servers one last time for deregistration */ 1113 isnst_monitor_all_servers(); 1114 1115 /* Clean up the all-portals list */ 1116 ISNS_GLOBAL_LOCK(); 1117 isnst_clear_default_portals(); 1118 ISNS_GLOBAL_UNLOCK(); 1119 1120 /* terminate the thread at the last */ 1121 thread_exit(); 1122 } 1123 1124 static int 1125 isnst_monitor_one_server(iscsit_isns_svr_t *svr, boolean_t enabled) 1126 { 1127 int rc = 0; 1128 isns_target_t *itarget; 1129 1130 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1131 1132 /* 1133 * First, take care of the case where iSNS is no longer enabled. 1134 * 1135 */ 1136 1137 if (enabled == B_FALSE || svr->svr_delete_needed) { 1138 /* 1139 * Just try one time to deregister all from server. 1140 * Doesn't matter if this fails. We're disabled. 1141 */ 1142 (void) isnst_update_one_server(svr, NULL, ISNS_DEREGISTER_ALL); 1143 isnst_set_server_status(svr, B_FALSE); 1144 return (0); 1145 } 1146 1147 retry_replace_all: 1148 /* 1149 * If the server needs replace-all, check if it should 1150 * be a DevDereg (i.e. if the last target is gone.) 1151 */ 1152 1153 if (svr->svr_registered && svr->svr_reset_needed) { 1154 /* Send DevDereg if last registered target */ 1155 isns_target_t *jtarget; 1156 for (jtarget = avl_first(&svr->svr_target_list); 1157 jtarget != NULL; 1158 jtarget = AVL_NEXT(&svr->svr_target_list, jtarget)) { 1159 if (!jtarget->target_delete_needed) { 1160 break; 1161 } 1162 } 1163 /* 1164 * jtarget is null IFF all tgts need deletion, 1165 * and there are no new targets to register. 1166 */ 1167 if (jtarget == NULL) { 1168 rc = isnst_update_one_server(svr, NULL, 1169 ISNS_DEREGISTER_ALL); 1170 if (rc != 0) { 1171 return (rc); 1172 } 1173 isnst_set_server_status(svr, B_FALSE); 1174 return (0); 1175 } 1176 } 1177 1178 /* 1179 * If the server is not yet registered, do the registration 1180 */ 1181 if (! svr->svr_registered || svr->svr_reset_needed) { 1182 1183 if (avl_numnodes(&svr->svr_target_list) == 0) { 1184 /* If no targets, nothing to register */ 1185 return (0); 1186 } 1187 if ((rc = isnst_update_one_server(svr, NULL, 1188 ISNS_REGISTER_ALL)) != 0) { 1189 /* Registration failed */ 1190 return (rc); 1191 } 1192 isnst_set_server_status(svr, B_TRUE); 1193 1194 } 1195 1196 /* The following checks are expensive, so only do them if needed */ 1197 if (svr->svr_targets_changed) { 1198 isns_target_t *next_target; 1199 /* 1200 * If there is a target to be deleted, send the 1201 * deletion request for one target at a time. 1202 */ 1203 for (itarget = avl_first(&svr->svr_target_list); 1204 itarget != NULL; 1205 itarget = next_target) { 1206 next_target = AVL_NEXT(&svr->svr_target_list, itarget); 1207 if (itarget->target_delete_needed) { 1208 /* See if last non-deleted target */ 1209 isns_target_t *jtarget; 1210 ASSERT(itarget->target_registered); 1211 for (jtarget = 1212 avl_first(&svr->svr_target_list); 1213 jtarget != NULL; 1214 jtarget = AVL_NEXT(&svr->svr_target_list, 1215 jtarget)) { 1216 if (jtarget->target_registered && 1217 !jtarget->target_delete_needed) { 1218 break; 1219 } 1220 } 1221 /* jtarget is null if last registered tgt */ 1222 if (jtarget == NULL) { 1223 /* 1224 * Removing last tgt -- deregister all. 1225 * Doesn't matter if this fails. 1226 * We're disabled. 1227 */ 1228 rc = isnst_update_one_server(svr, 1229 NULL, ISNS_DEREGISTER_ALL); 1230 if (rc != 0) { 1231 return (rc); 1232 } 1233 isnst_set_server_status(svr, B_FALSE); 1234 return (0); 1235 } 1236 rc = isnst_update_one_server(svr, 1237 itarget, ISNS_DEREGISTER_TARGET); 1238 if (rc != 0 && isnst_retry_registration(rc)) { 1239 /* Retryable code => try replace-all */ 1240 svr->svr_reset_needed = B_TRUE; 1241 goto retry_replace_all; 1242 } 1243 1244 if (rc != 0) { 1245 return (rc); 1246 } 1247 isnst_clear_from_target_list(itarget, 1248 &svr->svr_target_list); 1249 } 1250 } 1251 1252 /* If any target needs a register or an update, do so */ 1253 itarget = avl_first(&svr->svr_target_list); 1254 while (itarget) { 1255 if (!itarget->target_registered || 1256 itarget->target_update_needed) { 1257 1258 /* 1259 * Because of a bug in the isns 1260 * server, we cannot send a modify 1261 * operation that changes the target's 1262 * TPGTs. So just replace all. 1263 */ 1264 if (isns_modify_must_replace) { 1265 svr->svr_reset_needed = B_TRUE; 1266 goto retry_replace_all; 1267 } 1268 /* Try to update existing info for one tgt */ 1269 rc = isnst_update_one_server(svr, 1270 itarget, 1271 ISNS_MODIFY_TARGET); 1272 if (rc != 0 && isnst_retry_registration(rc)) { 1273 /* Retryable code => try replace-all */ 1274 svr->svr_reset_needed = B_TRUE; 1275 goto retry_replace_all; 1276 } 1277 if (rc != 0) { 1278 return (rc); 1279 } 1280 itarget->target_update_needed = 1281 B_FALSE; 1282 itarget->target_registered = B_TRUE; 1283 } 1284 itarget = AVL_NEXT(&svr->svr_target_list, 1285 itarget); 1286 } 1287 1288 /* 1289 * We have gone through all the cases -- this server 1290 * is now up to date. 1291 */ 1292 svr->svr_targets_changed = B_FALSE; 1293 } 1294 1295 1296 if (isns_use_esi) { 1297 /* 1298 * If using ESI, and no ESI request is received within 1299 * MAX_ESI_INTERVALS (3) number of intervals, we'll 1300 * try to re-register with the server. The server will 1301 * delete our information if we fail to respond for 2 1302 * ESI intervals. 1303 */ 1304 if (ddi_get_lbolt() >= (svr->svr_last_msg + 1305 drv_usectohz(svr->svr_esi_interval * 1000000 * 1306 MAX_ESI_INTERVALS))) { 1307 /* re-register everything */ 1308 svr->svr_reset_needed = B_TRUE; 1309 goto retry_replace_all; 1310 } 1311 } else { 1312 /* 1313 * If not using ESI, make sure to ping server during 1314 * each registration period. Do this at half the 1315 * registration interval, so we won't get timed out. 1316 */ 1317 if (ddi_get_lbolt() >= (svr->svr_last_msg + 1318 drv_usectohz(isns_registration_period * (1000000/3)))) { 1319 /* Send a self-query as a keepalive. */ 1320 rc = isnst_keepalive(svr); 1321 if (rc != 0 && isnst_retry_registration(rc)) { 1322 /* Retryable code => try replace-all */ 1323 svr->svr_reset_needed = B_TRUE; 1324 goto retry_replace_all; 1325 } 1326 if (rc != 0) { 1327 return (rc); 1328 } 1329 } 1330 } 1331 return (0); 1332 1333 } 1334 1335 /* 1336 * isnst_mark_deleted_target -- find tgt in svr list but not global list 1337 */ 1338 static void 1339 isnst_mark_deleted_targets(iscsit_isns_svr_t *svr) 1340 { 1341 isns_target_t *itarget, *nxt_target, tmptgt; 1342 1343 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1344 ASSERT(mutex_owned(&iscsit_isns_mutex)); 1345 1346 for (itarget = avl_first(&svr->svr_target_list); 1347 itarget != NULL; 1348 itarget = nxt_target) { 1349 tmptgt.target = itarget->target; 1350 nxt_target = AVL_NEXT(&svr->svr_target_list, itarget); 1351 if (avl_find(&isns_target_list, &tmptgt, NULL) == NULL) { 1352 if (itarget->target_registered) { 1353 itarget->target_delete_needed = B_TRUE; 1354 } else { 1355 isnst_clear_from_target_list(itarget, 1356 &svr->svr_target_list); 1357 } 1358 } 1359 } 1360 } 1361 1362 static isns_target_t * 1363 isnst_latch_to_target_list(isns_target_t *jtarget, avl_tree_t *target_list) 1364 { 1365 isns_target_t *itarget, tmptgt; 1366 avl_index_t where; 1367 1368 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1369 ASSERT(mutex_owned(&iscsit_isns_mutex)); 1370 /* 1371 * Make sure this target isn't already in our list. 1372 */ 1373 1374 tmptgt.target = jtarget->target; 1375 if ((itarget = (isns_target_t *)avl_find(target_list, 1376 &tmptgt, &where)) == NULL) { 1377 itarget = kmem_zalloc(sizeof (isns_target_t), KM_SLEEP); 1378 1379 itarget->target = jtarget->target; 1380 itarget->target_info = jtarget->target_info; 1381 idm_refcnt_hold(&itarget->target_info->ti_refcnt); 1382 1383 avl_insert(target_list, (void *)itarget, where); 1384 } else { 1385 ASSERT(0); 1386 } 1387 1388 return (itarget); 1389 } 1390 1391 static void 1392 isnst_clear_target_list(iscsit_isns_svr_t *svr) 1393 { 1394 isns_target_t *itarget; 1395 1396 while ((itarget = avl_first(&svr->svr_target_list)) != NULL) { 1397 isnst_clear_from_target_list(itarget, 1398 &svr->svr_target_list); 1399 } 1400 } 1401 1402 static void 1403 isnst_clear_from_target_list(isns_target_t *jtarget, avl_tree_t *target_list) 1404 { 1405 isns_target_t *itarget, tmptgt; 1406 1407 tmptgt.target = jtarget->target; 1408 1409 if ((itarget = avl_find(target_list, &tmptgt, NULL)) 1410 != NULL) { 1411 1412 avl_remove(target_list, itarget); 1413 idm_refcnt_rele(&itarget->target_info->ti_refcnt); 1414 kmem_free(itarget, sizeof (isns_target_t)); 1415 } else { 1416 ASSERT(0); 1417 } 1418 } 1419 1420 /* 1421 * isnst_copy_global_status_changes -- update svrs to match iscsit 1422 * 1423 * At the end of this routine svr->svr_target_list has all the entries 1424 * in the current isns_target_list plus any targets that are marked 1425 * for deletion. 1426 */ 1427 static void 1428 isnst_copy_global_status_changes(void) 1429 { 1430 isns_target_t *ttarget, *itarget, tmptgt; 1431 iscsit_isns_svr_t *svr; 1432 1433 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1434 1435 /* 1436 * Copy info about recent transitions from global state to 1437 * per-server state. We use the global state so that iscsit 1438 * functions can proceed without blocking on slow-to-release 1439 * iSNS locks. 1440 */ 1441 mutex_enter(&iscsit_isns_mutex); 1442 1443 /* 1444 * Periodically check for changed IP addresses. This function 1445 * sets isns_all_portals to the current set, and sets 1446 * isns_portals_changed if a portal is added or removed. 1447 */ 1448 isnst_monitor_default_portal_list(); 1449 1450 /* Initialize the per-server structs to some basic values */ 1451 for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs); 1452 svr != NULL; 1453 svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, 1454 svr)) { 1455 if (isns_portals_changed && svr->svr_registered) { 1456 /* 1457 * Cause re-register, for now, when portals change. 1458 * Eventually, we should add new portals one by one 1459 */ 1460 svr->svr_reset_needed = B_TRUE; 1461 } 1462 if (!svr->svr_registered) { 1463 /* To re-register, start with empty target list */ 1464 isnst_clear_target_list(svr); 1465 /* And set flag to add all current targets, below */ 1466 isns_targets_changed = B_TRUE; 1467 } else if (isns_targets_changed || svr->svr_reset_needed) { 1468 /* Mark to look for target changes */ 1469 isnst_mark_deleted_targets(svr); 1470 svr->svr_targets_changed = B_TRUE; 1471 } 1472 } 1473 1474 /* 1475 * If any target has been modified, tell all the svrs to 1476 * update that target. 1477 */ 1478 if (isns_targets_changed) { 1479 ttarget = avl_first(&isns_target_list); 1480 while (ttarget) { 1481 for (svr = list_head( 1482 &iscsit_global.global_isns_cfg.isns_svrs); 1483 svr != NULL; 1484 svr = list_next( 1485 &iscsit_global.global_isns_cfg.isns_svrs, 1486 svr)) { 1487 tmptgt.target = ttarget->target; 1488 itarget = avl_find( 1489 &svr->svr_target_list, 1490 &tmptgt, NULL); 1491 1492 if (itarget == NULL) { 1493 /* Add a new target */ 1494 (void) isnst_latch_to_target_list( 1495 ttarget, &svr->svr_target_list); 1496 } else if (ttarget->target_update_needed) { 1497 /* Modify existing target */ 1498 itarget->target_update_needed = 1499 B_TRUE; 1500 /* Remove link to old target_info */ 1501 idm_refcnt_rele( 1502 &itarget->target_info->ti_refcnt); 1503 /* Link to new target_info struct */ 1504 itarget->target_info = 1505 ttarget->target_info; 1506 idm_refcnt_hold( 1507 &itarget->target_info->ti_refcnt); 1508 } 1509 } 1510 ttarget->target_update_needed = B_FALSE; 1511 ttarget = AVL_NEXT(&isns_target_list, ttarget); 1512 } 1513 } 1514 1515 /* 1516 * Now we have updated the per-server state for all servers. 1517 * Clear the global state flags 1518 */ 1519 isns_targets_changed = B_FALSE; 1520 isns_portals_changed = B_FALSE; 1521 mutex_exit(&iscsit_isns_mutex); 1522 } 1523 1524 static int 1525 isnst_update_one_server(iscsit_isns_svr_t *svr, isns_target_t *itarget, 1526 isns_reg_type_t reg) 1527 { 1528 int rc = 0; 1529 1530 switch (reg) { 1531 case ISNS_DEREGISTER_TARGET: 1532 rc = isnst_deregister(svr, itarget); 1533 break; 1534 1535 case ISNS_DEREGISTER_ALL: 1536 rc = isnst_deregister(svr, NULL); 1537 break; 1538 1539 case ISNS_MODIFY_TARGET: 1540 case ISNS_REGISTER_TARGET: 1541 rc = isnst_register(svr, itarget, reg); 1542 break; 1543 1544 case ISNS_REGISTER_ALL: 1545 rc = isnst_register(svr, NULL, reg); 1546 break; 1547 1548 default: 1549 ASSERT(0); 1550 /* NOTREACHED */ 1551 } 1552 1553 return (rc); 1554 } 1555 1556 /* 1557 * isnst_retry_registration 1558 * 1559 * This function checks the return value from a registration pdu and 1560 * determines whether or not we should retry this request. If the 1561 * request is retried, it will do so as an "update", which means we 1562 * re-register everything. 1563 */ 1564 1565 static boolean_t 1566 isnst_retry_registration(int rsp_status_code) 1567 { 1568 boolean_t retry; 1569 1570 /* 1571 * The following are the error codes that indicate isns-client 1572 * and isns-server are out of synch. E.g. No-Such-Entry can 1573 * occur on a keepalive if the server has timed out our 1574 * connection. If we get one of these messages, we replace-all 1575 * right away to get back in synch faster. 1576 */ 1577 switch (rsp_status_code) { 1578 case ISNS_RSP_INVALID_REGIS: 1579 case ISNS_RSP_SRC_UNAUTHORIZED: 1580 case ISNS_RSP_BUSY: 1581 case ISNS_RSP_INVALID_UPDATE: 1582 case ISNS_RSP_NO_SUCH_ENTRY: 1583 retry = B_TRUE; 1584 break; 1585 default: 1586 retry = B_FALSE; 1587 break; 1588 } 1589 1590 return (retry); 1591 } 1592 1593 1594 1595 static int 1596 isnst_register(iscsit_isns_svr_t *svr, isns_target_t *itarget, 1597 isns_reg_type_t regtype) 1598 { 1599 struct sonode *so; 1600 int rc = 0; 1601 isns_pdu_t *pdu, *rsp; 1602 size_t pdu_size, rsp_size; 1603 1604 /* create TCP connection to the isns server */ 1605 so = isnst_open_so(&svr->svr_sa); 1606 if (so == NULL) { 1607 return (-1); 1608 } 1609 1610 pdu_size = isnst_make_reg_pdu(&pdu, itarget, svr, regtype); 1611 if (pdu_size == 0) { 1612 isnst_close_so(so); 1613 return (-1); 1614 } 1615 1616 rc = isnst_send_pdu(so, pdu); 1617 if (rc != 0) { 1618 kmem_free(pdu, pdu_size); 1619 isnst_close_so(so); 1620 return (rc); 1621 } 1622 1623 rsp_size = isnst_rcv_pdu(so, &rsp); 1624 if (rsp_size == 0) { 1625 kmem_free(pdu, pdu_size); 1626 isnst_close_so(so); 1627 return (-1); 1628 } 1629 1630 rc = isnst_verify_rsp(svr, pdu, rsp, rsp_size); 1631 1632 kmem_free(pdu, pdu_size); 1633 kmem_free(rsp, rsp_size); 1634 isnst_close_so(so); 1635 1636 return (rc); 1637 } 1638 1639 /* 1640 * isnst_make_reg_pdu: 1641 * Cases: 1642 * initial registration of all targets (replace-all) 1643 * initial registration of a single target (update-existing) 1644 * modify an existing target (update-existing) 1645 */ 1646 static size_t 1647 isnst_make_reg_pdu(isns_pdu_t **pdu, isns_target_t *itarget, 1648 iscsit_isns_svr_t *svr, isns_reg_type_t regtype) 1649 { 1650 size_t pdu_size; 1651 char *str; 1652 int len; 1653 isns_target_t *src; 1654 boolean_t reg_all = B_FALSE; 1655 uint16_t flags = 0; 1656 1657 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1658 1659 /* 1660 * Find a source attribute for this registration. 1661 * 1662 * If updating a specific target for the first time, use that 1663 * target. 1664 * If already registered, use a registered target 1665 * Otherwise, use the first target we are going to register. 1666 */ 1667 ASSERT(avl_numnodes(&svr->svr_target_list) != 0); 1668 if (itarget != NULL && ! svr->svr_registered) { 1669 src = itarget; 1670 } else if (svr->svr_registered) { 1671 src = isnst_get_registered_source(svr); 1672 } else { 1673 /* 1674 * When registering to a server, and we don't know which 1675 * of our targets the server might already know, 1676 * cycle through each of our targets as source. The server 1677 * does source validation. If the server knows any of our 1678 * targets, it will eventually accept one of our registrations. 1679 */ 1680 int i; 1681 isns_target_t *jtarget; 1682 1683 if (svr->svr_last_target_index >= 1684 avl_numnodes(&svr->svr_target_list) - 1) { 1685 svr->svr_last_target_index = 0; 1686 } else { 1687 svr->svr_last_target_index++; 1688 } 1689 for (i = 0, jtarget = avl_first(&svr->svr_target_list); 1690 i < svr->svr_last_target_index; 1691 i++, jtarget = AVL_NEXT(&svr->svr_target_list, jtarget)) { 1692 ASSERT(jtarget != NULL); 1693 } 1694 src = jtarget; 1695 ASSERT(src != NULL); 1696 } 1697 1698 /* 1699 * Null target means we're replacing everything. 1700 */ 1701 if (itarget == NULL) { 1702 reg_all = B_TRUE; 1703 flags = ISNS_FLAG_REPLACE_REG; 1704 /* Reset itarget to the beginning of our list */ 1705 itarget = (isns_target_t *)avl_first(&svr->svr_target_list); 1706 } else if (regtype == ISNS_REGISTER_TARGET) { 1707 flags = ISNS_FLAG_REPLACE_REG; 1708 ASSERT(!itarget->target_delete_needed); 1709 } 1710 1711 pdu_size = isnst_create_pdu_header(ISNS_DEV_ATTR_REG, pdu, flags); 1712 if (pdu_size == 0) { 1713 return (0); 1714 } 1715 1716 /* Source Attribute */ 1717 1718 len = strlen(src->target_info->ti_tgt_name) + 1; 1719 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 1720 len, src->target_info->ti_tgt_name, 0) != 0) { 1721 goto pdu_error; 1722 } 1723 1724 /* 1725 * Message Key Attributes - EID 1726 */ 1727 len = strlen(isns_eid) + 1; 1728 1729 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID, 1730 len, isns_eid, 0) != 0) { 1731 goto pdu_error; 1732 } 1733 1734 /* Delimiter */ 1735 if (isnst_add_attr(*pdu, pdu_size, ISNS_DELIMITER_ATTR_ID, 1736 0, 0, 0) != 0) { 1737 goto pdu_error; 1738 } 1739 1740 /* 1741 * Operating Attributes 1742 */ 1743 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID, len, 1744 isns_eid, 0) != 0) { 1745 goto pdu_error; 1746 } 1747 1748 1749 /* ENTITY Protocol - Section 6.2.2 */ 1750 if (isnst_add_attr(*pdu, pdu_size, 1751 ISNS_ENTITY_PROTOCOL_ATTR_ID, 1752 4, 0, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) { 1753 goto pdu_error; 1754 } 1755 1756 if (reg_all) { 1757 /* Registration Period -- use if not using ESI */ 1758 if (!isns_use_esi && 1759 isnst_add_attr(*pdu, pdu_size, 1760 ISNS_ENTITY_REG_PERIOD_ATTR_ID, 4, 1761 0, isns_registration_period) != 0) { 1762 goto pdu_error; 1763 } 1764 /* 1765 * Network entity portal information - only when 1766 * replacing all. Since targets are only registered 1767 * to iSNS when their portals are already registered 1768 * to iSNS, we can assume entity portals exist. 1769 */ 1770 if (isnst_reg_pdu_add_entity_portals(*pdu, pdu_size) != 0) { 1771 goto pdu_error; 1772 } 1773 1774 /* 1775 * Skip over delete-pending tgts. There must be at 1776 * least one non-deleted tgt, or it is an error. 1777 */ 1778 while (itarget->target_delete_needed) { 1779 itarget = AVL_NEXT(&svr->svr_target_list, 1780 itarget); 1781 ASSERT(itarget != NULL); 1782 } 1783 } 1784 1785 1786 /* Add information about each target or one target */ 1787 do { 1788 1789 /* iSCSI Name - Section 6.4.1 */ 1790 str = itarget->target_info->ti_tgt_name; 1791 len = strlen(str) + 1; 1792 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 1793 len, str, 0) != 0) { 1794 goto pdu_error; 1795 } 1796 1797 /* iSCSI Node Type */ 1798 if (isnst_add_attr(*pdu, pdu_size, 1799 ISNS_ISCSI_NODE_TYPE_ATTR_ID, 4, 0, 1800 ISNS_TARGET_NODE_TYPE) != 0) { 1801 goto pdu_error; 1802 } 1803 1804 /* iSCSI Alias */ 1805 str = itarget->target_info->ti_tgt_alias; 1806 len = strnlen(str, 1807 sizeof (itarget->target_info->ti_tgt_alias)); 1808 if (len) { 1809 /* Found alias in property list */ 1810 if (isnst_add_attr(*pdu, pdu_size, 1811 ISNS_ISCSI_ALIAS_ATTR_ID, len+1, str, 0) != 0) { 1812 goto pdu_error; 1813 } 1814 } 1815 1816 if (isnst_reg_pdu_add_pg(*pdu, pdu_size, itarget) != 0) { 1817 goto pdu_error; 1818 } 1819 1820 /* If registering one target, then we are done. */ 1821 if (!reg_all) { 1822 break; 1823 } 1824 1825 /* Skip over delete-pending tgts */ 1826 do { 1827 itarget = AVL_NEXT(&svr->svr_target_list, itarget); 1828 } while (itarget != NULL && itarget->target_delete_needed); 1829 1830 } while (itarget != NULL); 1831 1832 return (pdu_size); 1833 1834 pdu_error: 1835 /* packet too large, no memory (or other error) */ 1836 len = ntohs((*pdu)->payload_len); 1837 if (len + 1000 > isns_message_buf_size) { 1838 /* Increase the PDU size we will ask for next time */ 1839 if (isns_message_buf_size * 2 <= ISNST_MAX_MSG_SIZE) { 1840 isns_message_buf_size *= 2; 1841 ISNST_LOG(CE_NOTE, 1842 "Increasing isns_message_buf_size to %d", 1843 isns_message_buf_size); 1844 } else { 1845 cmn_err(CE_WARN, "iscsit: isns: no space" 1846 " to send required PDU"); 1847 } 1848 } 1849 1850 kmem_free(*pdu, pdu_size); 1851 *pdu = NULL; 1852 1853 return (0); 1854 } 1855 1856 static int 1857 isnst_reg_pdu_add_entity_portals(isns_pdu_t *pdu, size_t pdu_size) 1858 { 1859 int rc = 0; 1860 isns_portal_t *iportal; 1861 1862 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1863 1864 iportal = (isns_portal_t *)avl_first(&isns_all_portals); 1865 while (iportal != NULL) { 1866 /* Do not include ESI port if not using ESI */ 1867 if (isnst_add_portal_attr(pdu, pdu_size, 1868 ISNS_PORTAL_IP_ADDR_ATTR_ID, 1869 ISNS_PORTAL_PORT_ATTR_ID, 1870 &iportal->portal_addr, 1871 isns_use_esi /* ESI info */) != 0) { 1872 rc = -1; 1873 break; 1874 } 1875 iportal = AVL_NEXT(&isns_all_portals, iportal); 1876 } 1877 1878 return (rc); 1879 } 1880 1881 1882 /* 1883 * isnst_reg_pdu_add_pg -- add the PG and PGT entries for one target. 1884 */ 1885 static int 1886 isnst_reg_pdu_add_pg(isns_pdu_t *pdu, size_t pdu_size, isns_target_t *itarget) 1887 { 1888 int rval = 0; 1889 avl_tree_t null_portals; 1890 isns_target_info_t *ti; 1891 isns_tpgt_t *tig; 1892 1893 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1894 1895 ti = itarget->target_info; 1896 1897 /* 1898 * If all registered targets only use the default TPGT, then 1899 * we can skip sending PG info to the iSNS server. 1900 */ 1901 if (num_tpg_portals == 0) 1902 return (0); 1903 1904 /* 1905 * For each target, we start with the full portal list, 1906 * and then remove portals as we add them to TPGTs for this target. 1907 * At the end, all the remaining portals go into the "null pg". 1908 * We use the "null_portals" list to track this. 1909 */ 1910 avl_create(&null_portals, isnst_portal_avl_compare, 1911 sizeof (isns_portal_t), offsetof(isns_portal_t, portal_node)); 1912 isnst_copy_portal_list(&isns_all_portals, &null_portals); 1913 1914 for (tig = list_head(&ti->ti_tpgt_list); 1915 tig != NULL; 1916 tig = list_next(&ti->ti_tpgt_list, tig)) { 1917 1918 if (tig->ti_tpgt_tag == ISCSIT_DEFAULT_TPGT) { 1919 /* Add portal info from list of default portals */ 1920 if (isnst_add_default_pg(pdu, pdu_size, 1921 &null_portals) != 0) { 1922 rval = 1; 1923 break; 1924 } 1925 } else { 1926 /* Add portal info from this TPGT's entries */ 1927 if (isnst_add_tpg_pg(pdu, pdu_size, tig, 1928 &null_portals) != 0) { 1929 rval = 1; 1930 break; 1931 } 1932 } 1933 } 1934 1935 /* Add the remaining portals (if any) to the null PG */ 1936 if (rval == 0 && 1937 isnst_add_null_pg(pdu, pdu_size, &null_portals) != 0) { 1938 rval = 1; 1939 } 1940 isnst_clear_portal_list(&null_portals); 1941 avl_destroy(&null_portals); 1942 return (rval); 1943 } 1944 1945 /* Write one TPGT's info into the PDU */ 1946 static int 1947 isnst_add_tpg_pg(isns_pdu_t *pdu, size_t pdu_size, 1948 isns_tpgt_t *tig, avl_tree_t *null_portal_list) 1949 { 1950 isns_tpgt_addr_t *tip; 1951 int rval = 0; 1952 1953 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1954 ASSERT(tig->ti_tpgt_tag != ISCSIT_DEFAULT_TPGT); 1955 1956 /* Portal Group Tag */ 1957 if (isnst_add_attr(pdu, pdu_size, 1958 ISNS_PG_TAG_ATTR_ID, 4, 0, tig->ti_tpgt_tag) != 0) { 1959 rval = 1; 1960 goto pg_done; 1961 } 1962 1963 tip = list_head(&tig->ti_portal_list); 1964 ASSERT(tip != NULL); 1965 do { 1966 /* PG Portal Addr and PG Portal Port */ 1967 if (isnst_add_portal_attr(pdu, pdu_size, 1968 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, 1969 ISNS_PG_PORTAL_PORT_ATTR_ID, 1970 &tip->portal_addr, B_FALSE /* ESI */) != 0) { 1971 rval = 1; 1972 goto pg_done; 1973 } 1974 isnst_remove_from_portal_list(&tip->portal_addr, 1975 null_portal_list); 1976 1977 tip = list_next(&tig->ti_portal_list, tip); 1978 } while (tip != NULL); 1979 1980 pg_done: 1981 return (rval); 1982 } 1983 1984 static int 1985 isnst_add_default_pg(isns_pdu_t *pdu, size_t pdu_size, 1986 avl_tree_t *null_portal_list) 1987 { 1988 isns_portal_t *iportal; 1989 1990 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1991 1992 if (num_default_portals == 0) { 1993 /* 1994 * It is OK for a target with default-portals to be 1995 * online from an STMF perspective and yet all 1996 * default portals are down. if other (non-default) 1997 * portals do exist, we will still announce the target 1998 * to the isns server. In this case, we will specify 1999 * all the active non-default portals as NULL portals. 2000 * This is an OK state. 2001 * 2002 * There is a corner case if non-default portals have 2003 * been marked online but the targets that use them 2004 * are not fully online yet, AND all the default portals 2005 * are down. In this case, the iSNS server will receive 2006 * a DevAttrReg pdu that announces both non-default 2007 * portals and default-portal-only targets. In other 2008 * words, there may be no target that has an active 2009 * portal. The iSNS spec does not forbid this case. 2010 * 2011 * Both of the above cases are somewhat theoretical. 2012 * If the default portals are down we probably cannot 2013 * get any messages through to the iSNS server anyway. 2014 */ 2015 return (0); 2016 } 2017 2018 /* Portal Group Tag */ 2019 if (isnst_add_attr(pdu, pdu_size, 2020 ISNS_PG_TAG_ATTR_ID, 4, 0, ISCSIT_DEFAULT_TPGT) != 0) { 2021 return (1); 2022 } 2023 2024 for (iportal = avl_first(&isns_all_portals); 2025 iportal != NULL; 2026 iportal = AVL_NEXT(&isns_all_portals, iportal)) { 2027 if (iportal->portal_default) { 2028 /* PG Portal Addr and PG Portal Port */ 2029 if (isnst_add_portal_attr(pdu, pdu_size, 2030 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, 2031 ISNS_PG_PORTAL_PORT_ATTR_ID, 2032 &iportal->portal_addr, B_FALSE) != 0) { 2033 return (1); 2034 } 2035 isnst_remove_from_portal_list(&iportal->portal_addr, 2036 null_portal_list); 2037 } 2038 } 2039 2040 return (0); 2041 } 2042 2043 static int 2044 isnst_add_null_pg(isns_pdu_t *pdu, size_t pdu_size, 2045 avl_tree_t *null_portal_list) 2046 { 2047 isns_portal_t *iportal; 2048 2049 /* If all portals accounted for, no NULL PG needed */ 2050 if (avl_numnodes(null_portal_list) == 0) { 2051 return (0); 2052 } 2053 2054 /* NULL Portal Group Tag means no access via these portals. */ 2055 if (isnst_add_attr(pdu, pdu_size, 2056 ISNS_PG_TAG_ATTR_ID, 0, 0, 0) != 0) { 2057 return (1); 2058 } 2059 2060 for (iportal = avl_first(null_portal_list); 2061 iportal != NULL; 2062 iportal = AVL_NEXT(null_portal_list, iportal)) { 2063 if (isnst_add_portal_attr(pdu, pdu_size, 2064 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, 2065 ISNS_PG_PORTAL_PORT_ATTR_ID, 2066 &iportal->portal_addr, B_FALSE) != 0) { 2067 return (1); 2068 } 2069 } 2070 2071 return (0); 2072 } 2073 2074 static int 2075 isnst_add_portal_attr(isns_pdu_t *pdu, size_t pdu_size, 2076 uint32_t ip_attr_id, uint32_t port_attr_id, 2077 struct sockaddr_storage *ss, boolean_t esi_info) 2078 { 2079 struct sockaddr_in *in; 2080 struct sockaddr_in6 *in6; 2081 uint32_t attr_numeric_data; 2082 void *inaddrp; 2083 2084 in = (struct sockaddr_in *)ss; 2085 in6 = (struct sockaddr_in6 *)ss; 2086 2087 ASSERT((ss->ss_family == AF_INET) || (ss->ss_family == AF_INET6)); 2088 2089 if (ss->ss_family == AF_INET) { 2090 attr_numeric_data = sizeof (in_addr_t); 2091 inaddrp = (void *)&in->sin_addr; 2092 } else if (ss->ss_family == AF_INET6) { 2093 attr_numeric_data = sizeof (in6_addr_t); 2094 inaddrp = (void *)&in6->sin6_addr; 2095 } 2096 2097 /* Portal Group Portal IP Address */ 2098 if (isnst_add_attr(pdu, pdu_size, ip_attr_id, 2099 16, inaddrp, attr_numeric_data) != 0) { 2100 return (1); 2101 } 2102 2103 /* Portal Group Portal Port */ 2104 if (isnst_add_attr(pdu, pdu_size, port_attr_id, 2105 4, 0, ntohs(in->sin_port)) != 0) { 2106 return (1); 2107 } 2108 2109 mutex_enter(&esi.esi_mutex); 2110 if (esi_info && esi.esi_valid) { 2111 /* ESI interval and port */ 2112 if (isnst_add_attr(pdu, pdu_size, ISNS_ESI_INTERVAL_ATTR_ID, 4, 2113 NULL, isns_default_esi_interval) != 0) { 2114 return (1); 2115 } 2116 2117 if (isnst_add_attr(pdu, pdu_size, ISNS_ESI_PORT_ATTR_ID, 4, 2118 NULL, esi.esi_port) != 0) { 2119 return (1); 2120 } 2121 } 2122 mutex_exit(&esi.esi_mutex); 2123 2124 return (0); 2125 } 2126 2127 static int 2128 isnst_deregister(iscsit_isns_svr_t *svr, isns_target_t *itarget) 2129 { 2130 int rc; 2131 isns_pdu_t *pdu, *rsp; 2132 size_t pdu_size, rsp_size; 2133 struct sonode *so; 2134 2135 so = isnst_open_so(&svr->svr_sa); 2136 2137 if (so == NULL) { 2138 return (-1); 2139 } 2140 2141 pdu_size = isnst_make_dereg_pdu(svr, &pdu, itarget); 2142 if (pdu_size == 0) { 2143 isnst_close_so(so); 2144 return (-1); 2145 } 2146 2147 rc = isnst_send_pdu(so, pdu); 2148 if (rc != 0) { 2149 isnst_close_so(so); 2150 kmem_free(pdu, pdu_size); 2151 return (rc); 2152 } 2153 2154 rsp_size = isnst_rcv_pdu(so, &rsp); 2155 if (rsp_size == 0) { 2156 isnst_close_so(so); 2157 kmem_free(pdu, pdu_size); 2158 return (-1); 2159 } 2160 2161 rc = isnst_verify_rsp(svr, pdu, rsp, rsp_size); 2162 2163 isnst_close_so(so); 2164 kmem_free(pdu, pdu_size); 2165 kmem_free(rsp, rsp_size); 2166 2167 return (rc); 2168 } 2169 2170 static int 2171 isnst_keepalive(iscsit_isns_svr_t *svr) 2172 { 2173 int rc; 2174 isns_pdu_t *pdu, *rsp; 2175 size_t pdu_size, rsp_size; 2176 struct sonode *so; 2177 2178 so = isnst_open_so(&svr->svr_sa); 2179 2180 if (so == NULL) { 2181 return (-1); 2182 } 2183 2184 pdu_size = isnst_make_keepalive_pdu(svr, &pdu); 2185 if (pdu_size == 0) { 2186 isnst_close_so(so); 2187 return (-1); 2188 } 2189 2190 rc = isnst_send_pdu(so, pdu); 2191 if (rc != 0) { 2192 isnst_close_so(so); 2193 kmem_free(pdu, pdu_size); 2194 return (rc); 2195 } 2196 2197 rsp_size = isnst_rcv_pdu(so, &rsp); 2198 if (rsp_size == 0) { 2199 isnst_close_so(so); 2200 kmem_free(pdu, pdu_size); 2201 return (-1); 2202 } 2203 2204 rc = isnst_verify_rsp(svr, pdu, rsp, rsp_size); 2205 2206 isnst_close_so(so); 2207 kmem_free(pdu, pdu_size); 2208 kmem_free(rsp, rsp_size); 2209 2210 return (rc); 2211 } 2212 2213 static size_t 2214 isnst_make_dereg_pdu(iscsit_isns_svr_t *svr, isns_pdu_t **pdu, 2215 isns_target_t *itarget) 2216 { 2217 size_t pdu_size; 2218 int len; 2219 isns_target_t *src; 2220 2221 /* 2222 * create DevDereg Message with all of target nodes 2223 */ 2224 pdu_size = isnst_create_pdu_header(ISNS_DEV_DEREG, pdu, 0); 2225 if (pdu_size == 0) { 2226 return (0); 2227 } 2228 2229 /* 2230 * Source attribute - Must be a storage node in the same 2231 * network entity. 2232 */ 2233 if (svr->svr_registered) { 2234 src = isnst_get_registered_source(svr); 2235 } else if (itarget != NULL) { 2236 src = itarget; 2237 } else { 2238 goto dereg_pdu_error; 2239 } 2240 2241 len = strlen(src->target_info->ti_tgt_name) + 1; 2242 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 2243 len, src->target_info->ti_tgt_name, 0) != 0) { 2244 goto dereg_pdu_error; 2245 } 2246 2247 2248 /* Delimiter */ 2249 if (isnst_add_attr(*pdu, pdu_size, ISNS_DELIMITER_ATTR_ID, 2250 0, 0, 0) != 0) { 2251 goto dereg_pdu_error; 2252 } 2253 2254 /* 2255 * Operating attributes 2256 */ 2257 if (itarget == NULL) { 2258 /* dereg everything */ 2259 len = strlen(isns_eid) + 1; 2260 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID, 2261 len, isns_eid, 0) != 0) { 2262 goto dereg_pdu_error; 2263 } 2264 } else { 2265 /* dereg one target only */ 2266 len = strlen(itarget->target_info->ti_tgt_name) + 1; 2267 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 2268 len, itarget->target_info->ti_tgt_name, 0) != 0) { 2269 goto dereg_pdu_error; 2270 } 2271 } 2272 2273 return (pdu_size); 2274 2275 dereg_pdu_error: 2276 kmem_free(*pdu, pdu_size); 2277 *pdu = NULL; 2278 2279 return (0); 2280 } 2281 2282 static size_t 2283 isnst_make_keepalive_pdu(iscsit_isns_svr_t *svr, isns_pdu_t **pdu) 2284 { 2285 size_t pdu_size; 2286 int len; 2287 isns_target_t *src; 2288 2289 ASSERT(svr->svr_registered); 2290 2291 /* 2292 * create DevAttrQuery Message 2293 */ 2294 pdu_size = isnst_create_pdu_header(ISNS_DEV_ATTR_QRY, pdu, 0); 2295 if (pdu_size == 0) { 2296 return (0); 2297 } 2298 2299 /* 2300 * Source attribute - Must be a iscsi target in the same 2301 * network entity. 2302 */ 2303 src = isnst_get_registered_source(svr); 2304 2305 len = strlen(src->target_info->ti_tgt_name) + 1; 2306 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 2307 len, src->target_info->ti_tgt_name, 0) != 0) { 2308 goto keepalive_pdu_error; 2309 } 2310 2311 /* EID */ 2312 len = strlen(isns_eid) + 1; 2313 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID, 2314 len, isns_eid, 0) != 0) { 2315 goto keepalive_pdu_error; 2316 } 2317 /* Delimiter */ 2318 if (isnst_add_attr(*pdu, pdu_size, ISNS_DELIMITER_ATTR_ID, 2319 0, 0, 0) != 0) { 2320 goto keepalive_pdu_error; 2321 } 2322 2323 /* Values to Fetch -- EID */ 2324 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID, 2325 0, 0, 0) != 0) { 2326 goto keepalive_pdu_error; 2327 } 2328 2329 2330 return (pdu_size); 2331 2332 keepalive_pdu_error: 2333 kmem_free(*pdu, pdu_size); 2334 *pdu = NULL; 2335 2336 return (0); 2337 } 2338 2339 static isns_target_t * 2340 isnst_get_registered_source(iscsit_isns_svr_t *svr) 2341 { 2342 isns_target_t *itarget; 2343 2344 /* 2345 * If svr is registered, then there must be at least one 2346 * target that is registered to that svr. 2347 */ 2348 ASSERT(svr->svr_registered); 2349 ASSERT((avl_numnodes(&svr->svr_target_list) != 0)); 2350 2351 itarget = avl_first(&svr->svr_target_list); 2352 do { 2353 if (itarget->target_registered == B_TRUE) 2354 break; 2355 itarget = AVL_NEXT(&svr->svr_target_list, itarget); 2356 } while (itarget != NULL); 2357 ASSERT(itarget != NULL); 2358 return (itarget); 2359 } 2360 2361 static int 2362 isnst_verify_rsp(iscsit_isns_svr_t *svr, isns_pdu_t *pdu, 2363 isns_pdu_t *rsp, size_t rsp_size) 2364 { 2365 uint16_t func_id; 2366 int payload_len, rsp_payload_len; 2367 int status; 2368 isns_resp_t *resp; 2369 uint8_t *pp; 2370 isns_tlv_t *attr; 2371 uint32_t attr_len, attr_id, esi_interval; 2372 2373 /* 2374 * Ensure we have at least a valid header (don't count the 2375 * "payload" field. 2376 */ 2377 if (rsp_size < offsetof(isns_pdu_t, payload)) { 2378 ISNST_LOG(CE_WARN, "Invalid iSNS PDU header, %d of %d bytes", 2379 (int)rsp_size, (int)offsetof(isns_pdu_t, payload)); 2380 return (-1); 2381 } 2382 2383 /* Make sure we have the amount of data that the header specifies */ 2384 payload_len = ntohs(rsp->payload_len); 2385 if (rsp_size < (payload_len + offsetof(isns_pdu_t, payload))) { 2386 ISNST_LOG(CE_WARN, "Invalid iSNS response, %d of %d bytes", 2387 (int)rsp_size, 2388 (int)(payload_len + offsetof(isns_pdu_t, payload))); 2389 return (-1); 2390 } 2391 2392 /* Find the start of all operational parameters */ 2393 rsp_payload_len = isnst_pdu_get_op(rsp, &pp); 2394 /* 2395 * Make sure isnst_pdu_get_op didn't encounter an error 2396 * in the attributes. 2397 */ 2398 if (pp == NULL) { 2399 return (-1); 2400 } 2401 2402 /* verify response transaction id */ 2403 if (ntohs(rsp->xid) != ntohs(pdu->xid)) { 2404 return (-1); 2405 } 2406 2407 /* check the error code */ 2408 resp = (isns_resp_t *)((void *)&rsp->payload[0]); 2409 2410 status = ntohl(resp->status); 2411 2412 /* validate response function id */ 2413 func_id = ntohs(rsp->func_id); 2414 switch (ntohs(pdu->func_id)) { 2415 case ISNS_DEV_ATTR_REG: 2416 if (func_id != ISNS_DEV_ATTR_REG_RSP) { 2417 return (-1); 2418 } 2419 2420 /* Only look through response if msg status says OK */ 2421 if (status != 0) { 2422 break; 2423 } 2424 /* 2425 * Get the ESI interval returned by the server. It could 2426 * be different than what we asked for. We never know which 2427 * portal a request may come in on, and any server could demand 2428 * any interval. We'll simply keep track of the largest 2429 * interval for use in monitoring. 2430 */ 2431 2432 attr = (isns_tlv_t *)((void *)pp); 2433 while (rsp_payload_len >= 8) { 2434 attr_len = ntohl(attr->attr_len); 2435 attr_id = ntohl(attr->attr_id); 2436 if (attr_id == ISNS_ESI_INTERVAL_ATTR_ID) { 2437 if (attr_len != 4 || 2438 attr_len > rsp_payload_len - 8) { 2439 /* Mal-formed packet */ 2440 break; 2441 } 2442 esi_interval = 2443 ntohl(*((uint32_t *) 2444 ((void *)(&attr->attr_value)))); 2445 2446 if (esi_interval > svr->svr_esi_interval) 2447 svr->svr_esi_interval = esi_interval; 2448 2449 break; 2450 } 2451 rsp_payload_len -= (8 + attr_len); 2452 attr = (isns_tlv_t *) 2453 ((void *)((uint8_t *)attr + attr_len + 8)); 2454 } 2455 2456 break; 2457 case ISNS_DEV_DEREG: 2458 if (func_id != ISNS_DEV_DEREG_RSP) { 2459 return (-1); 2460 } 2461 break; 2462 case ISNS_DEV_ATTR_QRY: 2463 /* Keepalive Response */ 2464 if (func_id != ISNS_DEV_ATTR_QRY_RSP) { 2465 return (-1); 2466 } 2467 2468 if (status == 0) { 2469 boolean_t found_eid = B_FALSE; 2470 2471 /* Scan the operational parameters */ 2472 attr = (isns_tlv_t *)((void *)pp); 2473 while (rsp_payload_len >= 8) { 2474 attr_len = ntohl(attr->attr_len); 2475 attr_id = ntohl(attr->attr_id); 2476 if (attr_id == ISNS_EID_ATTR_ID && 2477 attr_len > 0 && 2478 attr_len <= rsp_payload_len - 8) { 2479 /* 2480 * If the isns server knows us, the 2481 * response will include our EID in 2482 * the operational parameters, i.e. 2483 * after the delimiter. 2484 * Just receiving this pattern 2485 * is good enough to tell the isns 2486 * server still knows us. 2487 */ 2488 found_eid = B_TRUE; 2489 break; 2490 } 2491 2492 rsp_payload_len -= (8 + attr_len); 2493 attr = (isns_tlv_t *) 2494 ((void *)((uint8_t *)attr + attr_len + 8)); 2495 } 2496 if (! found_eid) { 2497 status = ISNS_RSP_NO_SUCH_ENTRY; 2498 } 2499 } 2500 if (status == ISNS_RSP_NO_SUCH_ENTRY) { 2501 char server_buf[IDM_SA_NTOP_BUFSIZ]; 2502 /* 2503 * The iSNS server has forgotten about us. 2504 * We will re-register everything. 2505 * This can happen e.g. if ESI probes time out, 2506 * or if the iSNS server does a factory reset. 2507 */ 2508 ISNST_LOG(CE_WARN, "iscsit: iSNS server %s" 2509 " forgot about us and has to be reminded.", 2510 idm_sa_ntop(&svr->svr_sa, 2511 server_buf, sizeof (server_buf))); 2512 /* isnst_retry_registration will trigger the reset */ 2513 } 2514 2515 break; 2516 2517 default: 2518 ASSERT(0); 2519 break; 2520 } 2521 2522 /* Update the last time we heard from this server */ 2523 if (status == 0) { 2524 svr->svr_last_msg = ddi_get_lbolt(); 2525 } 2526 2527 2528 2529 return (status); 2530 } 2531 2532 static uint16_t 2533 isnst_pdu_get_op(isns_pdu_t *pdu, uint8_t **pp) 2534 { 2535 uint8_t *payload; 2536 uint16_t payload_len; 2537 isns_resp_t *resp; 2538 isns_tlv_t *attr; 2539 uint32_t attr_id; 2540 uint32_t tlv_len; 2541 2542 /* get payload */ 2543 payload_len = ntohs(pdu->payload_len); 2544 resp = (isns_resp_t *)((void *)&pdu->payload[0]); 2545 2546 /* find the operating attributes */ 2547 if (payload_len < sizeof (resp->status)) { 2548 ISNST_LOG(CE_WARN, "Invalid iSNS response, %d payload bytes", 2549 payload_len); 2550 *pp = NULL; 2551 return (0); 2552 } 2553 2554 payload_len -= sizeof (resp->status); 2555 payload = &resp->data[0]; 2556 2557 while (payload_len >= (sizeof (isns_tlv_t) - 1)) { 2558 attr = (isns_tlv_t *)((void *)payload); 2559 tlv_len = offsetof(isns_tlv_t, attr_value) + 2560 ntohl(attr->attr_len); 2561 if (payload_len >= tlv_len) { 2562 payload += tlv_len; 2563 payload_len -= tlv_len; 2564 attr_id = ntohl(attr->attr_id); 2565 if (attr_id == ISNS_DELIMITER_ATTR_ID) { 2566 break; 2567 } 2568 } else { 2569 /* mal-formed packet */ 2570 payload = NULL; 2571 payload_len = 0; 2572 } 2573 } 2574 2575 *pp = payload; 2576 2577 return (payload_len); 2578 } 2579 2580 static size_t 2581 isnst_create_pdu_header(uint16_t func_id, isns_pdu_t **pdu, uint16_t flags) 2582 { 2583 size_t pdu_size = isns_message_buf_size; 2584 2585 *pdu = (isns_pdu_t *)kmem_zalloc(pdu_size, KM_NOSLEEP); 2586 if (*pdu != NULL) { 2587 (*pdu)->version = htons((uint16_t)ISNSP_VERSION); 2588 (*pdu)->func_id = htons((uint16_t)func_id); 2589 (*pdu)->payload_len = htons(0); 2590 (*pdu)->flags = htons(flags); 2591 2592 (*pdu)->xid = htons(GET_XID()); 2593 (*pdu)->seq = htons(0); 2594 } else { 2595 pdu_size = 0; 2596 } 2597 2598 return (pdu_size); 2599 } 2600 2601 static int 2602 isnst_add_attr(isns_pdu_t *pdu, 2603 size_t max_pdu_size, 2604 uint32_t attr_id, 2605 uint32_t attr_len, 2606 void *attr_data, 2607 uint32_t attr_numeric_data) 2608 { 2609 isns_tlv_t *attr_tlv; 2610 uint8_t *payload_ptr; 2611 uint16_t payload_len; 2612 uint32_t normalized_attr_len; 2613 uint64_t attr_tlv_len; 2614 2615 /* The attribute length must be 4-byte aligned. Section 5.1.3. */ 2616 normalized_attr_len = (attr_len % 4) == 0 ? 2617 (attr_len) : (attr_len + (4 - (attr_len % 4))); 2618 attr_tlv_len = ISNS_TLV_ATTR_ID_LEN + 2619 ISNS_TLV_ATTR_LEN_LEN + normalized_attr_len; 2620 2621 /* Check if we are going to exceed the maximum PDU length. */ 2622 payload_len = ntohs(pdu->payload_len); 2623 if ((payload_len + attr_tlv_len) > max_pdu_size) { 2624 return (1); 2625 } 2626 2627 attr_tlv = (isns_tlv_t *)kmem_zalloc(attr_tlv_len, KM_SLEEP); 2628 2629 attr_tlv->attr_id = htonl(attr_id); 2630 2631 switch (attr_id) { 2632 case ISNS_DELIMITER_ATTR_ID: 2633 break; 2634 2635 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 2636 case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: 2637 if (attr_numeric_data == sizeof (in_addr_t)) { 2638 /* IPv4 */ 2639 attr_tlv->attr_value[10] = 0xFF; 2640 attr_tlv->attr_value[11] = 0xFF; 2641 bcopy(attr_data, ((attr_tlv->attr_value) + 12), 2642 sizeof (in_addr_t)); 2643 } else if (attr_numeric_data == sizeof (in6_addr_t)) { 2644 /* IPv6 */ 2645 bcopy(attr_data, attr_tlv->attr_value, 2646 sizeof (in6_addr_t)); 2647 } else if (attr_numeric_data == 0) { 2648 /* EMPTY */ 2649 /* Do nothing */ 2650 } else { 2651 kmem_free(attr_tlv, attr_tlv_len); 2652 attr_tlv = NULL; 2653 return (1); 2654 } 2655 break; 2656 2657 case ISNS_EID_ATTR_ID: 2658 case ISNS_ISCSI_NAME_ATTR_ID: 2659 case ISNS_ISCSI_ALIAS_ATTR_ID: 2660 case ISNS_PG_ISCSI_NAME_ATTR_ID: 2661 if (attr_len && attr_data) { 2662 bcopy((char *)attr_data, 2663 attr_tlv->attr_value, attr_len); 2664 } 2665 break; 2666 2667 default: 2668 if (attr_len == 8) { 2669 *(uint64_t *)((void *)attr_tlv->attr_value) = 2670 BE_64((uint64_t)attr_numeric_data); 2671 } else if (attr_len == 4) { 2672 *(uint32_t *)((void *)attr_tlv->attr_value) = 2673 htonl((uint32_t)attr_numeric_data); 2674 } 2675 break; 2676 } 2677 2678 attr_tlv->attr_len = htonl(normalized_attr_len); 2679 /* 2680 * Convert the network byte ordered payload length to host byte 2681 * ordered for local address calculation. 2682 */ 2683 payload_len = ntohs(pdu->payload_len); 2684 payload_ptr = pdu->payload + payload_len; 2685 bcopy(attr_tlv, payload_ptr, attr_tlv_len); 2686 payload_len += attr_tlv_len; 2687 2688 /* 2689 * Convert the host byte ordered payload length back to network 2690 * byte ordered - it's now ready to be sent on the wire. 2691 */ 2692 pdu->payload_len = htons(payload_len); 2693 2694 kmem_free(attr_tlv, attr_tlv_len); 2695 attr_tlv = NULL; 2696 2697 return (0); 2698 } 2699 2700 static void 2701 isnst_so_timeout(void *so) 2702 { 2703 /* Wake up any sosend or sorecv blocked on this socket */ 2704 idm_soshutdown(so); 2705 } 2706 2707 static int 2708 isnst_send_pdu(void *so, isns_pdu_t *pdu) 2709 { 2710 size_t total_len, payload_len, send_len; 2711 uint8_t *payload; 2712 uint16_t flags, seq; 2713 timeout_id_t send_timer; 2714 iovec_t iov[2]; 2715 int rc; 2716 2717 /* update pdu flags */ 2718 flags = ntohs(pdu->flags); 2719 flags |= ISNS_FLAG_CLIENT; 2720 flags |= ISNS_FLAG_FIRST_PDU; 2721 2722 /* initalize sequence number */ 2723 seq = 0; 2724 2725 payload = pdu->payload; 2726 2727 /* total payload length */ 2728 total_len = ntohs(pdu->payload_len); 2729 2730 /* fill in the pdu header */ 2731 iov[0].iov_base = (void *)pdu; 2732 iov[0].iov_len = ISNSP_HEADER_SIZE; 2733 2734 do { 2735 /* split the payload accordingly */ 2736 if (total_len > ISNSP_MAX_PAYLOAD_SIZE) { 2737 payload_len = ISNSP_MAX_PAYLOAD_SIZE; 2738 } else { 2739 payload_len = total_len; 2740 /* set the last pdu flag */ 2741 flags |= ISNS_FLAG_LAST_PDU; 2742 } 2743 2744 /* set back the pdu flags */ 2745 pdu->flags = htons(flags); 2746 /* set the sequence number */ 2747 pdu->seq = htons(seq); 2748 /* set the payload length */ 2749 pdu->payload_len = htons(payload_len); 2750 2751 /* fill in the payload */ 2752 iov[1].iov_base = (void *)payload; 2753 iov[1].iov_len = payload_len; 2754 2755 DTRACE_PROBE3(isnst__pdu__send, uint16_t, ntohs(pdu->func_id), 2756 uint16_t, ntohs(pdu->payload_len), caddr_t, pdu); 2757 2758 /* send the pdu */ 2759 send_len = ISNSP_HEADER_SIZE + payload_len; 2760 send_timer = timeout(isnst_so_timeout, so, 2761 drv_usectohz(isns_timeout_usec)); 2762 rc = idm_iov_sosend(so, &iov[0], 2, send_len); 2763 (void) untimeout(send_timer); 2764 2765 flags &= ~ISNS_FLAG_FIRST_PDU; 2766 payload += payload_len; 2767 total_len -= payload_len; 2768 2769 /* increase the sequence number */ 2770 seq ++; 2771 2772 } while (rc == 0 && total_len > 0); 2773 2774 return (rc); 2775 } 2776 2777 static size_t 2778 isnst_rcv_pdu(void *so, isns_pdu_t **pdu) 2779 { 2780 size_t total_pdu_len; 2781 size_t total_payload_len; 2782 size_t payload_len; 2783 size_t combined_len; 2784 isns_pdu_t tmp_pdu_hdr; 2785 isns_pdu_t *combined_pdu; 2786 uint8_t *payload; 2787 uint8_t *combined_payload; 2788 timeout_id_t rcv_timer; 2789 uint16_t flags; 2790 uint16_t seq; 2791 2792 *pdu = NULL; 2793 total_pdu_len = total_payload_len = 0; 2794 payload = NULL; 2795 seq = 0; 2796 2797 do { 2798 /* receive the pdu header */ 2799 rcv_timer = timeout(isnst_so_timeout, so, 2800 drv_usectohz(isns_timeout_usec)); 2801 if (idm_sorecv(so, &tmp_pdu_hdr, ISNSP_HEADER_SIZE) != 0 || 2802 ntohs(tmp_pdu_hdr.seq) != seq) { 2803 (void) untimeout(rcv_timer); 2804 goto rcv_error; 2805 } 2806 (void) untimeout(rcv_timer); 2807 2808 /* receive the payload */ 2809 payload_len = ntohs(tmp_pdu_hdr.payload_len); 2810 if (payload_len > ISNST_MAX_MSG_SIZE) { 2811 goto rcv_error; 2812 } 2813 payload = kmem_alloc(payload_len, KM_NOSLEEP); 2814 if (payload == NULL) { 2815 goto rcv_error; 2816 } 2817 rcv_timer = timeout(isnst_so_timeout, so, 2818 drv_usectohz(ISNS_RCV_TIMER_SECONDS * 1000000)); 2819 if (idm_sorecv(so, payload, payload_len) != 0) { 2820 (void) untimeout(rcv_timer); 2821 goto rcv_error; 2822 } 2823 (void) untimeout(rcv_timer); 2824 2825 /* combine the pdu if it is not the first one */ 2826 if (total_pdu_len > 0) { 2827 combined_len = total_pdu_len + payload_len; 2828 combined_pdu = kmem_alloc(combined_len, KM_SLEEP); 2829 if (combined_pdu == NULL) { 2830 goto rcv_error; 2831 } 2832 bcopy(*pdu, combined_pdu, total_pdu_len); 2833 combined_payload = 2834 &combined_pdu->payload[total_payload_len]; 2835 bcopy(payload, combined_payload, payload_len); 2836 kmem_free(*pdu, total_pdu_len); 2837 kmem_free(payload, payload_len); 2838 *pdu = combined_pdu; 2839 total_payload_len += payload_len; 2840 total_pdu_len += payload_len; 2841 (*pdu)->payload_len = htons(total_payload_len); 2842 } else { 2843 total_payload_len = payload_len; 2844 total_pdu_len = ISNSP_HEADER_SIZE + payload_len; 2845 *pdu = kmem_alloc(total_pdu_len, KM_NOSLEEP); 2846 if (*pdu == NULL) { 2847 goto rcv_error; 2848 } 2849 bcopy(&tmp_pdu_hdr, *pdu, ISNSP_HEADER_SIZE); 2850 bcopy(payload, &(*pdu)->payload[0], payload_len); 2851 kmem_free(payload, payload_len); 2852 } 2853 payload = NULL; 2854 2855 /* the flags of pdu which is just received */ 2856 flags = ntohs(tmp_pdu_hdr.flags); 2857 2858 /* increase sequence number by one */ 2859 seq ++; 2860 } while ((flags & ISNS_FLAG_LAST_PDU) == 0); 2861 2862 DTRACE_PROBE3(isnst__pdu__recv, uint16_t, ntohs((*pdu)->func_id), 2863 size_t, total_payload_len, caddr_t, *pdu); 2864 2865 return (total_pdu_len); 2866 2867 rcv_error: 2868 if (*pdu != NULL) { 2869 kmem_free(*pdu, total_pdu_len); 2870 *pdu = NULL; 2871 } 2872 if (payload != NULL) { 2873 kmem_free(payload, payload_len); 2874 } 2875 return (0); 2876 } 2877 2878 static void * 2879 isnst_open_so(struct sockaddr_storage *sa) 2880 { 2881 int sa_sz; 2882 ksocket_t so; 2883 2884 /* determin local IP address */ 2885 if (sa->ss_family == AF_INET) { 2886 /* IPv4 */ 2887 sa_sz = sizeof (struct sockaddr_in); 2888 2889 /* Create socket */ 2890 so = idm_socreate(AF_INET, SOCK_STREAM, 0); 2891 } else { 2892 /* IPv6 */ 2893 sa_sz = sizeof (struct sockaddr_in6); 2894 2895 /* Create socket */ 2896 so = idm_socreate(AF_INET6, SOCK_STREAM, 0); 2897 } 2898 2899 if (so != NULL) { 2900 if (idm_so_timed_socket_connect(so, sa, sa_sz, 2901 isns_timeout_usec) != 0) { 2902 /* not calling isnst_close_so() to */ 2903 /* make dtrace output look clear */ 2904 idm_soshutdown(so); 2905 idm_sodestroy(so); 2906 so = NULL; 2907 } 2908 } 2909 2910 if (so == NULL) { 2911 char server_buf[IDM_SA_NTOP_BUFSIZ]; 2912 ISNST_LOG(CE_WARN, "open iSNS Server %s failed", 2913 idm_sa_ntop(sa, server_buf, 2914 sizeof (server_buf))); 2915 DTRACE_PROBE1(isnst__connect__fail, 2916 struct sockaddr_storage *, sa); 2917 } 2918 2919 return (so); 2920 } 2921 2922 static void 2923 isnst_close_so(void *so) 2924 { 2925 idm_soshutdown(so); 2926 idm_sodestroy(so); 2927 } 2928 2929 /* 2930 * ESI handling 2931 */ 2932 2933 static void 2934 isnst_esi_start(void) 2935 { 2936 if (isns_use_esi == B_FALSE) { 2937 ISNST_LOG(CE_NOTE, "ESI disabled by isns_use_esi=FALSE"); 2938 return; 2939 } 2940 2941 ISNST_LOG(CE_NOTE, "isnst_esi_start"); 2942 2943 mutex_enter(&esi.esi_mutex); 2944 ASSERT(esi.esi_enabled == B_FALSE); 2945 ASSERT(esi.esi_thread_running == B_FALSE); 2946 2947 esi.esi_enabled = B_TRUE; 2948 esi.esi_valid = B_FALSE; 2949 esi.esi_thread = thread_create(NULL, 0, isnst_esi_thread, 2950 (void *)&esi, 0, &p0, TS_RUN, minclsyspri); 2951 2952 /* 2953 * Wait for the thread to start 2954 */ 2955 while (!esi.esi_thread_running) { 2956 cv_wait(&esi.esi_cv, &esi.esi_mutex); 2957 } 2958 mutex_exit(&esi.esi_mutex); 2959 } 2960 2961 static void 2962 isnst_esi_stop() 2963 { 2964 ISNST_LOG(CE_NOTE, "isnst_esi_stop"); 2965 2966 /* Shutdown ESI listening socket, wait for thread to terminate */ 2967 mutex_enter(&esi.esi_mutex); 2968 if (esi.esi_enabled) { 2969 esi.esi_enabled = B_FALSE; 2970 if (esi.esi_valid) { 2971 idm_soshutdown(esi.esi_so); 2972 idm_sodestroy(esi.esi_so); 2973 } 2974 mutex_exit(&esi.esi_mutex); 2975 thread_join(esi.esi_thread_did); 2976 } else { 2977 mutex_exit(&esi.esi_mutex); 2978 } 2979 } 2980 2981 /* 2982 * isnst_esi_thread 2983 * 2984 * This function listens on a socket for incoming connections from an 2985 * iSNS server until told to stop. 2986 */ 2987 2988 /*ARGSUSED*/ 2989 static void 2990 isnst_esi_thread(void *arg) 2991 { 2992 ksocket_t newso; 2993 struct sockaddr_in6 sin6; 2994 socklen_t sin_addrlen; 2995 uint32_t on = 1; 2996 int rc; 2997 isns_pdu_t *pdu; 2998 size_t pl_size; 2999 3000 bzero(&sin6, sizeof (struct sockaddr_in6)); 3001 sin_addrlen = sizeof (struct sockaddr_in6); 3002 3003 esi.esi_thread_did = curthread->t_did; 3004 3005 mutex_enter(&esi.esi_mutex); 3006 3007 /* 3008 * Mark the thread as running and the portal as no longer new. 3009 */ 3010 esi.esi_thread_running = B_TRUE; 3011 cv_signal(&esi.esi_cv); 3012 3013 while (esi.esi_enabled) { 3014 /* 3015 * Create a socket to listen for requests from the iSNS server. 3016 */ 3017 if ((esi.esi_so = idm_socreate(PF_INET6, SOCK_STREAM, 0)) == 3018 NULL) { 3019 ISNST_LOG(CE_WARN, 3020 "isnst_esi_thread: Unable to create socket"); 3021 mutex_exit(&esi.esi_mutex); 3022 delay(drv_usectohz(1000000)); 3023 mutex_enter(&esi.esi_mutex); 3024 continue; 3025 } 3026 3027 /* 3028 * Set options, bind, and listen until we're told to stop 3029 */ 3030 bzero(&sin6, sizeof (sin6)); 3031 sin6.sin6_family = AF_INET6; 3032 sin6.sin6_port = htons(0); 3033 sin6.sin6_addr = in6addr_any; 3034 3035 (void) ksocket_setsockopt(esi.esi_so, SOL_SOCKET, 3036 SO_REUSEADDR, (char *)&on, sizeof (on), CRED()); 3037 3038 if (ksocket_bind(esi.esi_so, (struct sockaddr *)&sin6, 3039 sizeof (sin6), CRED()) != 0) { 3040 ISNST_LOG(CE_WARN, "Unable to bind socket for ESI"); 3041 idm_sodestroy(esi.esi_so); 3042 mutex_exit(&esi.esi_mutex); 3043 delay(drv_usectohz(1000000)); 3044 mutex_enter(&esi.esi_mutex); 3045 continue; 3046 } 3047 3048 /* 3049 * Get the port (sin6 is meaningless at this point) 3050 */ 3051 (void) ksocket_getsockname(esi.esi_so, 3052 (struct sockaddr *)(&sin6), &sin_addrlen, CRED()); 3053 esi.esi_port = 3054 ntohs(((struct sockaddr_in6 *)(&sin6))->sin6_port); 3055 3056 if ((rc = ksocket_listen(esi.esi_so, 5, CRED())) != 0) { 3057 ISNST_LOG(CE_WARN, "isnst_esi_thread: listen " 3058 "failure 0x%x", rc); 3059 idm_sodestroy(esi.esi_so); 3060 mutex_exit(&esi.esi_mutex); 3061 delay(drv_usectohz(1000000)); 3062 mutex_enter(&esi.esi_mutex); 3063 continue; 3064 } 3065 3066 ksocket_hold(esi.esi_so); 3067 esi.esi_valid = B_TRUE; 3068 while (esi.esi_enabled) { 3069 mutex_exit(&esi.esi_mutex); 3070 3071 DTRACE_PROBE3(iscsit__isns__esi__accept__wait, 3072 boolean_t, esi.esi_enabled, 3073 ksocket_t, esi.esi_so, 3074 struct sockaddr_in6, &sin6); 3075 if ((rc = ksocket_accept(esi.esi_so, NULL, NULL, 3076 &newso, CRED())) != 0) { 3077 mutex_enter(&esi.esi_mutex); 3078 DTRACE_PROBE2(iscsit__isns__esi__accept__fail, 3079 int, rc, boolean_t, esi.esi_enabled); 3080 /* 3081 * If we were interrupted with EINTR 3082 * it's not really a failure. 3083 */ 3084 ISNST_LOG(CE_WARN, "isnst_esi_thread: " 3085 "accept failure (0x%x)", rc); 3086 3087 delay(drv_usectohz(100000)); 3088 if (rc == EINTR) { 3089 continue; 3090 } else { 3091 break; 3092 } 3093 } 3094 DTRACE_PROBE2(iscsit__isns__esi__accept, 3095 boolean_t, esi.esi_enabled, 3096 ksocket_t, newso); 3097 3098 pl_size = isnst_rcv_pdu(newso, &pdu); 3099 if (pl_size == 0) { 3100 ISNST_LOG(CE_WARN, "isnst_esi_thread: " 3101 "rcv_pdu failure"); 3102 (void) ksocket_close(newso, CRED()); 3103 3104 mutex_enter(&esi.esi_mutex); 3105 continue; 3106 } 3107 3108 isnst_handle_esi_req(newso, pdu, pl_size); 3109 3110 (void) ksocket_close(newso, CRED()); 3111 3112 mutex_enter(&esi.esi_mutex); 3113 } 3114 3115 idm_soshutdown(esi.esi_so); 3116 ksocket_rele(esi.esi_so); 3117 esi.esi_valid = B_FALSE; 3118 3119 /* 3120 * If we're going to try to re-establish the listener then 3121 * destroy this socket. Otherwise isnst_esi_stop already 3122 * destroyed it. 3123 */ 3124 if (esi.esi_enabled) 3125 idm_sodestroy(esi.esi_so); 3126 } 3127 3128 esi.esi_thread_running = B_FALSE; 3129 cv_signal(&esi.esi_cv); 3130 mutex_exit(&esi.esi_mutex); 3131 esi_thread_exit: 3132 thread_exit(); 3133 } 3134 3135 /* 3136 * Handle an incoming ESI request 3137 */ 3138 3139 static void 3140 isnst_handle_esi_req(ksocket_t ks, isns_pdu_t *pdu, size_t pdu_size) 3141 { 3142 isns_pdu_t *rsp_pdu; 3143 isns_resp_t *rsp; 3144 isns_tlv_t *attr; 3145 uint32_t attr_len, attr_id; 3146 size_t req_pl_len, rsp_size, tlv_len; 3147 struct sockaddr_storage portal_ss; 3148 struct sockaddr_storage server_ss; 3149 struct sockaddr_in6 *portal_addr6; 3150 boolean_t portal_addr_valid = B_FALSE; 3151 boolean_t portal_port_valid = B_FALSE; 3152 uint32_t esi_response = ISNS_RSP_SUCCESSFUL; 3153 isns_portal_t *iportal; 3154 socklen_t sa_len; 3155 3156 3157 if (ntohs(pdu->func_id) != ISNS_ESI) { 3158 ISNST_LOG(CE_WARN, "isnst_handle_esi_req: Unexpected func 0x%x", 3159 pdu->func_id); 3160 kmem_free(pdu, pdu_size); 3161 return; 3162 } 3163 3164 req_pl_len = ntohs(pdu->payload_len); 3165 if (req_pl_len + offsetof(isns_pdu_t, payload) > pdu_size) { 3166 ISNST_LOG(CE_WARN, "isnst_handle_esi_req: " 3167 "payload exceeds PDU size (%d > %d)", 3168 (int)(req_pl_len + offsetof(isns_pdu_t, payload)), 3169 (int)pdu_size); 3170 /* Not all data is present -- ignore */ 3171 kmem_free(pdu, pdu_size); 3172 return; 3173 } 3174 3175 if (req_pl_len + sizeof (uint32_t) > ISNSP_MAX_PAYLOAD_SIZE) { 3176 ISNST_LOG(CE_WARN, 3177 "isnst_handle_esi_req: PDU payload exceeds max (%ld bytes)", 3178 req_pl_len + sizeof (uint32_t)); 3179 kmem_free(pdu, pdu_size); 3180 return; 3181 } 3182 3183 /* 3184 * Check portal in ESI request and make sure it is valid. Return 3185 * esi_response of ISNS_RSP_SUCCESSFUL if valid, otherwise don't 3186 * respond at all. Get IP addr and port. Format of ESI 3187 * is: 3188 * 3189 * ISNS_TIMESTAMP_ATTR_ID, 3190 * ISNS_EID_ATTR_ID, 3191 * ISNS_PORTAL_IP_ADDR_ATTR_ID, 3192 * ISNS_PORTAL_PORT_ATTR_ID 3193 */ 3194 bzero(&portal_ss, sizeof (struct sockaddr_storage)); 3195 portal_ss.ss_family = AF_INET6; 3196 portal_addr6 = (struct sockaddr_in6 *)&portal_ss; 3197 attr = (isns_tlv_t *)((void *)&pdu->payload); 3198 attr_len = ntohl(attr->attr_len); 3199 attr_id = ntohl(attr->attr_id); 3200 tlv_len = attr_len + offsetof(isns_tlv_t, attr_value); 3201 while (tlv_len <= req_pl_len) { 3202 switch (attr_id) { 3203 case ISNS_TIMESTAMP_ATTR_ID: 3204 break; 3205 case ISNS_EID_ATTR_ID: 3206 break; 3207 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 3208 if (attr_len > sizeof (struct in6_addr)) { 3209 /* Bad attribute format */ 3210 esi_response = ISNS_RSP_MSG_FORMAT_ERROR; 3211 } else { 3212 portal_addr6->sin6_family = AF_INET6; 3213 attr_len = min(attr_len, 3214 sizeof (portal_addr6->sin6_addr)); 3215 bcopy(attr->attr_value, 3216 portal_addr6->sin6_addr.s6_addr, attr_len); 3217 portal_addr_valid = B_TRUE; 3218 } 3219 break; 3220 case ISNS_PORTAL_PORT_ATTR_ID: 3221 if (attr_len > sizeof (uint32_t)) { 3222 /* Bad attribute format */ 3223 esi_response = ISNS_RSP_MSG_FORMAT_ERROR; 3224 } else { 3225 portal_addr6->sin6_port = 3226 htons((uint16_t)BE_IN32(attr->attr_value)); 3227 portal_port_valid = B_TRUE; 3228 } 3229 break; 3230 default: 3231 /* Bad request format */ 3232 esi_response = ISNS_RSP_MSG_FORMAT_ERROR; 3233 break; 3234 } 3235 3236 /* If we've set an error then stop processing */ 3237 if (esi_response != ISNS_RSP_SUCCESSFUL) { 3238 break; 3239 } 3240 3241 /* Get next attribute */ 3242 req_pl_len -= tlv_len; 3243 attr = (isns_tlv_t *)((void *)((uint8_t *)attr + tlv_len)); 3244 attr_len = ntohl(attr->attr_len); 3245 attr_id = ntohl(attr->attr_id); 3246 tlv_len = attr_len + offsetof(isns_tlv_t, attr_value); 3247 } 3248 3249 if (!portal_port_valid) 3250 portal_addr6->sin6_port = htons(ISCSI_LISTEN_PORT); 3251 3252 if (!portal_addr_valid) { 3253 esi_response = ISNS_RSP_MSG_FORMAT_ERROR; 3254 } 3255 3256 /* 3257 * If we've detected an error or if the portal does not 3258 * exist then drop the request. The server will eventually 3259 * timeout the portal and eliminate it from the list. 3260 */ 3261 3262 if (esi_response != ISNS_RSP_SUCCESSFUL) { 3263 kmem_free(pdu, pdu_size); 3264 return; 3265 } 3266 3267 /* Get the remote peer's IP address */ 3268 bzero(&server_ss, sizeof (server_ss)); 3269 sa_len = sizeof (server_ss); 3270 if (ksocket_getpeername(ks, (struct sockaddr *)&server_ss, &sa_len, 3271 CRED())) { 3272 return; 3273 } 3274 3275 if (iscsit_isns_logging) { 3276 char server_buf[IDM_SA_NTOP_BUFSIZ]; 3277 char portal_buf[IDM_SA_NTOP_BUFSIZ]; 3278 ISNST_LOG(CE_NOTE, "ESI: svr %s -> portal %s", 3279 idm_sa_ntop(&server_ss, server_buf, 3280 sizeof (server_buf)), 3281 idm_sa_ntop(&portal_ss, portal_buf, 3282 sizeof (portal_buf))); 3283 } 3284 3285 3286 ISNS_GLOBAL_LOCK(); 3287 if (isnst_lookup_portal(&portal_ss) == NULL) { 3288 ISNST_LOG(CE_WARN, "ESI req to non-active portal"); 3289 ISNS_GLOBAL_UNLOCK(); 3290 kmem_free(pdu, pdu_size); 3291 return; 3292 } 3293 3294 /* 3295 * Update the server timestamp of how recently we have 3296 * received an ESI request from this iSNS server. 3297 * We ignore requests from servers we don't know. 3298 */ 3299 if (! isnst_update_server_timestamp(&server_ss)) { 3300 ISNST_LOG(CE_WARN, "ESI req from unknown server"); 3301 kmem_free(pdu, pdu_size); 3302 ISNS_GLOBAL_UNLOCK(); 3303 return; 3304 } 3305 3306 /* 3307 * Update ESI timestamps for all portals with same IP address. 3308 */ 3309 for (iportal = avl_first(&isns_all_portals); 3310 iportal != NULL; 3311 iportal = AVL_NEXT(&isns_all_portals, iportal)) { 3312 if (idm_ss_compare(&iportal->portal_addr, &portal_ss, 3313 B_TRUE, B_FALSE)) { 3314 gethrestime(&iportal->portal_esi_timestamp); 3315 } 3316 } 3317 3318 ISNS_GLOBAL_UNLOCK(); 3319 3320 3321 /* 3322 * Build response validating the portal 3323 */ 3324 rsp_size = isnst_create_pdu_header(ISNS_ESI_RSP, &rsp_pdu, 0); 3325 3326 if (rsp_size == 0) { 3327 ISNST_LOG(CE_WARN, "isnst_handle_esi_req: Can't get rsp pdu"); 3328 kmem_free(pdu, pdu_size); 3329 return; 3330 } 3331 3332 rsp = (isns_resp_t *)((void *)(&rsp_pdu->payload[0])); 3333 3334 /* Use xid from the request pdu */ 3335 rsp_pdu->xid = pdu->xid; 3336 rsp->status = htonl(ISNS_RSP_SUCCESSFUL); 3337 3338 /* Copy original data */ 3339 req_pl_len = ntohs(pdu->payload_len); 3340 bcopy(pdu->payload, rsp->data, req_pl_len); 3341 rsp_pdu->payload_len = htons(req_pl_len + sizeof (uint32_t)); 3342 3343 if (isnst_send_pdu(ks, rsp_pdu) != 0) { 3344 ISNST_LOG(CE_WARN, 3345 "isnst_handle_esi_req: Send response failed"); 3346 } 3347 3348 kmem_free(rsp_pdu, rsp_size); 3349 kmem_free(pdu, pdu_size); 3350 3351 } 3352 3353 static int 3354 isnst_tgt_avl_compare(const void *t1, const void *t2) 3355 { 3356 const isns_target_t *tgt1 = t1; 3357 const isns_target_t *tgt2 = t2; 3358 3359 /* 3360 * Sort by target (pointer to iscsit_tgt_t). 3361 */ 3362 3363 if (tgt1->target < tgt2->target) { 3364 return (-1); 3365 } else if (tgt1->target > tgt2->target) { 3366 return (1); 3367 } 3368 3369 return (0); 3370 } 3371 3372 static void 3373 isnst_set_server_status(iscsit_isns_svr_t *svr, boolean_t registered) 3374 { 3375 isns_target_t *itarget; 3376 3377 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 3378 3379 svr->svr_reset_needed = B_FALSE; 3380 if (registered == B_TRUE) { 3381 svr->svr_registered = B_TRUE; 3382 svr->svr_last_msg = ddi_get_lbolt(); 3383 itarget = avl_first(&svr->svr_target_list); 3384 while (itarget) { 3385 isns_target_t *next_target; 3386 next_target = AVL_NEXT(&svr->svr_target_list, itarget); 3387 if (itarget->target_delete_needed) { 3388 /* All deleted tgts removed */ 3389 isnst_clear_from_target_list(itarget, 3390 &svr->svr_target_list); 3391 } else { 3392 /* Other tgts marked registered */ 3393 itarget->target_registered = B_TRUE; 3394 /* No updates needed -- clean slate */ 3395 itarget->target_update_needed = B_FALSE; 3396 } 3397 itarget = next_target; 3398 } 3399 ASSERT(avl_numnodes(&svr->svr_target_list) > 0); 3400 } else { 3401 svr->svr_registered = B_FALSE; 3402 isnst_clear_target_list(svr); 3403 } 3404 } 3405 3406 static void 3407 isnst_monitor_default_portal_list(void) 3408 { 3409 idm_addr_list_t *new_portal_list = NULL; 3410 uint32_t new_portal_list_size = 0; 3411 3412 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 3413 ASSERT(mutex_owned(&iscsit_isns_mutex)); 3414 3415 if (default_portal_online) { 3416 new_portal_list_size = idm_get_ipaddr(&new_portal_list); 3417 } 3418 3419 /* 3420 * We compute a new list of portals if 3421 * a) Something in itadm has changed a portal 3422 * b) there are new default portals 3423 * c) the default portal has gone offline 3424 */ 3425 if (isns_portals_changed || 3426 ((new_portal_list_size != 0) && 3427 (isnst_find_default_portals(new_portal_list) != 3428 num_default_portals)) || 3429 ((new_portal_list_size == 0) && (num_default_portals > 0))) { 3430 3431 isnst_clear_default_portals(); 3432 isnst_copy_portal_list(&isns_tpg_portals, 3433 &isns_all_portals); 3434 num_tpg_portals = avl_numnodes(&isns_all_portals); 3435 if (new_portal_list_size != 0) { 3436 num_default_portals = 3437 isnst_add_default_portals(new_portal_list); 3438 } 3439 } 3440 3441 /* Catch any case where we miss an update to TPG portals */ 3442 ASSERT(num_tpg_portals == avl_numnodes(&isns_tpg_portals)); 3443 3444 if (new_portal_list != NULL) { 3445 kmem_free(new_portal_list, new_portal_list_size); 3446 } 3447 } 3448 3449 3450 static int 3451 isnst_find_default_portals(idm_addr_list_t *alist) 3452 { 3453 idm_addr_t *dportal; 3454 isns_portal_t *iportal; 3455 struct sockaddr_storage sa; 3456 int aidx; 3457 int num_portals_found = 0; 3458 3459 for (aidx = 0; aidx < alist->al_out_cnt; aidx++) { 3460 dportal = &alist->al_addrs[aidx]; 3461 dportal->a_port = ISCSI_LISTEN_PORT; 3462 idm_addr_to_sa(dportal, &sa); 3463 iportal = isnst_lookup_portal(&sa); 3464 if (iportal == NULL) { 3465 /* Found a non-matching default portal */ 3466 return (-1); 3467 } 3468 if (iportal->portal_default) { 3469 num_portals_found++; 3470 } 3471 } 3472 return (num_portals_found); 3473 } 3474 3475 static void 3476 isnst_clear_default_portals(void) 3477 { 3478 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 3479 3480 isnst_clear_portal_list(&isns_all_portals); 3481 num_tpg_portals = 0; 3482 num_default_portals = 0; 3483 } 3484 3485 static int 3486 isnst_add_default_portals(idm_addr_list_t *alist) 3487 { 3488 idm_addr_t *dportal; 3489 isns_portal_t *iportal; 3490 struct sockaddr_storage sa; 3491 int aidx; 3492 3493 for (aidx = 0; aidx < alist->al_out_cnt; aidx++) { 3494 dportal = &alist->al_addrs[aidx]; 3495 dportal->a_port = ISCSI_LISTEN_PORT; 3496 idm_addr_to_sa(dportal, &sa); 3497 iportal = isnst_add_to_portal_list(&sa, &isns_all_portals); 3498 iportal->portal_default = B_TRUE; 3499 } 3500 return (alist->al_out_cnt); 3501 } 3502 3503 3504 static int 3505 isnst_portal_avl_compare(const void *p1, const void *p2) 3506 { 3507 const isns_portal_t *portal1 = p1; 3508 const isns_portal_t *portal2 = p2; 3509 3510 return (idm_ss_compare(&portal1->portal_addr, &portal2->portal_addr, 3511 B_TRUE /* v4_mapped_as_v4 */, B_TRUE /* compare_ports */)); 3512 } 3513 3514 static void 3515 isnst_clear_portal_list(avl_tree_t *portal_list) 3516 { 3517 isns_portal_t *iportal; 3518 void *cookie = NULL; 3519 3520 while ((iportal = avl_destroy_nodes(portal_list, &cookie)) != NULL) { 3521 kmem_free(iportal, sizeof (isns_portal_t)); 3522 } 3523 } 3524 static void 3525 isnst_copy_portal_list(avl_tree_t *t1, avl_tree_t *t2) 3526 { 3527 isns_portal_t *iportal, *jportal; 3528 3529 iportal = (isns_portal_t *)avl_first(t1); 3530 while (iportal) { 3531 jportal = isnst_add_to_portal_list(&iportal->portal_addr, t2); 3532 jportal->portal_iscsit = iportal->portal_iscsit; 3533 iportal = AVL_NEXT(t1, iportal); 3534 } 3535 } 3536 3537 3538 static isns_portal_t * 3539 isnst_lookup_portal(struct sockaddr_storage *sa) 3540 { 3541 isns_portal_t *iportal, tmp_portal; 3542 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 3543 3544 bcopy(sa, &tmp_portal.portal_addr, sizeof (*sa)); 3545 iportal = avl_find(&isns_all_portals, &tmp_portal, NULL); 3546 return (iportal); 3547 } 3548 3549 static isns_portal_t * 3550 isnst_add_to_portal_list(struct sockaddr_storage *sa, avl_tree_t *portal_list) 3551 { 3552 isns_portal_t *iportal, tmp_portal; 3553 avl_index_t where; 3554 /* 3555 * Make sure this portal isn't already in our list. 3556 */ 3557 3558 bcopy(sa, &tmp_portal.portal_addr, sizeof (*sa)); 3559 3560 if ((iportal = (isns_portal_t *)avl_find(portal_list, 3561 &tmp_portal, &where)) == NULL) { 3562 iportal = kmem_zalloc(sizeof (isns_portal_t), KM_SLEEP); 3563 bcopy(sa, &iportal->portal_addr, sizeof (*sa)); 3564 avl_insert(portal_list, (void *)iportal, where); 3565 } 3566 3567 return (iportal); 3568 } 3569 3570 3571 static void 3572 isnst_remove_from_portal_list(struct sockaddr_storage *sa, 3573 avl_tree_t *portal_list) 3574 { 3575 isns_portal_t *iportal, tmp_portal; 3576 3577 bcopy(sa, &tmp_portal.portal_addr, sizeof (*sa)); 3578 3579 if ((iportal = avl_find(portal_list, &tmp_portal, NULL)) 3580 != NULL) { 3581 avl_remove(portal_list, iportal); 3582 kmem_free(iportal, sizeof (isns_portal_t)); 3583 } 3584 } 3585 3586 /* 3587 * These functions are called by iscsit proper when a portal comes online 3588 * or goes offline. 3589 */ 3590 3591 void 3592 iscsit_isns_portal_online(iscsit_portal_t *portal) 3593 { 3594 isns_portal_t *iportal; 3595 3596 mutex_enter(&iscsit_isns_mutex); 3597 3598 if (portal->portal_default) { 3599 /* Portals should only be onlined once */ 3600 ASSERT(default_portal_online == B_FALSE); 3601 default_portal_online = B_TRUE; 3602 } else { 3603 iportal = isnst_add_to_portal_list( 3604 &portal->portal_addr, &isns_tpg_portals); 3605 iportal->portal_iscsit = portal; 3606 } 3607 isns_portals_changed = B_TRUE; 3608 3609 mutex_exit(&iscsit_isns_mutex); 3610 3611 isnst_monitor_awaken(); 3612 } 3613 3614 void 3615 iscsit_isns_portal_offline(iscsit_portal_t *portal) 3616 { 3617 mutex_enter(&iscsit_isns_mutex); 3618 3619 if (portal->portal_default) { 3620 /* Portals should only be offlined once */ 3621 ASSERT(default_portal_online == B_TRUE); 3622 default_portal_online = B_FALSE; 3623 } else { 3624 isnst_remove_from_portal_list(&portal->portal_addr, 3625 &isns_tpg_portals); 3626 } 3627 isns_portals_changed = B_TRUE; 3628 3629 mutex_exit(&iscsit_isns_mutex); 3630 3631 isnst_monitor_awaken(); 3632 } 3633