1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/cpuvar.h> 27 #include <sys/types.h> 28 #include <sys/conf.h> 29 #include <sys/file.h> 30 #include <sys/ddi.h> 31 #include <sys/sunddi.h> 32 #include <sys/socket.h> 33 #include <inet/tcp.h> 34 #include <sys/sdt.h> 35 36 #include <sys/stmf.h> 37 #include <sys/stmf_ioctl.h> 38 #include <sys/portif.h> 39 #include <sys/idm/idm.h> 40 #include <sys/idm/idm_so.h> 41 #include <sys/iscsit/iscsit_common.h> 42 #include <sys/iscsit/isns_protocol.h> 43 #include <iscsit.h> 44 #include <iscsit_isns.h> 45 #include <sys/ksocket.h> 46 47 /* local defines */ 48 #define MAX_XID (2^16) 49 #define ISNS_IDLE_TIME 60 50 #define MAX_RETRY (3) 51 #define ISNS_RCV_TIMER_SECONDS 5 52 53 #define VALID_NAME(NAME, LEN) \ 54 ((LEN) > 0 && (NAME)[0] != 0 && (NAME)[(LEN) - 1] == 0) 55 56 57 boolean_t iscsit_isns_logging = 0; 58 59 #define ISNST_LOG if (iscsit_isns_logging) cmn_err 60 61 static kmutex_t isns_monitor_mutex; 62 static kthread_t *isns_monitor_thr_id; 63 static kt_did_t isns_monitor_thr_did; 64 static boolean_t isns_monitor_thr_running; 65 66 static kcondvar_t isns_idle_cv; 67 68 static uint16_t xid; 69 #define GET_XID() atomic_inc_16_nv(&xid) 70 71 static clock_t monitor_idle_interval; 72 73 #define ISNS_GLOBAL_LOCK() \ 74 mutex_enter(&iscsit_global.global_isns_cfg.isns_mutex) 75 76 #define ISNS_GLOBAL_LOCK_HELD() \ 77 MUTEX_HELD(&iscsit_global.global_isns_cfg.isns_mutex) 78 79 #define ISNS_GLOBAL_UNLOCK() \ 80 mutex_exit(&iscsit_global.global_isns_cfg.isns_mutex) 81 82 /* 83 * iSNS ESI thread state 84 */ 85 86 static isns_esi_tinfo_t esi; 87 88 /* 89 * List of portals. 90 */ 91 static boolean_t default_portal_online = B_FALSE; 92 static boolean_t default_portal_state_change = B_FALSE; 93 static list_t portal_list; 94 static uint32_t portal_list_count = 0; 95 96 /* 97 * Our entity identifier (fully-qualified hostname) 98 */ 99 static char *isns_eid = NULL; 100 101 /* 102 * Our list of targets 103 */ 104 static avl_tree_t isns_target_list; 105 106 /* 107 * in6addr_any is currently all zeroes, but use the macro in case this 108 * ever changes. 109 */ 110 static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; 111 112 static void 113 isnst_start(); 114 115 static void 116 isnst_stop(); 117 118 static void 119 iscsit_set_isns(boolean_t state); 120 121 static int 122 iscsit_add_isns(it_portal_t *cfg_svr); 123 124 static void 125 iscsit_delete_isns(iscsit_isns_svr_t *svr); 126 127 static iscsit_isns_svr_t * 128 iscsit_isns_svr_lookup(struct sockaddr_storage *sa); 129 130 static void 131 isnst_monitor(void *arg); 132 133 static int 134 isnst_monitor_one_server(iscsit_isns_svr_t *svr, boolean_t enabled); 135 136 static int 137 isnst_update_target(iscsit_tgt_t *target, isns_reg_type_t reg); 138 139 static int 140 isnst_update_one_server(iscsit_isns_svr_t *svr, iscsit_tgt_t *target, 141 isns_reg_type_t reg); 142 143 static int isnst_register(iscsit_isns_svr_t *svr, iscsit_tgt_t *target, 144 isns_reg_type_t regtype); 145 static int isnst_deregister(iscsit_isns_svr_t *svr, char *node); 146 147 static size_t 148 isnst_make_dereg_pdu(isns_pdu_t **pdu, char *node); 149 150 static int 151 isnst_verify_rsp(iscsit_isns_svr_t *svr, isns_pdu_t *pdu, 152 isns_pdu_t *rsp, size_t rsp_size); 153 154 static uint16_t 155 isnst_pdu_get_op(isns_pdu_t *pdu, uint8_t **pp); 156 157 static size_t 158 isnst_make_reg_pdu(isns_pdu_t **pdu, iscsit_tgt_t *target, 159 boolean_t svr_registered, isns_reg_type_t regtype); 160 161 static int 162 isnst_reg_pdu_add_entity_portals(isns_pdu_t *pdu, size_t pdu_size, 163 idm_addr_list_t *default_portal_list); 164 165 static int 166 isnst_reg_pdu_add_pg(isns_pdu_t *pdu, size_t pdu_size, iscsit_tgt_t *target, 167 idm_addr_list_t *default_portal_list); 168 169 static int 170 isnst_add_null_pg(isns_pdu_t *pdu, size_t pdu_size, 171 iscsit_tgt_t *tgt, idm_addr_list_t *default_portal_list); 172 173 static int 174 isnst_add_portal_attr(isns_pdu_t *pdu, size_t pdu_size, 175 uint32_t ip_attr_id, uint32_t port_attr_id, 176 struct sockaddr_storage *ss, boolean_t esi_info); 177 178 static size_t 179 isnst_create_pdu_header(uint16_t func_id, isns_pdu_t **pdu, uint16_t flags); 180 181 static int 182 isnst_add_attr(isns_pdu_t *pdu, 183 size_t max_pdu_size, 184 uint32_t attr_id, 185 uint32_t attr_len, 186 void *attr_data, 187 uint32_t attr_numeric_data); 188 189 static int 190 isnst_send_pdu(void *so, isns_pdu_t *pdu); 191 192 static size_t 193 isnst_rcv_pdu(void *so, isns_pdu_t **pdu); 194 195 static void * 196 isnst_open_so(struct sockaddr_storage *sa); 197 198 static void 199 isnst_close_so(void *); 200 201 static void 202 isnst_esi_thread(void *arg); 203 204 static void 205 isnst_handle_esi_req(ksocket_t so, isns_pdu_t *pdu, size_t pl_size); 206 207 static void isnst_esi_start(void); 208 static void isnst_esi_stop(void); 209 static isns_target_t *isnst_add_to_target_list(iscsit_tgt_t *target); 210 int isnst_tgt_avl_compare(const void *t1, const void *t2); 211 static void isnst_get_target_list(void); 212 static void isnst_set_server_status(iscsit_isns_svr_t *svr, 213 boolean_t registered); 214 static void isnst_monitor_start(void); 215 static void isnst_monitor_stop(void); 216 static void isnst_add_portal(iscsit_portal_t *portal); 217 static void isnst_remove_portal(iscsit_portal_t *portal); 218 static isns_portal_list_t *isnst_lookup_portal(struct sockaddr_storage *p, 219 isns_portal_list_t *last_portal); 220 static boolean_t isnst_portal_exists(struct sockaddr_storage *p); 221 static boolean_t isnst_lookup_default_portal(); 222 223 static boolean_t isnst_retry_registration(int rsp_status_code); 224 225 it_cfg_status_t 226 isnst_config_merge(it_config_t *cfg) 227 { 228 boolean_t new_isns_state = B_FALSE; 229 iscsit_isns_svr_t *isns_svr, *next_isns_svr; 230 it_portal_t *cfg_isns_svr; 231 232 /* 233 * Determine whether iSNS is enabled in the new config. 234 * Isns property may not be set up yet. 235 */ 236 (void) nvlist_lookup_boolean_value(cfg->config_global_properties, 237 PROP_ISNS_ENABLED, &new_isns_state); 238 239 ISNS_GLOBAL_LOCK(); 240 241 /* Delete iSNS servers that are no longer part of the config */ 242 for (isns_svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs); 243 isns_svr != NULL; 244 isns_svr = next_isns_svr) { 245 next_isns_svr = list_next( 246 &iscsit_global.global_isns_cfg.isns_svrs, isns_svr); 247 if (it_sns_svr_lookup(cfg, &isns_svr->svr_sa) == NULL) 248 iscsit_delete_isns(isns_svr); 249 } 250 251 /* Add new iSNS servers */ 252 for (cfg_isns_svr = cfg->config_isns_svr_list; 253 cfg_isns_svr != NULL; 254 cfg_isns_svr = cfg_isns_svr->next) { 255 isns_svr = iscsit_isns_svr_lookup(&cfg_isns_svr->portal_addr); 256 if (isns_svr == NULL) { 257 if (iscsit_add_isns(cfg_isns_svr) != 0) { 258 /* Shouldn't happen */ 259 ISNS_GLOBAL_UNLOCK(); 260 return (ITCFG_MISC_ERR); 261 } 262 } 263 } 264 265 /* Start/Stop iSNS if necessary */ 266 if (iscsit_global.global_isns_cfg.isns_state != new_isns_state) { 267 iscsit_set_isns(new_isns_state); 268 } 269 270 ISNS_GLOBAL_UNLOCK(); 271 272 /* 273 * There is no "modify case" since the user specifies a complete 274 * server list each time. A modify is the same as a remove+add. 275 */ 276 277 return (0); 278 } 279 280 int 281 iscsit_isns_init(iscsit_hostinfo_t *hostinfo) 282 { 283 mutex_init(&iscsit_global.global_isns_cfg.isns_mutex, NULL, 284 MUTEX_DEFAULT, NULL); 285 286 ISNS_GLOBAL_LOCK(); 287 iscsit_global.global_isns_cfg.isns_state = B_FALSE; 288 list_create(&iscsit_global.global_isns_cfg.isns_svrs, 289 sizeof (iscsit_isns_svr_t), offsetof(iscsit_isns_svr_t, svr_ln)); 290 list_create(&portal_list, sizeof (isns_portal_list_t), 291 offsetof(isns_portal_list_t, portal_ln)); 292 portal_list_count = 0; 293 isns_eid = kmem_alloc(hostinfo->length, KM_SLEEP); 294 if (hostinfo->length > ISCSIT_MAX_HOSTNAME_LEN) 295 hostinfo->length = ISCSIT_MAX_HOSTNAME_LEN; 296 (void) strlcpy(isns_eid, hostinfo->fqhn, hostinfo->length); 297 avl_create(&isns_target_list, isnst_tgt_avl_compare, 298 sizeof (isns_target_t), offsetof(isns_target_t, target_node)); 299 /* 300 * The iscsi global lock is not held here, but it is held when 301 * isnst_start is called, so we need to acquire it only in this 302 * case. 303 */ 304 ISCSIT_GLOBAL_LOCK(RW_READER); 305 isnst_get_target_list(); 306 ISCSIT_GLOBAL_UNLOCK(); 307 308 /* initialize isns client */ 309 mutex_init(&isns_monitor_mutex, NULL, MUTEX_DEFAULT, NULL); 310 mutex_init(&esi.esi_mutex, NULL, MUTEX_DEFAULT, NULL); 311 isns_monitor_thr_id = NULL; 312 monitor_idle_interval = ISNS_IDLE_TIME * drv_usectohz(1000000); 313 cv_init(&isns_idle_cv, NULL, CV_DEFAULT, NULL); 314 cv_init(&esi.esi_cv, NULL, CV_DEFAULT, NULL); 315 xid = 0; 316 ISNS_GLOBAL_UNLOCK(); 317 318 return (0); 319 } 320 321 void 322 iscsit_isns_fini() 323 { 324 ISNS_GLOBAL_LOCK(); 325 iscsit_set_isns(B_FALSE); 326 mutex_destroy(&isns_monitor_mutex); 327 cv_destroy(&isns_idle_cv); 328 mutex_destroy(&esi.esi_mutex); 329 cv_destroy(&esi.esi_cv); 330 331 /* 332 * Free our EID and target list. 333 */ 334 335 if (isns_eid) { 336 kmem_free(isns_eid, strlen(isns_eid) + 1); 337 isns_eid = NULL; 338 } 339 340 iscsit_global.global_isns_cfg.isns_state = B_FALSE; 341 avl_destroy(&isns_target_list); 342 list_destroy(&iscsit_global.global_isns_cfg.isns_svrs); 343 list_destroy(&portal_list); 344 portal_list_count = 0; 345 ISNS_GLOBAL_UNLOCK(); 346 347 mutex_destroy(&iscsit_global.global_isns_cfg.isns_mutex); 348 } 349 350 static void 351 iscsit_set_isns(boolean_t state) 352 { 353 iscsit_isns_svr_t *svr; 354 355 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 356 357 /* 358 * Update state and isns stop flag 359 */ 360 if (iscsit_global.global_isns_cfg.isns_state != state) { 361 /* reset retry count for all servers */ 362 for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs); 363 svr != NULL; 364 svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, 365 svr)) { 366 svr->svr_retry_count = 0; 367 } 368 369 iscsit_global.global_isns_cfg.isns_state = state; 370 371 if (state) { 372 isnst_start(); 373 } else { 374 isnst_stop(); 375 } 376 } 377 } 378 379 int 380 iscsit_add_isns(it_portal_t *cfg_svr) 381 { 382 iscsit_isns_svr_t *svr; 383 384 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 385 386 svr = kmem_zalloc(sizeof (iscsit_isns_svr_t), KM_SLEEP); 387 bcopy(&cfg_svr->portal_addr, &svr->svr_sa, 388 sizeof (struct sockaddr_storage)); 389 390 /* put it on the global isns server list */ 391 list_insert_tail(&iscsit_global.global_isns_cfg.isns_svrs, svr); 392 393 /* 394 * Register targets with this server if iSNS is enabled. 395 */ 396 397 if (iscsit_global.global_isns_cfg.isns_state && 398 (isnst_update_one_server(svr, NULL, ISNS_REGISTER_ALL) == 0)) { 399 isnst_set_server_status(svr, B_TRUE); 400 } 401 402 return (0); 403 } 404 405 void 406 iscsit_delete_isns(iscsit_isns_svr_t *svr) 407 { 408 boolean_t need_dereg; 409 410 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 411 412 list_remove(&iscsit_global.global_isns_cfg.isns_svrs, svr); 413 414 /* talk to this server if isns monitor is running */ 415 mutex_enter(&isns_monitor_mutex); 416 if (isns_monitor_thr_id != NULL) { 417 need_dereg = B_TRUE; 418 } else { 419 need_dereg = B_FALSE; 420 } 421 mutex_exit(&isns_monitor_mutex); 422 423 if (need_dereg) { 424 (void) isnst_monitor_one_server(svr, B_FALSE); 425 } 426 427 /* free the memory */ 428 kmem_free(svr, sizeof (*svr)); 429 } 430 431 static iscsit_isns_svr_t * 432 iscsit_isns_svr_lookup(struct sockaddr_storage *sa) 433 { 434 iscsit_isns_svr_t *svr; 435 it_portal_t portal1; 436 437 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 438 439 bcopy(sa, &portal1.portal_addr, sizeof (struct sockaddr_storage)); 440 441 for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs); 442 svr != NULL; 443 svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, svr)) { 444 if (it_sa_compare(&svr->svr_sa, sa) == 0) 445 return (svr); 446 } 447 448 return (NULL); 449 } 450 451 int 452 iscsit_isns_register(iscsit_tgt_t *target) 453 { 454 int rc = 0; 455 456 ISNS_GLOBAL_LOCK(); 457 458 (void) isnst_add_to_target_list(target); 459 460 if (iscsit_global.global_isns_cfg.isns_state == B_FALSE) { 461 ISNS_GLOBAL_UNLOCK(); 462 return (rc); 463 } 464 465 rc = isnst_update_target(target, ISNS_REGISTER_TARGET); 466 467 ISNS_GLOBAL_UNLOCK(); 468 469 return (rc); 470 } 471 472 int 473 iscsit_isns_deregister(iscsit_tgt_t *target) 474 { 475 void *itarget; 476 isns_target_t tmptgt; 477 iscsit_isns_svr_t *svr; 478 list_t *global; 479 480 ISNS_GLOBAL_LOCK(); 481 482 if (iscsit_global.global_isns_cfg.isns_state == B_FALSE) { 483 tmptgt.target = target; 484 485 if ((itarget = avl_find(&isns_target_list, &tmptgt, NULL)) 486 != NULL) { 487 avl_remove(&isns_target_list, itarget); 488 kmem_free(itarget, sizeof (isns_target_t)); 489 } 490 491 ISNS_GLOBAL_UNLOCK(); 492 return (0); 493 } 494 495 /* 496 * Don't worry about dereg failures. 497 */ 498 (void) isnst_update_target(target, ISNS_DEREGISTER_TARGET); 499 500 /* 501 * Remove the target from the list regardless of the status. 502 */ 503 504 tmptgt.target = target; 505 if ((itarget = avl_find(&isns_target_list, &tmptgt, NULL)) != NULL) { 506 avl_remove(&isns_target_list, itarget); 507 kmem_free(itarget, sizeof (isns_target_t)); 508 } 509 510 /* 511 * If there are no more targets, mark the server as 512 * unregistered. 513 */ 514 515 if (avl_numnodes(&isns_target_list) == 0) { 516 global = &iscsit_global.global_isns_cfg.isns_svrs; 517 for (svr = list_head(global); svr != NULL; 518 svr = list_next(global, svr)) { 519 isnst_set_server_status(svr, B_FALSE); 520 } 521 } 522 523 ISNS_GLOBAL_UNLOCK(); 524 525 return (0); 526 } 527 528 /* 529 * This function is called by iscsit when a target's configuration 530 * has changed. 531 */ 532 533 void 534 iscsit_isns_target_update(iscsit_tgt_t *target) 535 { 536 ISNS_GLOBAL_LOCK(); 537 538 if (iscsit_global.global_isns_cfg.isns_state == B_FALSE) { 539 ISNS_GLOBAL_UNLOCK(); 540 return; 541 } 542 543 (void) isnst_update_target(target, ISNS_UPDATE_TARGET); 544 545 ISNS_GLOBAL_UNLOCK(); 546 } 547 548 static void 549 isnst_start() 550 { 551 ISNST_LOG(CE_NOTE, "**** isnst_start"); 552 553 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 554 555 /* 556 * Get initial target list 557 */ 558 isnst_get_target_list(); 559 560 /* 561 * Start ESI thread(s) 562 */ 563 isnst_esi_start(); 564 565 /* 566 * Create a thread for monitoring server communications 567 */ 568 isnst_monitor_start(); 569 } 570 571 static void 572 isnst_stop() 573 { 574 isns_target_t *itarget; 575 576 ISNST_LOG(CE_NOTE, "**** isnst_stop"); 577 578 ISNS_GLOBAL_UNLOCK(); 579 isnst_esi_stop(); 580 isnst_monitor_stop(); 581 ISNS_GLOBAL_LOCK(); 582 while ((itarget = avl_first(&isns_target_list)) != NULL) { 583 avl_remove(&isns_target_list, itarget); 584 kmem_free(itarget, sizeof (isns_target_t)); 585 } 586 } 587 588 static void 589 isnst_monitor_start(void) 590 { 591 ISNST_LOG(CE_NOTE, "isnst_monitor_start"); 592 593 mutex_enter(&isns_monitor_mutex); 594 isns_monitor_thr_id = thread_create(NULL, 0, 595 isnst_monitor, NULL, 0, &p0, TS_RUN, minclsyspri); 596 while (!isns_monitor_thr_running) 597 cv_wait(&isns_idle_cv, &isns_monitor_mutex); 598 mutex_exit(&isns_monitor_mutex); 599 } 600 601 static void 602 isnst_monitor_stop(void) 603 { 604 ISNST_LOG(CE_NOTE, "isnst_monitor_stop"); 605 606 mutex_enter(&isns_monitor_mutex); 607 if (isns_monitor_thr_running) { 608 isns_monitor_thr_running = B_FALSE; 609 cv_signal(&isns_idle_cv); 610 mutex_exit(&isns_monitor_mutex); 611 612 thread_join(isns_monitor_thr_did); 613 return; 614 } 615 mutex_exit(&isns_monitor_mutex); 616 } 617 618 /* 619 * isnst_update_server_timestamp 620 * 621 * When we receive an ESI request, update the timestamp for the server. 622 * If we don't receive one for the specified period of time, we'll attempt 623 * to re-register. 624 */ 625 626 static void 627 isnst_update_server_timestamp(ksocket_t so) 628 { 629 iscsit_isns_svr_t *svr; 630 struct in_addr *sin = NULL, *svr_in; 631 struct in6_addr *sin6 = NULL, *svr_in6; 632 struct sockaddr_in6 t_addr; 633 socklen_t t_addrlen; 634 635 bzero(&t_addr, sizeof (struct sockaddr_in6)); 636 t_addrlen = sizeof (struct sockaddr_in6); 637 (void) ksocket_getpeername(so, (struct sockaddr *)&t_addr, &t_addrlen, 638 CRED()); 639 if (((struct sockaddr *)(&t_addr))->sa_family == AF_INET) { 640 sin = &((struct sockaddr_in *)((void *)(&t_addr)))->sin_addr; 641 } else { 642 sin6 = &(&t_addr)->sin6_addr; 643 } 644 645 /* 646 * Find the server and update the timestamp 647 */ 648 649 ISNS_GLOBAL_LOCK(); 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 (sin6 == NULL) { 654 if (svr->svr_sa.ss_family == AF_INET) { 655 svr_in = &((struct sockaddr_in *)&svr->svr_sa)-> 656 sin_addr; 657 if (bcmp(svr_in, sin, sizeof (in_addr_t)) 658 == 0) { 659 break; 660 } 661 } 662 } else { 663 if (svr->svr_sa.ss_family == AF_INET6) { 664 svr_in6 = &((struct sockaddr_in6 *) 665 &svr->svr_sa)->sin6_addr; 666 if (bcmp(svr_in6, sin6, 667 sizeof (in6_addr_t)) == 0) { 668 break; 669 } 670 } 671 } 672 } 673 674 if (svr != NULL) { 675 svr->svr_last_msg = ddi_get_lbolt(); 676 } 677 ISNS_GLOBAL_UNLOCK(); 678 } 679 680 /* 681 * isnst_monitor 682 * 683 * This function monitors registration status for each server. 684 */ 685 686 687 static void 688 isnst_monitor_all_servers() 689 { 690 iscsit_isns_svr_t *svr; 691 boolean_t enabled; 692 list_t *svr_list; 693 694 svr_list = &iscsit_global.global_isns_cfg.isns_svrs; 695 696 ISNS_GLOBAL_LOCK(); 697 enabled = iscsit_global.global_isns_cfg.isns_state; 698 for (svr = list_head(svr_list); svr != NULL; 699 svr = list_next(svr_list, svr)) { 700 if (isnst_monitor_one_server(svr, enabled) != 0) { 701 svr->svr_retry_count++; 702 } else { 703 svr->svr_retry_count = 0; 704 } 705 } 706 ISNS_GLOBAL_UNLOCK(); 707 } 708 709 /*ARGSUSED*/ 710 static void 711 isnst_monitor(void *arg) 712 { 713 mutex_enter(&isns_monitor_mutex); 714 cv_signal(&isns_idle_cv); 715 isns_monitor_thr_did = curthread->t_did; 716 isns_monitor_thr_running = B_TRUE; 717 718 while (isns_monitor_thr_running) { 719 mutex_exit(&isns_monitor_mutex); 720 721 /* Update servers */ 722 isnst_monitor_all_servers(); 723 724 /* 725 * Keep running until isns_monitor_thr_running is set to 726 * B_FALSE. 727 */ 728 mutex_enter(&isns_monitor_mutex); 729 DTRACE_PROBE(iscsit__isns__monitor__sleep); 730 (void) cv_timedwait(&isns_idle_cv, &isns_monitor_mutex, 731 ddi_get_lbolt() + monitor_idle_interval); 732 DTRACE_PROBE1(iscsit__isns__monitor__wakeup, 733 boolean_t, isns_monitor_thr_running); 734 } 735 736 mutex_exit(&isns_monitor_mutex); 737 738 /* Update the servers one last time for deregistration */ 739 isnst_monitor_all_servers(); 740 741 /* terminate the thread at the last */ 742 thread_exit(); 743 } 744 745 static int 746 isnst_monitor_one_server(iscsit_isns_svr_t *svr, boolean_t enabled) 747 { 748 int rc = 0; 749 struct sonode *so; 750 751 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 752 753 /* 754 * First, take care of the case where iSNS is no longer enabled. 755 * 756 * If we're still registered, deregister. Regardless, mark the 757 * server as not registered. 758 */ 759 760 if (enabled == B_FALSE) { 761 if (svr->svr_registered == B_TRUE) { 762 /* 763 * Doesn't matter if this fails. We're disabled. 764 */ 765 so = isnst_open_so(&svr->svr_sa); 766 if (so != NULL) { 767 (void) isnst_update_one_server(svr, NULL, 768 ISNS_DEREGISTER_ALL); 769 isnst_close_so(so); 770 } 771 } 772 773 isnst_set_server_status(svr, B_FALSE); 774 return (0); 775 } 776 777 /* 778 * If there are no targets, we're done. 779 */ 780 781 if (avl_numnodes(&isns_target_list) == 0) { 782 return (0); 783 } 784 785 /* 786 * At this point, we know iSNS is enabled. 787 * 788 * If we've received an ESI request from the server recently 789 * (within MAX_ESI_INTERVALS * the max interval length), 790 * no need to continue. 791 */ 792 793 if (svr->svr_registered == B_TRUE) { 794 if (ddi_get_lbolt() < (svr->svr_last_msg + 795 drv_usectohz(svr->svr_esi_interval * 1000000 * 796 MAX_ESI_INTERVALS))) { 797 return (0); 798 } 799 } else { 800 /* 801 * We're not registered... Try to register now. 802 */ 803 if ((rc = isnst_update_one_server(svr, NULL, 804 ISNS_REGISTER_ALL)) == 0) { 805 isnst_set_server_status(svr, B_TRUE); 806 } 807 } 808 809 return (rc); 810 } 811 812 static int 813 isnst_update_target(iscsit_tgt_t *target, isns_reg_type_t reg) 814 { 815 iscsit_isns_svr_t *svr; 816 int rc = 0, curr_rc; 817 818 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 819 ASSERT(iscsit_global.global_isns_cfg.isns_state == B_TRUE); 820 821 for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs); 822 svr != NULL; 823 svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, svr)) { 824 /* 825 * Only return success if they all succeed. Let the caller 826 * deal with any failure. 827 */ 828 829 curr_rc = isnst_update_one_server(svr, target, reg); 830 831 if (curr_rc == 0) { 832 if (reg == ISNS_REGISTER_TARGET) { 833 isnst_set_server_status(svr, B_TRUE); 834 } 835 } else if (rc == 0) { 836 rc = curr_rc; 837 } 838 } 839 840 return (rc); 841 } 842 843 static int 844 isnst_update_one_server(iscsit_isns_svr_t *svr, iscsit_tgt_t *target, 845 isns_reg_type_t reg) 846 { 847 int rc = 0; 848 849 switch (reg) { 850 case ISNS_DEREGISTER_TARGET: 851 rc = isnst_deregister(svr, target->target_name); 852 break; 853 854 case ISNS_DEREGISTER_ALL: 855 rc = isnst_deregister(svr, NULL); 856 break; 857 858 case ISNS_UPDATE_TARGET: 859 case ISNS_REGISTER_TARGET: 860 rc = isnst_register(svr, target, reg); 861 break; 862 863 case ISNS_REGISTER_ALL: 864 rc = isnst_register(svr, NULL, reg); 865 break; 866 867 default: 868 ASSERT(0); 869 /* NOTREACHED */ 870 } 871 872 return (rc); 873 } 874 875 /* 876 * isnst_retry_registration 877 * 878 * This function checks the return value from a registration pdu and 879 * determines whether or not we should retry this request. If the 880 * request is retried, it will do so as an "update", which means we 881 * re-register everything. 882 */ 883 884 static boolean_t 885 isnst_retry_registration(int rsp_status_code) 886 { 887 boolean_t retry; 888 889 /* 890 * Currently, we will attempt to retry for "Invalid Registration", 891 * "Source Unauthorized", or "Busy" errors. Any other errors should 892 * be handled by the caller if necessary. 893 */ 894 895 switch (rsp_status_code) { 896 case ISNS_RSP_INVALID_REGIS: 897 case ISNS_RSP_SRC_UNAUTHORIZED: 898 case ISNS_RSP_BUSY: 899 retry = B_TRUE; 900 break; 901 default: 902 retry = B_FALSE; 903 break; 904 } 905 906 return (retry); 907 } 908 909 static int 910 isnst_register(iscsit_isns_svr_t *svr, iscsit_tgt_t *target, 911 isns_reg_type_t regtype) 912 { 913 struct sonode *so; 914 int rc = 0; 915 isns_pdu_t *pdu, *rsp; 916 size_t pdu_size, rsp_size; 917 isns_target_t *itarget, tmptgt; 918 boolean_t retry_reg = B_TRUE; 919 920 /* 921 * Registration is a tricky thing. In order to keep things simple, 922 * we don't want to keep track of which targets are registered to 923 * which server. We rely on the target state machine to tell us 924 * when a target is online or offline, which prompts us to either 925 * register or deregister that target. 926 * 927 * When iscsit_isns_init is called, get a list of targets. Those that 928 * are online will need to be registered. In this case, target 929 * will be NULL. 930 * 931 * What this means is that if svr_registered == B_FALSE, that's 932 * when we'll register the network entity as well. 933 */ 934 935 if ((avl_numnodes(&isns_target_list) == 0) && (target == NULL)) { 936 return (0); 937 } 938 939 /* 940 * If the target is already registered and we're not doing an 941 * update registration, just return. 942 */ 943 944 if (target != NULL) { 945 tmptgt.target = target; 946 itarget = avl_find(&isns_target_list, &tmptgt, NULL); 947 ASSERT(itarget); 948 if ((itarget->target_registered == B_TRUE) && 949 (regtype != ISNS_UPDATE_TARGET)) { 950 return (0); 951 } 952 } 953 954 /* create TCP connection to the isns server */ 955 so = isnst_open_so(&svr->svr_sa); 956 957 if (so == NULL) { 958 isnst_set_server_status(svr, B_FALSE); 959 return (-1); 960 } 961 962 while (retry_reg) { 963 pdu_size = isnst_make_reg_pdu(&pdu, target, svr->svr_registered, 964 regtype); 965 if (pdu_size == 0) { 966 isnst_close_so(so); 967 return (-1); 968 } 969 970 rc = isnst_send_pdu(so, pdu); 971 if (rc != 0) { 972 kmem_free(pdu, pdu_size); 973 isnst_close_so(so); 974 return (rc); 975 } 976 977 rsp_size = isnst_rcv_pdu(so, &rsp); 978 if (rsp_size == 0) { 979 kmem_free(pdu, pdu_size); 980 isnst_close_so(so); 981 return (-1); 982 } 983 984 rc = isnst_verify_rsp(svr, pdu, rsp, rsp_size); 985 986 /* 987 * If we got a registration error, the server may be out of 988 * sync. In this case, we may re-try the registration as 989 * a "target update", which causes us to re-register everything. 990 */ 991 992 if ((retry_reg = isnst_retry_registration(rc)) == B_TRUE) { 993 if (regtype == ISNS_UPDATE_TARGET) { 994 /* 995 * If registration failed on an update, there 996 * is something terribly wrong, possibly with 997 * the server. 998 */ 999 rc = -1; 1000 retry_reg = B_FALSE; 1001 isnst_set_server_status(svr, B_FALSE); 1002 } else { 1003 regtype = ISNS_UPDATE_TARGET; 1004 } 1005 } 1006 1007 kmem_free(pdu, pdu_size); 1008 kmem_free(rsp, rsp_size); 1009 } 1010 1011 isnst_close_so(so); 1012 1013 /* 1014 * If it succeeded, mark all registered targets as such 1015 */ 1016 if (rc == 0) { 1017 if ((target != NULL) && (regtype != ISNS_UPDATE_TARGET)) { 1018 /* itarget initialized above */ 1019 itarget->target_registered = B_TRUE; 1020 } else { 1021 itarget = avl_first(&isns_target_list); 1022 while (itarget) { 1023 itarget->target_registered = B_TRUE; 1024 itarget = AVL_NEXT(&isns_target_list, itarget); 1025 } 1026 } 1027 } 1028 1029 return (rc); 1030 } 1031 1032 static isns_portal_list_t * 1033 isnst_lookup_portal(struct sockaddr_storage *p, isns_portal_list_t *last_portal) 1034 { 1035 isns_portal_list_t *portal; 1036 1037 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1038 1039 portal = (last_portal == NULL) ? 1040 list_head(&portal_list) : list_next(&portal_list, last_portal); 1041 1042 while (portal != NULL) { 1043 if (idm_ss_compare(p, &portal->portal_addr, 1044 B_TRUE /* v4_mapped_as_v4 */) == 0) { 1045 return (portal); 1046 } 1047 portal = list_next(&portal_list, portal); 1048 } 1049 1050 return (NULL); 1051 } 1052 1053 static boolean_t 1054 isnst_portal_exists(struct sockaddr_storage *p) 1055 { 1056 return ((isnst_lookup_portal(p, NULL) != NULL) || 1057 (default_portal_online && isnst_lookup_default_portal(p))); 1058 } 1059 1060 static void 1061 isnst_add_portal(iscsit_portal_t *portal) 1062 { 1063 isns_portal_list_t *new_portal; 1064 1065 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1066 1067 new_portal = kmem_zalloc(sizeof (isns_portal_list_t), KM_SLEEP); 1068 new_portal->portal_addr = portal->portal_addr; 1069 new_portal->portal_iscsit = portal; 1070 list_insert_tail(&portal_list, new_portal); 1071 portal->portal_isns = new_portal; 1072 portal_list_count++; 1073 1074 } 1075 1076 static void 1077 isnst_remove_portal(iscsit_portal_t *portal) 1078 { 1079 ASSERT(portal->portal_isns != NULL); 1080 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1081 1082 list_remove(&portal_list, portal->portal_isns); 1083 kmem_free(portal->portal_isns, sizeof (isns_portal_list_t)); 1084 portal_list_count--; 1085 } 1086 1087 static isns_target_t * 1088 isnst_add_to_target_list(iscsit_tgt_t *target) 1089 { 1090 isns_target_t *itarget, tmptgt; 1091 1092 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1093 1094 /* 1095 * Make sure this target isn't already in our list. If it is, 1096 * perhaps it has just moved from offline to online. 1097 */ 1098 1099 tmptgt.target = target; 1100 if ((itarget = (isns_target_t *)avl_find(&isns_target_list, 1101 &tmptgt, NULL)) == NULL) { 1102 itarget = kmem_zalloc(sizeof (isns_target_t), KM_SLEEP); 1103 1104 itarget->target = target; 1105 avl_add(&isns_target_list, itarget); 1106 } 1107 1108 return (itarget); 1109 } 1110 1111 static size_t 1112 isnst_make_reg_pdu(isns_pdu_t **pdu, iscsit_tgt_t *target, 1113 boolean_t svr_registered, isns_reg_type_t regtype) 1114 { 1115 idm_addr_list_t *default_portal_list = NULL; 1116 uint32_t default_portal_list_size; 1117 size_t pdu_size; 1118 char *str; 1119 int len; 1120 isns_target_t *itarget; 1121 iscsit_tgt_t *src; 1122 boolean_t reg_all = B_FALSE; 1123 uint16_t flags = 0; 1124 1125 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 1126 1127 /* 1128 * If any targets are using the default portal then get the global 1129 * list of portals. 1130 */ 1131 if (default_portal_online) { 1132 default_portal_list_size = idm_get_ipaddr(&default_portal_list); 1133 1134 if (default_portal_list_size == 0) { 1135 /* 1136 * If the default portal is online, then there should 1137 * be at least one default portal. 1138 */ 1139 return (0); 1140 } 1141 } 1142 1143 /* 1144 * Find a source attribute for this registration. 1145 * 1146 * If we're already registered, registering for the first time, or 1147 * updating a target, we'll use the target_name of the first target 1148 * in our list. 1149 * 1150 * The alternate case is that we're registering for the first time, 1151 * but target is non-NULL. In that case, we have no targets in our 1152 * list yet, so we use the passed in target's name. 1153 */ 1154 1155 if (svr_registered || (target == NULL) || 1156 (regtype == ISNS_UPDATE_TARGET)) { 1157 ASSERT(avl_numnodes(&isns_target_list) != 0); 1158 itarget = (isns_target_t *)avl_first(&isns_target_list); 1159 src = itarget->target; 1160 } else { 1161 src = target; 1162 } 1163 1164 /* 1165 * No target means we're registering everything. A regtype of 1166 * ISNS_UPDATE_TARGET means we're re-registering everything. 1167 * Whether we're registering or re-registering depends on if 1168 * we're already registered. 1169 */ 1170 1171 if ((target == NULL) || (regtype == ISNS_UPDATE_TARGET) || 1172 ((regtype == ISNS_REGISTER_TARGET) && 1173 default_portal_state_change)) { 1174 reg_all = B_TRUE; 1175 target = src; /* This will be the 1st tgt in our list */ 1176 default_portal_state_change = B_FALSE; 1177 1178 /* 1179 * If we're already registered, this will be a replacement 1180 * registration. In this case, we need to make sure our 1181 * source attribute is an already registered target. 1182 */ 1183 if (svr_registered) { 1184 flags = ISNS_FLAG_REPLACE_REG; 1185 while (itarget->target_registered == B_FALSE) { 1186 itarget = AVL_NEXT(&isns_target_list, 1187 itarget); 1188 } 1189 src = itarget->target; 1190 /* Reset itarget to the beginning of our list */ 1191 itarget = (isns_target_t *)avl_first(&isns_target_list); 1192 } 1193 } 1194 1195 pdu_size = isnst_create_pdu_header(ISNS_DEV_ATTR_REG, pdu, flags); 1196 if (pdu_size == 0) { 1197 if (default_portal_list) 1198 kmem_free(default_portal_list, 1199 default_portal_list_size); 1200 return (0); 1201 } 1202 1203 len = strlen(src->target_name) + 1; 1204 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 1205 len, src->target_name, 0) != 0) { 1206 goto pdu_error; 1207 } 1208 1209 /* 1210 * Message Key Attributes - EID 1211 */ 1212 len = strlen(isns_eid) + 1; 1213 1214 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID, 1215 len, isns_eid, 0) != 0) { 1216 goto pdu_error; 1217 } 1218 1219 /* Delimiter */ 1220 if (isnst_add_attr(*pdu, pdu_size, ISNS_DELIMITER_ATTR_ID, 1221 0, 0, 0) != 0) { 1222 goto pdu_error; 1223 } 1224 1225 /* 1226 * Operating Attributes 1227 */ 1228 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID, len, 1229 isns_eid, 0) != 0) { 1230 goto pdu_error; 1231 } 1232 1233 /* ENTITY Protocol - Section 6.2.2 */ 1234 if (isnst_add_attr(*pdu, pdu_size, ISNS_ENTITY_PROTOCOL_ATTR_ID, 1235 4, 0, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) { 1236 goto pdu_error; 1237 } 1238 1239 /* 1240 * Network entity portal information - only on the first registration. 1241 */ 1242 if (!svr_registered || (flags & ISNS_FLAG_REPLACE_REG)) { 1243 if (isnst_reg_pdu_add_entity_portals(*pdu, pdu_size, 1244 default_portal_list) != 0) { 1245 goto pdu_error; 1246 } 1247 } 1248 1249 do { 1250 /* Hold the target mutex */ 1251 mutex_enter(&target->target_mutex); 1252 1253 /* iSCSI Name - Section 6.4.1 */ 1254 str = target->target_name; 1255 len = strlen(str) + 1; 1256 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 1257 len, str, 0) != 0) { 1258 mutex_exit(&target->target_mutex); 1259 goto pdu_error; 1260 } 1261 1262 /* iSCSI Node Type */ 1263 if (isnst_add_attr(*pdu, pdu_size, 1264 ISNS_ISCSI_NODE_TYPE_ATTR_ID, 4, 0, 1265 ISNS_TARGET_NODE_TYPE) != 0) { 1266 mutex_exit(&target->target_mutex); 1267 goto pdu_error; 1268 } 1269 1270 /* iSCSI Alias */ 1271 if (nvlist_lookup_string(target->target_props, PROP_ALIAS, 1272 &str) == 0) { 1273 /* Found alias in property list */ 1274 len = strlen(str) + 1; 1275 if (isnst_add_attr(*pdu, pdu_size, 1276 ISNS_ISCSI_ALIAS_ATTR_ID, len, str, 0) != 0) { 1277 mutex_exit(&target->target_mutex); 1278 goto pdu_error; 1279 } 1280 } 1281 1282 if (isnst_reg_pdu_add_pg(*pdu, pdu_size, target, 1283 default_portal_list) != 0) { 1284 mutex_exit(&target->target_mutex); 1285 goto pdu_error; 1286 } 1287 1288 mutex_exit(&target->target_mutex); 1289 1290 if (reg_all) { 1291 itarget = AVL_NEXT(&isns_target_list, itarget); 1292 if (itarget) { 1293 target = itarget->target; 1294 } else { 1295 target = NULL; 1296 } 1297 } 1298 } while ((reg_all == B_TRUE) && (target != NULL)); 1299 1300 if (default_portal_list) 1301 kmem_free(default_portal_list, default_portal_list_size); 1302 1303 return (pdu_size); 1304 1305 pdu_error: 1306 /* packet too large, no memory */ 1307 kmem_free(*pdu, pdu_size); 1308 *pdu = NULL; 1309 if (default_portal_list) 1310 kmem_free(default_portal_list, default_portal_list_size); 1311 1312 return (0); 1313 } 1314 1315 1316 static int 1317 isnst_reg_pdu_add_entity_portals(isns_pdu_t *pdu, size_t pdu_size, 1318 idm_addr_list_t *default_portal_list) 1319 { 1320 isns_portal_list_t *portal; 1321 idm_addr_t *dportal; 1322 struct sockaddr_storage ss; 1323 struct sockaddr_in *sin; 1324 struct sockaddr_in6 *sin6; 1325 int idx; 1326 int dp_addr_size; 1327 1328 if (default_portal_list != NULL) { 1329 for (idx = 0; idx < default_portal_list->al_out_cnt; idx++) { 1330 dportal = &default_portal_list->al_addrs[idx]; 1331 1332 /* Build sockaddr_storage for this portal */ 1333 bzero(&ss, sizeof (ss)); 1334 dp_addr_size = dportal->a_addr.i_insize; 1335 if (dp_addr_size == sizeof (struct in_addr)) { 1336 /* IPv4 */ 1337 ss.ss_family = AF_INET; 1338 sin = (struct sockaddr_in *)&ss; 1339 sin->sin_port = htons(ISCSI_LISTEN_PORT); 1340 bcopy(&dportal->a_addr.i_addr.in4, 1341 &sin->sin_addr, sizeof (struct in_addr)); 1342 } else if (dp_addr_size == sizeof (struct in6_addr)) { 1343 ss.ss_family = AF_INET6; 1344 sin6 = (struct sockaddr_in6 *)&ss; 1345 sin6->sin6_port = htons(ISCSI_LISTEN_PORT); 1346 bcopy(&dportal->a_addr.i_addr.in6, 1347 &sin6->sin6_addr, sizeof (struct in6_addr)); 1348 } else { 1349 continue; 1350 } 1351 1352 if (isnst_add_portal_attr(pdu, pdu_size, 1353 ISNS_PORTAL_IP_ADDR_ATTR_ID, 1354 ISNS_PORTAL_PORT_ATTR_ID, 1355 &ss, B_TRUE /* ESI info */) != 0) { 1356 return (-1); 1357 } 1358 1359 } 1360 } else { 1361 portal = list_head(&portal_list); 1362 1363 while (portal != NULL) { 1364 if (isnst_add_portal_attr(pdu, pdu_size, 1365 ISNS_PORTAL_IP_ADDR_ATTR_ID, 1366 ISNS_PORTAL_PORT_ATTR_ID, 1367 &portal->portal_addr, B_TRUE /* ESI info */) != 0) { 1368 return (-1); 1369 } 1370 1371 portal = list_next(&portal_list, portal); 1372 } 1373 } 1374 1375 return (0); 1376 } 1377 1378 1379 static int 1380 isnst_reg_pdu_add_pg(isns_pdu_t *pdu, size_t pdu_size, iscsit_tgt_t *target, 1381 idm_addr_list_t *default_portal_list) 1382 { 1383 iscsit_tpgt_t *tpgt; 1384 iscsit_tpg_t *tpg; 1385 iscsit_portal_t *tp; 1386 int rval = 0; 1387 boolean_t use_default = B_FALSE; 1388 1389 1390 tpgt = avl_first(&target->target_tpgt_list); 1391 ASSERT(tpgt != NULL); 1392 do { 1393 /* 1394 * No need to explicitly register default PG. Any target 1395 * should have either an explicit portal list or 1396 * one and only one portal representing the default portal. 1397 */ 1398 ASSERT((avl_numnodes(&target->target_tpgt_list) == 1) || 1399 (tpgt->tpgt_tag != ISCSIT_DEFAULT_TPGT)); 1400 if (tpgt->tpgt_tag == ISCSIT_DEFAULT_TPGT) { 1401 use_default = B_TRUE; 1402 tpgt = AVL_NEXT(&target->target_tpgt_list, tpgt); 1403 continue; 1404 } 1405 1406 tpg = tpgt->tpgt_tpg; 1407 mutex_enter(&tpg->tpg_mutex); 1408 1409 tp = avl_first(&tpg->tpg_portal_list); 1410 1411 /* Portal Group Tag */ 1412 if (isnst_add_attr(pdu, pdu_size, 1413 ISNS_PG_TAG_ATTR_ID, 4, 0, tpgt->tpgt_tag) != 0) { 1414 mutex_exit(&tpg->tpg_mutex); 1415 rval = 1; 1416 goto pg_done; 1417 } 1418 1419 ASSERT(tp != NULL); 1420 do { 1421 if (isnst_add_portal_attr(pdu, pdu_size, 1422 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, 1423 ISNS_PG_PORTAL_PORT_ATTR_ID, 1424 &tp->portal_addr, B_FALSE /* ESI */) != 0) { 1425 mutex_exit(&tpg->tpg_mutex); 1426 rval = 1; 1427 goto pg_done; 1428 } 1429 1430 tp = AVL_NEXT(&tpg->tpg_portal_list, tp); 1431 } while (tp != NULL); 1432 1433 mutex_exit(&tpg->tpg_mutex); 1434 tpgt = AVL_NEXT(&target->target_tpgt_list, tpgt); 1435 } while (tpgt != NULL); 1436 1437 /* 1438 * If we are not using the default portal group we need to create 1439 * a NULL PG tag indicating some of the default portals should be 1440 * not be used to access this target. 1441 */ 1442 if (!use_default) { 1443 if (isnst_add_null_pg(pdu, pdu_size, target, 1444 default_portal_list) != 0) { 1445 rval = 1; 1446 goto pg_done; 1447 } 1448 } 1449 1450 pg_done: 1451 return (rval); 1452 } 1453 1454 static int 1455 isnst_add_null_pg(isns_pdu_t *pdu, size_t pdu_size, 1456 iscsit_tgt_t *tgt, idm_addr_list_t *default_portal_list) 1457 { 1458 isns_portal_list_t *portal; 1459 idm_addr_t *dportal; 1460 iscsit_portal_t *iscsit_portal; 1461 iscsit_tpgt_t *iscsit_tpgt; 1462 struct sockaddr_storage ss; 1463 struct sockaddr_in *sin; 1464 struct sockaddr_in6 *sin6; 1465 int idx; 1466 int dp_addr_size; 1467 boolean_t null_pg_tag = B_FALSE; 1468 1469 /* 1470 * Register all entity portals that aren't bound to this target in the 1471 * null pg. 1472 */ 1473 if (default_portal_list != NULL) { 1474 for (idx = 0; idx < default_portal_list->al_out_cnt; idx++) { 1475 dportal = &default_portal_list->al_addrs[idx]; 1476 1477 /* Build sockaddr_storage for this portal */ 1478 bzero(&ss, sizeof (ss)); 1479 dp_addr_size = dportal->a_addr.i_insize; 1480 if (dp_addr_size == sizeof (struct in_addr)) { 1481 /* IPv4 */ 1482 ss.ss_family = AF_INET; 1483 sin = (struct sockaddr_in *)&ss; 1484 sin->sin_port = htons(ISCSI_LISTEN_PORT); 1485 bcopy(&dportal->a_addr.i_addr.in4, 1486 &sin->sin_addr, sizeof (struct in_addr)); 1487 } else if (dp_addr_size == sizeof (struct in6_addr)) { 1488 ss.ss_family = AF_INET6; 1489 sin6 = (struct sockaddr_in6 *)&ss; 1490 sin6->sin6_port = htons(ISCSI_LISTEN_PORT); 1491 bcopy(&dportal->a_addr.i_addr.in6, 1492 &sin6->sin6_addr, sizeof (struct in6_addr)); 1493 } else { 1494 continue; 1495 } 1496 1497 iscsit_portal = iscsit_tgt_lookup_portal(tgt, 1498 &ss, &iscsit_tpgt); 1499 if (iscsit_portal == NULL) { 1500 /* 1501 * If this is the first NULL PG portal, then 1502 * write the NULL PG tag first. 1503 */ 1504 if (!null_pg_tag) { 1505 if (isnst_add_attr(pdu, pdu_size, 1506 ISNS_PG_TAG_ATTR_ID, 1507 0, 0, 0) != 0) { 1508 return (-1); 1509 } 1510 null_pg_tag = B_TRUE; 1511 } 1512 if (isnst_add_portal_attr(pdu, pdu_size, 1513 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, 1514 ISNS_PG_PORTAL_PORT_ATTR_ID, 1515 &ss, B_FALSE) != 0) { 1516 return (-1); 1517 } 1518 } else { 1519 iscsit_tpgt_rele(iscsit_tpgt); 1520 iscsit_portal_rele(iscsit_portal); 1521 } 1522 } 1523 } else { 1524 portal = list_head(&portal_list); 1525 1526 while (portal != NULL) { 1527 iscsit_portal = iscsit_tgt_lookup_portal(tgt, 1528 &portal->portal_addr, &iscsit_tpgt); 1529 if (iscsit_portal == NULL) { 1530 /* 1531 * If this is the first NULL PG portal, then 1532 * write the NULL PG tag first. 1533 */ 1534 if (!null_pg_tag) { 1535 if (isnst_add_attr(pdu, pdu_size, 1536 ISNS_PG_TAG_ATTR_ID, 1537 0, 0, 0) != 0) { 1538 return (-1); 1539 } 1540 null_pg_tag = B_TRUE; 1541 } 1542 if (isnst_add_portal_attr(pdu, pdu_size, 1543 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, 1544 ISNS_PG_PORTAL_PORT_ATTR_ID, 1545 &portal->portal_addr, B_FALSE) != 0) { 1546 return (-1); 1547 } 1548 } else { 1549 iscsit_tpgt_rele(iscsit_tpgt); 1550 iscsit_portal_rele(iscsit_portal); 1551 } 1552 1553 portal = list_next(&portal_list, portal); 1554 } 1555 } 1556 1557 return (0); 1558 } 1559 1560 1561 static int 1562 isnst_add_portal_attr(isns_pdu_t *pdu, size_t pdu_size, 1563 uint32_t ip_attr_id, uint32_t port_attr_id, 1564 struct sockaddr_storage *ss, boolean_t esi_info) 1565 { 1566 struct sockaddr_in *in; 1567 struct sockaddr_in6 *in6; 1568 uint32_t attr_numeric_data; 1569 void *inaddrp; 1570 1571 in = (struct sockaddr_in *)ss; 1572 in6 = (struct sockaddr_in6 *)ss; 1573 1574 ASSERT((ss->ss_family == AF_INET) || (ss->ss_family == AF_INET6)); 1575 1576 if (ss->ss_family == AF_INET) { 1577 attr_numeric_data = sizeof (in_addr_t); 1578 inaddrp = (void *)&in->sin_addr; 1579 } else if (ss->ss_family == AF_INET6) { 1580 attr_numeric_data = sizeof (in6_addr_t); 1581 inaddrp = (void *)&in6->sin6_addr; 1582 } 1583 1584 /* Portal Group Portal IP Address */ 1585 if (isnst_add_attr(pdu, pdu_size, ip_attr_id, 1586 16, inaddrp, attr_numeric_data) != 0) { 1587 return (1); 1588 } 1589 1590 /* Portal Group Portal Port */ 1591 if (isnst_add_attr(pdu, pdu_size, port_attr_id, 1592 4, 0, ntohs(in->sin_port)) != 0) { 1593 return (1); 1594 } 1595 1596 mutex_enter(&esi.esi_mutex); 1597 if (esi_info && esi.esi_valid) { 1598 /* ESI interval and port */ 1599 if (isnst_add_attr(pdu, pdu_size, ISNS_ESI_INTERVAL_ATTR_ID, 4, 1600 NULL, 20) != 0) { 1601 return (1); 1602 } 1603 1604 if (isnst_add_attr(pdu, pdu_size, ISNS_ESI_PORT_ATTR_ID, 4, 1605 NULL, esi.esi_port) != 0) { 1606 return (1); 1607 } 1608 } 1609 mutex_exit(&esi.esi_mutex); 1610 1611 return (0); 1612 } 1613 1614 static int 1615 isnst_deregister(iscsit_isns_svr_t *svr, char *node) 1616 { 1617 int rc; 1618 isns_pdu_t *pdu, *rsp; 1619 size_t pdu_size, rsp_size; 1620 struct sonode *so; 1621 1622 if ((svr->svr_registered == B_FALSE) || 1623 (avl_numnodes(&isns_target_list) == 0)) { 1624 return (0); 1625 } 1626 1627 so = isnst_open_so(&svr->svr_sa); 1628 1629 if (so == NULL) { 1630 return (-1); 1631 } 1632 1633 pdu_size = isnst_make_dereg_pdu(&pdu, node); 1634 if (pdu_size == 0) { 1635 isnst_close_so(so); 1636 return (-1); 1637 } 1638 1639 rc = isnst_send_pdu(so, pdu); 1640 if (rc != 0) { 1641 isnst_close_so(so); 1642 kmem_free(pdu, pdu_size); 1643 return (rc); 1644 } 1645 1646 rsp_size = isnst_rcv_pdu(so, &rsp); 1647 if (rsp_size == 0) { 1648 isnst_close_so(so); 1649 kmem_free(pdu, pdu_size); 1650 return (-1); 1651 } 1652 1653 rc = isnst_verify_rsp(svr, pdu, rsp, rsp_size); 1654 1655 isnst_close_so(so); 1656 kmem_free(pdu, pdu_size); 1657 kmem_free(rsp, rsp_size); 1658 1659 return (rc); 1660 } 1661 1662 static size_t 1663 isnst_make_dereg_pdu(isns_pdu_t **pdu, char *node) 1664 { 1665 size_t pdu_size; 1666 int len; 1667 isns_target_t *itarget; 1668 iscsit_tgt_t *target; 1669 int num_targets; 1670 1671 /* 1672 * create DevDereg Message with all of target nodes 1673 */ 1674 pdu_size = isnst_create_pdu_header(ISNS_DEV_DEREG, pdu, 0); 1675 if (pdu_size == 0) { 1676 return (0); 1677 } 1678 1679 /* 1680 * Source attribute - Must be a storage node in the same 1681 * network entity. We'll just grab the first one in the list. 1682 * If it's the only online target, we turn this into a total 1683 * deregistration regardless of the value of "node". 1684 */ 1685 1686 num_targets = avl_numnodes(&isns_target_list); 1687 itarget = avl_first(&isns_target_list); 1688 target = itarget->target; 1689 1690 len = strlen(target->target_name) + 1; 1691 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 1692 len, target->target_name, 0) != 0) { 1693 goto dereg_pdu_error; 1694 } 1695 1696 /* Delimiter */ 1697 if (isnst_add_attr(*pdu, pdu_size, ISNS_DELIMITER_ATTR_ID, 1698 0, 0, 0) != 0) { 1699 goto dereg_pdu_error; 1700 } 1701 1702 /* 1703 * Operating attributes 1704 */ 1705 if ((node == NULL) || (num_targets == 1)) { 1706 /* dereg everything */ 1707 len = strlen(isns_eid) + 1; 1708 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID, 1709 len, isns_eid, 0) != 0) { 1710 goto dereg_pdu_error; 1711 } 1712 } else { 1713 /* dereg one target only */ 1714 len = strlen(node) + 1; 1715 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 1716 len, node, 0) != 0) { 1717 goto dereg_pdu_error; 1718 } 1719 } 1720 1721 return (pdu_size); 1722 1723 dereg_pdu_error: 1724 kmem_free(*pdu, pdu_size); 1725 *pdu = NULL; 1726 1727 return (0); 1728 } 1729 1730 static int 1731 isnst_verify_rsp(iscsit_isns_svr_t *svr, isns_pdu_t *pdu, 1732 isns_pdu_t *rsp, size_t rsp_size) 1733 { 1734 uint16_t func_id; 1735 uint16_t payload_len, rsp_payload_len; 1736 isns_resp_t *resp; 1737 uint8_t *pp; 1738 isns_tlv_t *attr; 1739 uint32_t attr_len, attr_id, esi_interval; 1740 1741 /* 1742 * Ensure we have at least a valid header (don't count the 1743 * "payload" field. 1744 */ 1745 if (rsp_size < offsetof(isns_pdu_t, payload)) { 1746 ISNST_LOG(CE_WARN, "Invalid iSNS PDU header, %d of %d bytes", 1747 (int)rsp_size, (int)offsetof(isns_pdu_t, payload)); 1748 return (-1); 1749 } 1750 1751 /* Make sure we have the amount of data that the header specifies */ 1752 payload_len = ntohs(rsp->payload_len); 1753 if (rsp_size < (payload_len + offsetof(isns_pdu_t, payload))) { 1754 ISNST_LOG(CE_WARN, "Invalid iSNS response, %d of %d bytes", 1755 (int)rsp_size, 1756 (int)(payload_len + offsetof(isns_pdu_t, payload))); 1757 return (-1); 1758 } 1759 1760 /* validate response function id */ 1761 func_id = ntohs(rsp->func_id); 1762 switch (ntohs(pdu->func_id)) { 1763 case ISNS_DEV_ATTR_REG: 1764 if (func_id != ISNS_DEV_ATTR_REG_RSP) { 1765 return (-1); 1766 } 1767 1768 /* 1769 * Get the ESI interval returned by the server. It could 1770 * be different than what we asked for. We never know which 1771 * portal a request may come in on, and any server could demand 1772 * any interval. We'll simply keep track of the largest interval 1773 * for use in monitoring. 1774 */ 1775 1776 rsp_payload_len = isnst_pdu_get_op(rsp, &pp); 1777 attr = (isns_tlv_t *)((void *)pp); 1778 1779 /* 1780 * Make sure isnst_pdu_get_op didn't encounter an error 1781 * in the attributes. 1782 */ 1783 if (pp == NULL) { 1784 return (-1); 1785 } 1786 1787 while (rsp_payload_len) { 1788 attr_len = ntohl(attr->attr_len); 1789 attr_id = ntohl(attr->attr_id); 1790 1791 if (attr_id == ISNS_ESI_INTERVAL_ATTR_ID) { 1792 esi_interval = 1793 ntohl(*((uint32_t *) 1794 ((void *)(&attr->attr_value)))); 1795 1796 if (esi_interval > svr->svr_esi_interval) 1797 svr->svr_esi_interval = esi_interval; 1798 1799 break; 1800 } 1801 1802 rsp_payload_len -= (8 + attr_len); 1803 attr = (isns_tlv_t *) 1804 ((void *)((uint8_t *)attr + attr_len + 8)); 1805 } 1806 1807 break; 1808 case ISNS_DEV_DEREG: 1809 if (func_id != ISNS_DEV_DEREG_RSP) { 1810 return (-1); 1811 } 1812 break; 1813 default: 1814 ASSERT(0); 1815 break; 1816 } 1817 1818 /* verify response transaction id */ 1819 if (ntohs(rsp->xid) != ntohs(pdu->xid)) { 1820 return (-1); 1821 } 1822 1823 /* check the error code */ 1824 resp = (isns_resp_t *)((void *)&rsp->payload[0]); 1825 1826 return (ntohl(resp->status)); 1827 } 1828 1829 static uint16_t 1830 isnst_pdu_get_op(isns_pdu_t *pdu, uint8_t **pp) 1831 { 1832 uint8_t *payload; 1833 uint16_t payload_len; 1834 isns_resp_t *resp; 1835 isns_tlv_t *attr; 1836 uint32_t attr_id; 1837 uint32_t tlv_len; 1838 1839 /* get payload */ 1840 payload_len = ntohs(pdu->payload_len); 1841 resp = (isns_resp_t *)((void *)&pdu->payload[0]); 1842 1843 /* find the operating attributes */ 1844 if (payload_len < sizeof (resp->status)) { 1845 ISNST_LOG(CE_WARN, "Invalid iSNS response, %d payload bytes", 1846 payload_len); 1847 *pp = NULL; 1848 return (0); 1849 } 1850 1851 payload_len -= sizeof (resp->status); 1852 payload = &resp->data[0]; 1853 1854 while (payload_len >= (sizeof (isns_tlv_t) - 1)) { 1855 attr = (isns_tlv_t *)((void *)payload); 1856 tlv_len = offsetof(isns_tlv_t, attr_value) + 1857 ntohl(attr->attr_len); 1858 if (payload_len >= tlv_len) { 1859 payload += tlv_len; 1860 payload_len -= tlv_len; 1861 attr_id = ntohl(attr->attr_id); 1862 if (attr_id == ISNS_DELIMITER_ATTR_ID) { 1863 break; 1864 } 1865 } else { 1866 /* mal-formed packet */ 1867 payload = NULL; 1868 payload_len = 0; 1869 } 1870 } 1871 1872 *pp = payload; 1873 1874 return (payload_len); 1875 } 1876 1877 static size_t 1878 isnst_create_pdu_header(uint16_t func_id, isns_pdu_t **pdu, uint16_t flags) 1879 { 1880 size_t pdu_size = ISNSP_MAX_PDU_SIZE; 1881 1882 *pdu = (isns_pdu_t *)kmem_zalloc(pdu_size, KM_NOSLEEP); 1883 if (*pdu != NULL) { 1884 (*pdu)->version = htons((uint16_t)ISNSP_VERSION); 1885 (*pdu)->func_id = htons((uint16_t)func_id); 1886 (*pdu)->payload_len = htons(0); 1887 (*pdu)->flags = htons(flags); 1888 1889 (*pdu)->xid = htons(GET_XID()); 1890 (*pdu)->seq = htons(0); 1891 } else { 1892 pdu_size = 0; 1893 } 1894 1895 return (pdu_size); 1896 } 1897 1898 static int 1899 isnst_add_attr(isns_pdu_t *pdu, 1900 size_t max_pdu_size, 1901 uint32_t attr_id, 1902 uint32_t attr_len, 1903 void *attr_data, 1904 uint32_t attr_numeric_data) 1905 { 1906 isns_tlv_t *attr_tlv; 1907 uint8_t *payload_ptr; 1908 uint16_t payload_len; 1909 uint32_t normalized_attr_len; 1910 uint64_t attr_tlv_len; 1911 1912 /* The attribute length must be 4-byte aligned. Section 5.1.3. */ 1913 normalized_attr_len = (attr_len % 4) == 0 ? 1914 (attr_len) : (attr_len + (4 - (attr_len % 4))); 1915 attr_tlv_len = ISNS_TLV_ATTR_ID_LEN + 1916 ISNS_TLV_ATTR_LEN_LEN + normalized_attr_len; 1917 1918 /* Check if we are going to exceed the maximum PDU length. */ 1919 payload_len = ntohs(pdu->payload_len); 1920 if ((payload_len + attr_tlv_len) > max_pdu_size) { 1921 return (1); 1922 } 1923 1924 attr_tlv = (isns_tlv_t *)kmem_zalloc(attr_tlv_len, KM_SLEEP); 1925 1926 attr_tlv->attr_id = htonl(attr_id); 1927 1928 switch (attr_id) { 1929 case ISNS_DELIMITER_ATTR_ID: 1930 break; 1931 1932 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 1933 case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: 1934 if (attr_numeric_data == sizeof (in_addr_t)) { 1935 /* IPv4 */ 1936 attr_tlv->attr_value[10] = 0xFF; 1937 attr_tlv->attr_value[11] = 0xFF; 1938 bcopy(attr_data, ((attr_tlv->attr_value) + 12), 1939 sizeof (in_addr_t)); 1940 } else if (attr_numeric_data == sizeof (in6_addr_t)) { 1941 /* IPv6 */ 1942 bcopy(attr_data, attr_tlv->attr_value, 1943 sizeof (in6_addr_t)); 1944 } else if (attr_numeric_data == 0) { 1945 /* EMPTY */ 1946 /* Do nothing */ 1947 } else { 1948 kmem_free(attr_tlv, attr_tlv_len); 1949 attr_tlv = NULL; 1950 return (1); 1951 } 1952 break; 1953 1954 case ISNS_EID_ATTR_ID: 1955 case ISNS_ISCSI_NAME_ATTR_ID: 1956 case ISNS_ISCSI_ALIAS_ATTR_ID: 1957 case ISNS_PG_ISCSI_NAME_ATTR_ID: 1958 if (attr_len && attr_data) { 1959 bcopy((char *)attr_data, 1960 attr_tlv->attr_value, attr_len); 1961 } 1962 break; 1963 1964 default: 1965 if (attr_len == 8) { 1966 *(uint64_t *)((void *)attr_tlv->attr_value) = 1967 BE_64((uint64_t)attr_numeric_data); 1968 } else if (attr_len == 4) { 1969 *(uint32_t *)((void *)attr_tlv->attr_value) = 1970 htonl((uint32_t)attr_numeric_data); 1971 } 1972 break; 1973 } 1974 1975 attr_tlv->attr_len = htonl(normalized_attr_len); 1976 /* 1977 * Convert the network byte ordered payload length to host byte 1978 * ordered for local address calculation. 1979 */ 1980 payload_len = ntohs(pdu->payload_len); 1981 payload_ptr = pdu->payload + payload_len; 1982 bcopy(attr_tlv, payload_ptr, attr_tlv_len); 1983 payload_len += attr_tlv_len; 1984 1985 /* 1986 * Convert the host byte ordered payload length back to network 1987 * byte ordered - it's now ready to be sent on the wire. 1988 */ 1989 pdu->payload_len = htons(payload_len); 1990 1991 kmem_free(attr_tlv, attr_tlv_len); 1992 attr_tlv = NULL; 1993 1994 return (0); 1995 } 1996 1997 static void 1998 isnst_so_timeout(void *so) 1999 { 2000 /* Wake up any sosend or sorecv blocked on this socket */ 2001 idm_soshutdown(so); 2002 } 2003 2004 static int 2005 isnst_send_pdu(void *so, isns_pdu_t *pdu) 2006 { 2007 size_t total_len, payload_len, send_len; 2008 uint8_t *payload; 2009 uint16_t flags, seq; 2010 timeout_id_t send_timer; 2011 iovec_t iov[2]; 2012 int rc; 2013 2014 /* update pdu flags */ 2015 flags = ntohs(pdu->flags); 2016 flags |= ISNS_FLAG_CLIENT; 2017 flags |= ISNS_FLAG_FIRST_PDU; 2018 2019 /* initalize sequence number */ 2020 seq = 0; 2021 2022 payload = pdu->payload; 2023 2024 /* total payload length */ 2025 total_len = ntohs(pdu->payload_len); 2026 2027 /* fill in the pdu header */ 2028 iov[0].iov_base = (void *)pdu; 2029 iov[0].iov_len = ISNSP_HEADER_SIZE; 2030 2031 do { 2032 /* split the payload accordingly */ 2033 if (total_len > ISNSP_MAX_PAYLOAD_SIZE) { 2034 payload_len = ISNSP_MAX_PAYLOAD_SIZE; 2035 } else { 2036 payload_len = total_len; 2037 /* set the last pdu flag */ 2038 flags |= ISNS_FLAG_LAST_PDU; 2039 } 2040 2041 /* set back the pdu flags */ 2042 pdu->flags = htons(flags); 2043 /* set the sequence number */ 2044 pdu->seq = htons(seq); 2045 /* set the payload length */ 2046 pdu->payload_len = htons(payload_len); 2047 2048 /* fill in the payload */ 2049 iov[1].iov_base = (void *)payload; 2050 iov[1].iov_len = payload_len; 2051 2052 DTRACE_PROBE3(isnst__pdu__send, uint16_t, ntohs(pdu->func_id), 2053 uint16_t, ntohs(pdu->payload_len), caddr_t, pdu); 2054 2055 /* send the pdu */ 2056 send_len = ISNSP_HEADER_SIZE + payload_len; 2057 send_timer = timeout(isnst_so_timeout, so, 2058 drv_usectohz(ISNS_RCV_TIMER_SECONDS * 1000000)); 2059 rc = idm_iov_sosend(so, &iov[0], 2, send_len); 2060 (void) untimeout(send_timer); 2061 2062 flags &= ~ISNS_FLAG_FIRST_PDU; 2063 payload += payload_len; 2064 total_len -= payload_len; 2065 2066 /* increase the sequence number */ 2067 seq ++; 2068 2069 } while (rc == 0 && total_len > 0); 2070 2071 return (rc); 2072 } 2073 2074 static size_t 2075 isnst_rcv_pdu(void *so, isns_pdu_t **pdu) 2076 { 2077 size_t total_pdu_len; 2078 size_t total_payload_len; 2079 size_t payload_len; 2080 size_t combined_len; 2081 isns_pdu_t tmp_pdu_hdr; 2082 isns_pdu_t *combined_pdu; 2083 uint8_t *payload; 2084 uint8_t *combined_payload; 2085 timeout_id_t rcv_timer; 2086 uint16_t flags; 2087 uint16_t seq; 2088 2089 *pdu = NULL; 2090 total_pdu_len = total_payload_len = 0; 2091 payload = NULL; 2092 seq = 0; 2093 2094 do { 2095 /* receive the pdu header */ 2096 rcv_timer = timeout(isnst_so_timeout, so, 2097 drv_usectohz(ISNS_RCV_TIMER_SECONDS * 1000000)); 2098 if (idm_sorecv(so, &tmp_pdu_hdr, ISNSP_HEADER_SIZE) != 0 || 2099 ntohs(tmp_pdu_hdr.seq) != seq) { 2100 (void) untimeout(rcv_timer); 2101 goto rcv_error; 2102 } 2103 (void) untimeout(rcv_timer); 2104 2105 /* receive the payload */ 2106 payload_len = ntohs(tmp_pdu_hdr.payload_len); 2107 payload = kmem_alloc(payload_len, KM_SLEEP); 2108 rcv_timer = timeout(isnst_so_timeout, so, 2109 drv_usectohz(ISNS_RCV_TIMER_SECONDS * 1000000)); 2110 if (idm_sorecv(so, payload, payload_len) != 0) { 2111 (void) untimeout(rcv_timer); 2112 goto rcv_error; 2113 } 2114 (void) untimeout(rcv_timer); 2115 2116 /* combine the pdu if it is not the first one */ 2117 if (total_pdu_len > 0) { 2118 combined_len = total_pdu_len + payload_len; 2119 combined_pdu = kmem_alloc(combined_len, KM_SLEEP); 2120 bcopy(*pdu, combined_pdu, total_pdu_len); 2121 combined_payload = 2122 &combined_pdu->payload[total_payload_len]; 2123 bcopy(payload, combined_payload, payload_len); 2124 kmem_free(*pdu, total_pdu_len); 2125 kmem_free(payload, payload_len); 2126 *pdu = combined_pdu; 2127 total_payload_len += payload_len; 2128 total_pdu_len += payload_len; 2129 (*pdu)->payload_len = htons(total_payload_len); 2130 } else { 2131 total_payload_len = payload_len; 2132 total_pdu_len = ISNSP_HEADER_SIZE + payload_len; 2133 *pdu = kmem_alloc(total_pdu_len, KM_SLEEP); 2134 bcopy(&tmp_pdu_hdr, *pdu, ISNSP_HEADER_SIZE); 2135 bcopy(payload, &(*pdu)->payload[0], payload_len); 2136 kmem_free(payload, payload_len); 2137 } 2138 payload = NULL; 2139 2140 /* the flags of pdu which is just received */ 2141 flags = ntohs(tmp_pdu_hdr.flags); 2142 2143 /* increase sequence number by one */ 2144 seq ++; 2145 } while ((flags & ISNS_FLAG_LAST_PDU) == 0); 2146 2147 DTRACE_PROBE3(isnst__pdu__recv, uint16_t, ntohs((*pdu)->func_id), 2148 size_t, total_payload_len, caddr_t, *pdu); 2149 2150 return (total_pdu_len); 2151 2152 rcv_error: 2153 if (*pdu != NULL) { 2154 kmem_free(*pdu, total_pdu_len); 2155 *pdu = NULL; 2156 } 2157 if (payload != NULL) { 2158 kmem_free(payload, payload_len); 2159 } 2160 return (0); 2161 } 2162 2163 static void * 2164 isnst_open_so(struct sockaddr_storage *sa) 2165 { 2166 int sa_sz; 2167 ksocket_t so; 2168 2169 /* determin local IP address */ 2170 if (sa->ss_family == AF_INET) { 2171 /* IPv4 */ 2172 sa_sz = sizeof (struct sockaddr_in); 2173 2174 /* Create socket */ 2175 so = idm_socreate(AF_INET, SOCK_STREAM, 0); 2176 } else { 2177 /* IPv6 */ 2178 sa_sz = sizeof (struct sockaddr_in6); 2179 2180 /* Create socket */ 2181 so = idm_socreate(AF_INET6, SOCK_STREAM, 0); 2182 } 2183 2184 if (so != NULL) { 2185 if (ksocket_connect(so, (struct sockaddr *)sa, sa_sz, CRED()) 2186 != 0) { 2187 /* not calling isnst_close_so() to */ 2188 /* make dtrace output look clear */ 2189 idm_soshutdown(so); 2190 idm_sodestroy(so); 2191 so = NULL; 2192 } 2193 } 2194 2195 if (so == NULL) { 2196 struct sockaddr_in *sin; 2197 struct sockaddr_in6 *sin6; 2198 char s[INET6_ADDRSTRLEN]; 2199 void *ip; 2200 uint16_t port; 2201 sin = (struct sockaddr_in *)sa; 2202 port = ntohs(sin->sin_port); 2203 if (sa->ss_family == AF_INET) { 2204 ip = (void *)&sin->sin_addr.s_addr; 2205 (void) inet_ntop(AF_INET, ip, s, sizeof (s)); 2206 } else { 2207 sin6 = (struct sockaddr_in6 *)sa; 2208 ip = (void *)&sin6->sin6_addr.s6_addr; 2209 (void) inet_ntop(AF_INET6, ip, s, sizeof (s)); 2210 } 2211 ISNST_LOG(CE_WARN, "open iSNS Server %s:%u failed", s, port); 2212 } 2213 2214 return (so); 2215 } 2216 2217 static void 2218 isnst_close_so(void *so) 2219 { 2220 idm_soshutdown(so); 2221 idm_sodestroy(so); 2222 } 2223 2224 2225 /* 2226 * ESI handling 2227 */ 2228 2229 static void 2230 isnst_esi_start(void) 2231 { 2232 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 2233 2234 ISNST_LOG(CE_NOTE, "isnst_esi_start"); 2235 2236 mutex_enter(&esi.esi_mutex); 2237 esi.esi_enabled = B_TRUE; 2238 esi.esi_thread_running = B_FALSE; 2239 esi.esi_valid = B_FALSE; 2240 esi.esi_thread = thread_create(NULL, 0, isnst_esi_thread, 2241 (void *)&esi, 0, &p0, TS_RUN, minclsyspri); 2242 2243 /* 2244 * Wait for the thread to start 2245 */ 2246 while (!esi.esi_thread_running) { 2247 cv_wait(&esi.esi_cv, &esi.esi_mutex); 2248 } 2249 mutex_exit(&esi.esi_mutex); 2250 } 2251 2252 static void 2253 isnst_esi_stop() 2254 { 2255 ISNST_LOG(CE_NOTE, "isnst_esi_stop"); 2256 2257 /* Shutdown ESI listening socket, wait for thread to terminate */ 2258 mutex_enter(&esi.esi_mutex); 2259 esi.esi_enabled = B_FALSE; 2260 if (esi.esi_valid) { 2261 idm_soshutdown(esi.esi_so); 2262 mutex_exit(&esi.esi_mutex); 2263 idm_sodestroy(esi.esi_so); 2264 } else { 2265 mutex_exit(&esi.esi_mutex); 2266 } 2267 thread_join(esi.esi_thread_did); 2268 2269 } 2270 2271 /* 2272 * isnst_esi_thread 2273 * 2274 * This function listens on a socket for incoming connections from an 2275 * iSNS server until told to stop. 2276 */ 2277 2278 /*ARGSUSED*/ 2279 static void 2280 isnst_esi_thread(void *arg) 2281 { 2282 ksocket_t newso; 2283 struct sockaddr_in6 sin6; 2284 socklen_t sin_addrlen; 2285 uint32_t on = 1; 2286 int rc; 2287 isns_pdu_t *pdu; 2288 size_t pl_size; 2289 2290 bzero(&sin6, sizeof (struct sockaddr_in6)); 2291 sin_addrlen = sizeof (struct sockaddr_in6); 2292 2293 esi.esi_thread_did = curthread->t_did; 2294 2295 mutex_enter(&esi.esi_mutex); 2296 2297 /* 2298 * Mark the thread as running and the portal as no longer new. 2299 */ 2300 esi.esi_thread_running = B_TRUE; 2301 cv_signal(&esi.esi_cv); 2302 2303 while (esi.esi_enabled) { 2304 /* 2305 * Create a socket to listen for requests from the iSNS server. 2306 */ 2307 DTRACE_PROBE1(iscsit__isns__esi__socreate, 2308 boolean_t, esi.esi_enabled); 2309 if ((esi.esi_so = idm_socreate(PF_INET6, SOCK_STREAM, 0)) == 2310 NULL) { 2311 ISNST_LOG(CE_WARN, 2312 "isnst_esi_thread: Unable to create socket"); 2313 mutex_exit(&esi.esi_mutex); 2314 delay(drv_usectohz(1000000)); 2315 mutex_enter(&esi.esi_mutex); 2316 continue; 2317 } 2318 2319 /* 2320 * Set options, bind, and listen until we're told to stop 2321 */ 2322 bzero(&sin6, sizeof (sin6)); 2323 sin6.sin6_family = AF_INET6; 2324 sin6.sin6_port = htons(0); 2325 sin6.sin6_addr = in6addr_any; 2326 2327 (void) ksocket_setsockopt(esi.esi_so, SOL_SOCKET, 2328 SO_REUSEADDR, (char *)&on, sizeof (on), CRED()); 2329 2330 if (ksocket_bind(esi.esi_so, (struct sockaddr *)&sin6, 2331 sizeof (sin6), CRED()) != 0) { 2332 ISNST_LOG(CE_WARN, "Unable to bind socket for ESI"); 2333 idm_sodestroy(esi.esi_so); 2334 mutex_exit(&esi.esi_mutex); 2335 delay(drv_usectohz(1000000)); 2336 mutex_enter(&esi.esi_mutex); 2337 continue; 2338 } 2339 2340 /* 2341 * Get the port (sin6 is meaningless at this point) 2342 */ 2343 (void) ksocket_getsockname(esi.esi_so, 2344 (struct sockaddr *)(&sin6), &sin_addrlen, CRED()); 2345 esi.esi_port = 2346 ntohs(((struct sockaddr_in6 *)(&sin6))->sin6_port); 2347 2348 if ((rc = ksocket_listen(esi.esi_so, 5, CRED())) != 0) { 2349 ISNST_LOG(CE_WARN, "isnst_esi_thread: listen " 2350 "failure 0x%x", rc); 2351 idm_sodestroy(esi.esi_so); 2352 mutex_exit(&esi.esi_mutex); 2353 delay(drv_usectohz(1000000)); 2354 mutex_enter(&esi.esi_mutex); 2355 continue; 2356 } 2357 2358 ksocket_hold(esi.esi_so); 2359 esi.esi_valid = B_TRUE; 2360 while (esi.esi_enabled) { 2361 mutex_exit(&esi.esi_mutex); 2362 2363 DTRACE_PROBE1(iscsit__isns__esi__accept__wait, 2364 boolean_t, esi.esi_enabled); 2365 if ((rc = ksocket_accept(esi.esi_so, NULL, NULL, 2366 &newso, CRED())) != 0) { 2367 mutex_enter(&esi.esi_mutex); 2368 DTRACE_PROBE2(iscsit__isns__esi__accept__fail, 2369 int, rc, boolean_t, esi.esi_enabled); 2370 /* 2371 * If we were interrupted with EINTR 2372 * it's not really a failure. 2373 */ 2374 ISNST_LOG(CE_WARN, "isnst_esi_thread: " 2375 "accept failure (0x%x)", rc); 2376 2377 delay(drv_usectohz(100000)); 2378 if (rc == EINTR) { 2379 continue; 2380 } else { 2381 break; 2382 } 2383 } 2384 DTRACE_PROBE2(iscsit__isns__esi__accept, 2385 boolean_t, esi.esi_enabled, 2386 ksocket_t, newso); 2387 2388 pl_size = isnst_rcv_pdu(newso, &pdu); 2389 if (pl_size == 0) { 2390 ISNST_LOG(CE_WARN, "isnst_esi_thread: " 2391 "rcv_pdu failure"); 2392 (void) ksocket_close(newso, CRED()); 2393 2394 mutex_enter(&esi.esi_mutex); 2395 continue; 2396 } 2397 2398 isnst_handle_esi_req(newso, pdu, pl_size); 2399 2400 (void) ksocket_close(newso, CRED()); 2401 2402 /* 2403 * Do not hold the esi mutex during server timestamp 2404 * update. It requires the isns global lock, which may 2405 * be held during other functions that also require 2406 * the esi_mutex (potential deadlock). 2407 */ 2408 isnst_update_server_timestamp(newso); 2409 mutex_enter(&esi.esi_mutex); 2410 } 2411 2412 idm_soshutdown(esi.esi_so); 2413 ksocket_rele(esi.esi_so); 2414 esi.esi_valid = B_FALSE; 2415 2416 /* 2417 * If we're going to try to re-establish the listener then 2418 * destroy this socket. Otherwise isnst_esi_stop already 2419 * destroyed it. 2420 */ 2421 if (esi.esi_enabled) 2422 idm_sodestroy(esi.esi_so); 2423 } 2424 2425 esi.esi_thread_running = B_FALSE; 2426 cv_signal(&esi.esi_cv); 2427 mutex_exit(&esi.esi_mutex); 2428 esi_thread_exit: 2429 thread_exit(); 2430 } 2431 2432 /* 2433 * Handle an incoming ESI request 2434 */ 2435 2436 static void 2437 isnst_handle_esi_req(ksocket_t ks, isns_pdu_t *pdu, size_t pdu_size) 2438 { 2439 static char log_addr_buf[INET6_ADDRSTRLEN]; 2440 isns_pdu_t *rsp_pdu; 2441 isns_resp_t *rsp; 2442 isns_tlv_t *attr; 2443 uint32_t attr_len, attr_id; 2444 size_t req_pl_len, rsp_size, tlv_len; 2445 struct sockaddr_storage ss; 2446 struct sockaddr_in6 *portal_addr6; 2447 boolean_t portal_addr_valid = B_FALSE; 2448 boolean_t portal_port_valid = B_FALSE; 2449 uint32_t esi_response = ISNS_RSP_SUCCESSFUL; 2450 isns_portal_list_t *portal; 2451 2452 if (ntohs(pdu->func_id) != ISNS_ESI) { 2453 ISNST_LOG(CE_WARN, "isnst_handle_esi_req: Unexpected func 0x%x", 2454 pdu->func_id); 2455 kmem_free(pdu, pdu_size); 2456 return; 2457 } 2458 2459 req_pl_len = ntohs(pdu->payload_len); 2460 if (req_pl_len + offsetof(isns_pdu_t, payload) > pdu_size) { 2461 ISNST_LOG(CE_WARN, "isnst_handle_esi_req: " 2462 "payload exceeds PDU size (%d > %d)", 2463 (int)(req_pl_len + offsetof(isns_pdu_t, payload)), 2464 (int)pdu_size); 2465 /* Not all data is present -- ignore */ 2466 kmem_free(pdu, pdu_size); 2467 return; 2468 } 2469 2470 if (req_pl_len + sizeof (uint32_t) > ISNSP_MAX_PAYLOAD_SIZE) { 2471 ISNST_LOG(CE_WARN, 2472 "isnst_handle_esi_req: PDU payload exceeds max (%ld bytes)", 2473 req_pl_len + sizeof (uint32_t)); 2474 kmem_free(pdu, pdu_size); 2475 return; 2476 } 2477 2478 /* 2479 * Check portal in ESI request and make sure it is valid. Return 2480 * esi_response of ISNS_RSP_SUCCESSFUL if valid, otherwise don't 2481 * respond at all. Get IP addr and port. Format of ESI 2482 * is: 2483 * 2484 * ISNS_TIMESTAMP_ATTR_ID, 2485 * ISNS_EID_ATTR_ID, 2486 * ISNS_PORTAL_IP_ADDR_ATTR_ID, 2487 * ISNS_PORTAL_PORT_ATTR_ID 2488 */ 2489 bzero(&ss, sizeof (struct sockaddr_storage)); 2490 ss.ss_family = AF_INET6; 2491 portal_addr6 = (struct sockaddr_in6 *)&ss; 2492 attr = (isns_tlv_t *)((void *)&pdu->payload); 2493 attr_len = ntohl(attr->attr_len); 2494 attr_id = ntohl(attr->attr_id); 2495 tlv_len = attr_len + offsetof(isns_tlv_t, attr_value); 2496 while (tlv_len <= req_pl_len) { 2497 switch (attr_id) { 2498 case ISNS_TIMESTAMP_ATTR_ID: 2499 break; 2500 case ISNS_EID_ATTR_ID: 2501 break; 2502 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 2503 if (attr_len > sizeof (struct in6_addr)) { 2504 /* Bad attribute format */ 2505 esi_response = ISNS_RSP_MSG_FORMAT_ERROR; 2506 } else { 2507 portal_addr6->sin6_family = AF_INET6; 2508 attr_len = min(attr_len, 2509 sizeof (portal_addr6->sin6_addr)); 2510 bcopy(attr->attr_value, 2511 portal_addr6->sin6_addr.s6_addr, attr_len); 2512 portal_addr_valid = B_TRUE; 2513 } 2514 break; 2515 case ISNS_PORTAL_PORT_ATTR_ID: 2516 if (attr_len > sizeof (uint32_t)) { 2517 /* Bad attribute format */ 2518 esi_response = ISNS_RSP_MSG_FORMAT_ERROR; 2519 } else { 2520 portal_addr6->sin6_port = 2521 htons((uint16_t)BE_IN32(attr->attr_value)); 2522 portal_port_valid = B_TRUE; 2523 } 2524 break; 2525 default: 2526 /* Bad request format */ 2527 esi_response = ISNS_RSP_MSG_FORMAT_ERROR; 2528 break; 2529 } 2530 2531 /* If we've set an error then stop processing */ 2532 if (esi_response != ISNS_RSP_SUCCESSFUL) { 2533 break; 2534 } 2535 2536 /* Get next attribute */ 2537 req_pl_len -= tlv_len; 2538 attr = (isns_tlv_t *)((void *)((uint8_t *)attr + tlv_len)); 2539 attr_len = ntohl(attr->attr_len); 2540 attr_id = ntohl(attr->attr_id); 2541 tlv_len = attr_len + offsetof(isns_tlv_t, attr_value); 2542 } 2543 2544 if (!portal_port_valid) 2545 portal_addr6->sin6_port = htons(ISCSI_LISTEN_PORT); 2546 2547 if (portal_addr_valid) { 2548 ISNST_LOG(CE_NOTE, "ESI %s:%d", 2549 inet_ntop(AF_INET6, &portal_addr6->sin6_addr, log_addr_buf, 2550 INET6_ADDRSTRLEN), 2551 ntohs(portal_addr6->sin6_port)); 2552 } else { 2553 esi_response = ISNS_RSP_MSG_FORMAT_ERROR; 2554 } 2555 2556 /* 2557 * If we've detected an error or if the portal does not 2558 * exist then drop the request. The server will eventually 2559 * timeout the portal and eliminate it from the list. 2560 */ 2561 2562 ISNS_GLOBAL_LOCK(); 2563 if ((esi_response != ISNS_RSP_SUCCESSFUL) || 2564 !isnst_portal_exists(&ss)) { 2565 ISNS_GLOBAL_UNLOCK(); 2566 kmem_free(pdu, pdu_size); 2567 return; 2568 } 2569 ISNS_GLOBAL_UNLOCK(); 2570 2571 /* 2572 * Build response validating the portal 2573 */ 2574 rsp_size = isnst_create_pdu_header(ISNS_ESI_RSP, &rsp_pdu, 0); 2575 2576 if (rsp_size == 0) { 2577 ISNST_LOG(CE_WARN, "isnst_handle_esi_req: Can't get rsp pdu"); 2578 kmem_free(pdu, pdu_size); 2579 return; 2580 } 2581 2582 rsp = (isns_resp_t *)((void *)(&rsp_pdu->payload[0])); 2583 2584 /* Use xid from the request pdu */ 2585 rsp_pdu->xid = pdu->xid; 2586 rsp->status = htonl(ISNS_RSP_SUCCESSFUL); 2587 2588 /* Copy original data */ 2589 req_pl_len = ntohs(pdu->payload_len); 2590 bcopy(pdu->payload, rsp->data, req_pl_len); 2591 rsp_pdu->payload_len = htons(req_pl_len + sizeof (uint32_t)); 2592 2593 if (isnst_send_pdu(ks, rsp_pdu) != 0) { 2594 ISNST_LOG(CE_WARN, 2595 "isnst_handle_esi_req: Send response failed"); 2596 } 2597 2598 kmem_free(rsp_pdu, rsp_size); 2599 kmem_free(pdu, pdu_size); 2600 2601 /* 2602 * Update ESI timestamps for all matching portals. Iscsit may or 2603 * may not allow portals to belong to multiple portal groups depending 2604 * on the policy it implements. The iSNS client does not know or 2605 * care so we allow for multiple hits in the list. 2606 */ 2607 ISNS_GLOBAL_LOCK(); 2608 for (portal = isnst_lookup_portal(&ss, NULL); 2609 portal != NULL; 2610 portal = isnst_lookup_portal(&ss, portal)) { 2611 gethrestime(&portal->portal_esi_timestamp); 2612 } 2613 ISNS_GLOBAL_UNLOCK(); 2614 } 2615 2616 int 2617 isnst_tgt_avl_compare(const void *t1, const void *t2) 2618 { 2619 const isns_target_t *tgt1 = t1; 2620 const isns_target_t *tgt2 = t2; 2621 2622 /* 2623 * Sort by target (pointer to iscsit_tgt_t). 2624 */ 2625 2626 if (tgt1->target < tgt2->target) { 2627 return (-1); 2628 } else if (tgt1->target > tgt2->target) { 2629 return (1); 2630 } 2631 2632 return (0); 2633 } 2634 2635 static void 2636 isnst_get_target_list(void) 2637 { 2638 iscsit_tgt_t *tgt, *next_tgt; 2639 2640 /* 2641 * Initialize our list of targets with those from the global 2642 * list that are online. 2643 */ 2644 2645 for (tgt = avl_first(&iscsit_global.global_target_list); tgt != NULL; 2646 tgt = next_tgt) { 2647 next_tgt = AVL_NEXT(&iscsit_global.global_target_list, tgt); 2648 if (tgt->target_state == TS_STMF_ONLINE) { 2649 (void) isnst_add_to_target_list(tgt); 2650 } 2651 } 2652 } 2653 2654 static void 2655 isnst_set_server_status(iscsit_isns_svr_t *svr, boolean_t registered) 2656 { 2657 ASSERT(ISNS_GLOBAL_LOCK_HELD()); 2658 2659 if (registered == B_TRUE) { 2660 svr->svr_registered = B_TRUE; 2661 svr->svr_last_msg = ddi_get_lbolt(); 2662 } else { 2663 svr->svr_registered = B_FALSE; 2664 } 2665 } 2666 2667 static boolean_t 2668 isnst_lookup_default_portal(struct sockaddr_storage *p) 2669 { 2670 idm_addr_list_t *default_portal_list; 2671 uint32_t default_portal_list_size; 2672 idm_addr_t *dportal; 2673 struct sockaddr_storage dportal_ss; 2674 int idx; 2675 boolean_t result = B_FALSE; 2676 2677 /* 2678 * If the address we're looking up is not using the well known 2679 * port then it's inherently not a match for a default portal 2680 */ 2681 if (((struct sockaddr_in *)p)->sin_port != htons(ISCSI_LISTEN_PORT)) { 2682 return (B_FALSE); 2683 } 2684 2685 /* 2686 * Get the global list of default portals 2687 */ 2688 default_portal_list_size = idm_get_ipaddr(&default_portal_list); 2689 2690 if (default_portal_list_size == 0) { 2691 ISNST_LOG(CE_WARN, "isnst_lookup_default_portal: " 2692 "No default portals"); 2693 return (B_FALSE); 2694 } 2695 2696 /* 2697 * Scan the through the current default portal list (this should 2698 * be refreshed just before lookup since the contents can change) 2699 */ 2700 for (idx = 0; idx < default_portal_list->al_out_cnt; idx++) { 2701 dportal = &default_portal_list->al_addrs[idx]; 2702 2703 /* 2704 * Translate the address idm_get_ipaddr returned into 2705 * sockaddr_storage format 2706 */ 2707 bzero(&dportal_ss, sizeof (dportal_ss)); 2708 ((struct sockaddr_in *)&dportal_ss)->sin_port = 2709 htons(ISCSI_LISTEN_PORT); 2710 if (dportal->a_addr.i_insize == sizeof (struct in_addr)) { 2711 dportal_ss.ss_family = AF_INET; 2712 bcopy(&dportal->a_addr.i_addr.in4, 2713 &((struct sockaddr_in *)&dportal_ss)->sin_addr, 2714 sizeof (struct in_addr)); 2715 } else if (dportal->a_addr.i_insize == 2716 sizeof (struct in6_addr)) { 2717 dportal_ss.ss_family = AF_INET6; 2718 bcopy(&dportal->a_addr.i_addr.in6, 2719 &((struct sockaddr_in6 *)&dportal_ss)->sin6_addr, 2720 sizeof (struct in6_addr)); 2721 } else { 2722 continue; 2723 } 2724 2725 /* 2726 * Now we can compare to the address we were passed 2727 */ 2728 if (idm_ss_compare(p, &dportal_ss, 2729 B_TRUE /* v4_mapped_as_v4 */) == 0) { 2730 result = B_TRUE; 2731 goto lookup_default_portal_done; 2732 } 2733 } 2734 2735 lookup_default_portal_done: 2736 kmem_free(default_portal_list, default_portal_list_size); 2737 return (result); 2738 } 2739 2740 /* 2741 * These functions are called by iscsit proper when a portal comes online 2742 * or goes offline. 2743 */ 2744 2745 void 2746 iscsit_isns_portal_online(iscsit_portal_t *portal) 2747 { 2748 ISNS_GLOBAL_LOCK(); 2749 2750 if (portal->portal_default) { 2751 /* Portals should only be onlined once */ 2752 ASSERT(!default_portal_online); 2753 default_portal_online = B_TRUE; 2754 default_portal_state_change = B_TRUE; 2755 ISNS_GLOBAL_UNLOCK(); 2756 return; 2757 } 2758 2759 isnst_add_portal(portal); 2760 2761 ISNS_GLOBAL_UNLOCK(); 2762 } 2763 2764 void 2765 iscsit_isns_portal_offline(iscsit_portal_t *portal) 2766 { 2767 ISNS_GLOBAL_LOCK(); 2768 2769 if (portal->portal_default) { 2770 /* Portals should only be offlined once */ 2771 ASSERT(default_portal_online); 2772 default_portal_online = B_FALSE; 2773 default_portal_state_change = B_TRUE; 2774 ISNS_GLOBAL_UNLOCK(); 2775 return; 2776 } 2777 2778 isnst_remove_portal(portal); 2779 2780 ISNS_GLOBAL_UNLOCK(); 2781 } 2782