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