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