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