1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/cpuvar.h> 27 #include <sys/types.h> 28 #include <sys/conf.h> 29 #include <sys/file.h> 30 #include <sys/ddi.h> 31 #include <sys/sunddi.h> 32 #include <sys/modctl.h> 33 34 #include <sys/socket.h> 35 #include <sys/strsubr.h> 36 #include <sys/sysmacros.h> 37 #include <sys/note.h> 38 #include <sys/sdt.h> 39 40 #include <sys/stmf.h> 41 #include <sys/stmf_ioctl.h> 42 #include <sys/portif.h> 43 #include <sys/idm/idm.h> 44 #include <sys/idm/idm_text.h> 45 46 #define ISCSIT_LOGIN_SM_STRINGS 47 #include <iscsit.h> 48 #include <iscsit_auth.h> 49 50 typedef struct { 51 list_node_t le_ctx_node; 52 iscsit_login_event_t le_ctx_event; 53 idm_pdu_t *le_pdu; 54 } login_event_ctx_t; 55 56 #ifndef TRUE 57 #define TRUE B_TRUE 58 #endif 59 60 #ifndef FALSE 61 #define FALSE B_FALSE 62 #endif 63 64 #define DEFAULT_RADIUS_PORT 1812 65 66 static void 67 login_sm_complete(void *ict_void); 68 69 static void 70 login_sm_event_dispatch(iscsit_conn_login_t *lsm, iscsit_conn_t *ict, 71 login_event_ctx_t *ctx); 72 73 static void 74 login_sm_init(iscsit_conn_t *ict, login_event_ctx_t *ctx); 75 76 static void 77 login_sm_waiting(iscsit_conn_t *ict, login_event_ctx_t *ctx); 78 79 static void 80 login_sm_processing(iscsit_conn_t *ict, login_event_ctx_t *ctx); 81 82 static void 83 login_sm_responding(iscsit_conn_t *ict, login_event_ctx_t *ctx); 84 85 static void 86 login_sm_responded(iscsit_conn_t *ict, login_event_ctx_t *ctx); 87 88 static void 89 login_sm_ffp(iscsit_conn_t *ict, login_event_ctx_t *ctx); 90 91 static void 92 login_sm_done(iscsit_conn_t *ict, login_event_ctx_t *ctx); 93 94 static void 95 login_sm_error(iscsit_conn_t *ict, login_event_ctx_t *ctx); 96 97 static void 98 login_sm_new_state(iscsit_conn_t *ict, login_event_ctx_t *ctx, 99 iscsit_login_state_t new_state); 100 101 static void 102 login_sm_send_ack(iscsit_conn_t *ict, idm_pdu_t *pdu); 103 104 static idm_status_t 105 login_sm_validate_ack(iscsit_conn_t *ict, idm_pdu_t *pdu); 106 107 static boolean_t 108 login_sm_is_last_response(idm_pdu_t *pdu); 109 110 static void 111 login_sm_handle_initial_login(iscsit_conn_t *ict, idm_pdu_t *pdu); 112 113 static void 114 login_sm_send_next_response(iscsit_conn_t *ict, idm_pdu_t *pdu); 115 116 static void 117 login_sm_process_request(iscsit_conn_t *ict); 118 119 static idm_status_t 120 login_sm_req_pdu_check(iscsit_conn_t *ict, idm_pdu_t *pdu); 121 122 static idm_status_t 123 login_sm_process_nvlist(iscsit_conn_t *ict); 124 125 static idm_status_t 126 login_sm_check_security(iscsit_conn_t *ict); 127 128 static idm_pdu_t * 129 login_sm_build_login_response(iscsit_conn_t *ict); 130 131 static void 132 login_sm_ffp_actions(iscsit_conn_t *ict); 133 134 static idm_status_t 135 login_sm_validate_initial_parameters(iscsit_conn_t *ict); 136 137 static idm_status_t 138 login_sm_session_bind(iscsit_conn_t *ict); 139 140 static idm_status_t 141 login_sm_set_auth(iscsit_conn_t *ict); 142 143 static idm_status_t 144 login_sm_session_register(iscsit_conn_t *ict); 145 146 static kv_status_t 147 iscsit_handle_key(iscsit_conn_t *ict, nvpair_t *nvp, char *nvp_name); 148 149 static kv_status_t 150 iscsit_handle_common_key(iscsit_conn_t *ict, nvpair_t *nvp, 151 const idm_kv_xlate_t *ikvx); 152 153 static kv_status_t 154 iscsit_handle_security_key(iscsit_conn_t *ict, nvpair_t *nvp, 155 const idm_kv_xlate_t *ikvx); 156 157 static kv_status_t 158 iscsit_reply_security_key(iscsit_conn_t *ict); 159 160 static kv_status_t 161 iscsit_handle_operational_key(iscsit_conn_t *ict, nvpair_t *nvp, 162 const idm_kv_xlate_t *ikvx); 163 164 static kv_status_t 165 iscsit_reply_numerical(iscsit_conn_t *ict, 166 const char *nvp_name, const uint64_t value); 167 168 static kv_status_t 169 iscsit_reply_string(iscsit_conn_t *ict, 170 const char *nvp_name, const char *text); 171 172 static kv_status_t 173 iscsit_handle_digest(iscsit_conn_t *ict, nvpair_t *choices, 174 const idm_kv_xlate_t *ikvx); 175 176 static kv_status_t 177 iscsit_handle_boolean(iscsit_conn_t *ict, nvpair_t *nvp, boolean_t value, 178 const idm_kv_xlate_t *ikvx, boolean_t iscsit_value); 179 180 static kv_status_t 181 iscsit_handle_numerical(iscsit_conn_t *ict, nvpair_t *nvp, uint64_t value, 182 const idm_kv_xlate_t *ikvx, 183 uint64_t iscsi_min_value, uint64_t iscsi_max_value, 184 uint64_t iscsit_max_value); 185 186 static void 187 iscsit_process_negotiated_values(iscsit_conn_t *ict); 188 189 static void 190 login_resp_complete_cb(idm_pdu_t *pdu, idm_status_t status); 191 192 idm_status_t 193 iscsit_login_sm_init(iscsit_conn_t *ict) 194 { 195 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 196 197 bzero(lsm, sizeof (iscsit_conn_login_t)); 198 199 (void) nvlist_alloc(&lsm->icl_negotiated_values, NV_UNIQUE_NAME, 200 KM_SLEEP); 201 202 /* 203 * Hold connection until the login state machine completes 204 */ 205 iscsit_conn_hold(ict); 206 207 /* 208 * Pre-allocating a login response PDU means we will always be 209 * able to respond to a login request -- even if we can't allocate 210 * a data buffer to hold the text responses we can at least send 211 * a login failure. 212 */ 213 lsm->icl_login_resp_tmpl = kmem_zalloc(sizeof (iscsi_login_rsp_hdr_t), 214 KM_SLEEP); 215 216 idm_sm_audit_init(&lsm->icl_state_audit); 217 mutex_init(&lsm->icl_mutex, NULL, MUTEX_DEFAULT, NULL); 218 list_create(&lsm->icl_login_events, sizeof (login_event_ctx_t), 219 offsetof(login_event_ctx_t, le_ctx_node)); 220 list_create(&lsm->icl_pdu_list, sizeof (idm_pdu_t), 221 offsetof(idm_pdu_t, isp_client_lnd)); 222 223 lsm->icl_login_state = ILS_LOGIN_INIT; 224 lsm->icl_login_last_state = ILS_LOGIN_INIT; 225 226 /* 227 * Initialize operational parameters to default values. Anything 228 * we don't specifically negotiate stays at the default. 229 */ 230 ict->ict_op.op_discovery_session = B_FALSE; 231 ict->ict_op.op_initial_r2t = ISCSI_DEFAULT_INITIALR2T; 232 ict->ict_op.op_immed_data = ISCSI_DEFAULT_IMMEDIATE_DATA; 233 ict->ict_op.op_data_pdu_in_order = ISCSI_DEFAULT_DATA_PDU_IN_ORDER; 234 ict->ict_op.op_data_sequence_in_order = 235 ISCSI_DEFAULT_DATA_SEQUENCE_IN_ORDER; 236 ict->ict_op.op_max_connections = ISCSI_DEFAULT_MAX_CONNECTIONS; 237 ict->ict_op.op_max_recv_data_segment_length = 238 ISCSI_DEFAULT_MAX_RECV_SEG_LEN; 239 ict->ict_op.op_max_burst_length = ISCSI_DEFAULT_MAX_BURST_LENGTH; 240 ict->ict_op.op_first_burst_length = ISCSI_DEFAULT_FIRST_BURST_LENGTH; 241 ict->ict_op.op_default_time_2_wait = ISCSI_DEFAULT_TIME_TO_WAIT; 242 ict->ict_op.op_default_time_2_retain = ISCSI_DEFAULT_TIME_TO_RETAIN; 243 ict->ict_op.op_max_outstanding_r2t = ISCSI_DEFAULT_MAX_OUT_R2T; 244 ict->ict_op.op_error_recovery_level = 245 ISCSI_DEFAULT_ERROR_RECOVERY_LEVEL; 246 247 return (IDM_STATUS_SUCCESS); 248 } 249 250 static void 251 login_resp_complete_cb(idm_pdu_t *pdu, idm_status_t status) 252 { 253 iscsit_conn_t *ict = pdu->isp_private; 254 255 /* 256 * Check that this is a login pdu 257 */ 258 ASSERT((pdu->isp_flags & IDM_PDU_LOGIN_TX) != 0); 259 idm_pdu_free(pdu); 260 261 if ((status != IDM_STATUS_SUCCESS) || 262 (ict->ict_login_sm.icl_login_resp_err_class != 0)) { 263 /* 264 * Transport or login error occurred. 265 */ 266 iscsit_login_sm_event(ict, ILE_LOGIN_ERROR, NULL); 267 } 268 iscsit_conn_rele(ict); 269 } 270 271 void 272 iscsit_login_sm_fini(iscsit_conn_t *ict) 273 { 274 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 275 276 mutex_enter(&lsm->icl_mutex); 277 list_destroy(&lsm->icl_pdu_list); 278 list_destroy(&lsm->icl_login_events); 279 280 kmem_free(lsm->icl_login_resp_tmpl, sizeof (iscsi_login_rsp_hdr_t)); 281 282 /* clean up the login response idm text buffer */ 283 if (lsm->icl_login_resp_itb != NULL) { 284 idm_itextbuf_free(lsm->icl_login_resp_itb); 285 lsm->icl_login_resp_itb = NULL; 286 } 287 288 nvlist_free(lsm->icl_negotiated_values); 289 mutex_destroy(&lsm->icl_mutex); 290 } 291 292 void 293 iscsit_login_sm_event(iscsit_conn_t *ict, iscsit_login_event_t event, 294 idm_pdu_t *pdu) 295 { 296 /* 297 * This is a bit ugly but if we're already in ILS_LOGIN_ERROR 298 * or ILS_LOGIN_DONE then just drop any additional events. They 299 * won't change the state and it's possible we've already called 300 * iscsit_login_sm_fini in which case the mutex is destroyed. 301 */ 302 if ((ict->ict_login_sm.icl_login_state == ILS_LOGIN_ERROR) || 303 (ict->ict_login_sm.icl_login_state == ILS_LOGIN_DONE)) 304 return; 305 306 mutex_enter(&ict->ict_login_sm.icl_mutex); 307 iscsit_login_sm_event_locked(ict, event, pdu); 308 mutex_exit(&ict->ict_login_sm.icl_mutex); 309 } 310 void 311 iscsit_login_sm_event_locked(iscsit_conn_t *ict, iscsit_login_event_t event, 312 idm_pdu_t *pdu) 313 { 314 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 315 login_event_ctx_t *ctx; 316 317 ASSERT(mutex_owned(&lsm->icl_mutex)); 318 ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP); 319 320 ctx->le_ctx_event = event; 321 ctx->le_pdu = pdu; 322 323 list_insert_tail(&lsm->icl_login_events, ctx); 324 325 /* 326 * Use the icl_busy flag to keep the state machine single threaded. 327 * This also serves as recursion avoidance since this flag will 328 * always be set if we call login_sm_event from within the 329 * state machine code. 330 */ 331 if (!lsm->icl_busy) { 332 lsm->icl_busy = B_TRUE; 333 while (!list_is_empty(&lsm->icl_login_events)) { 334 ctx = list_head(&lsm->icl_login_events); 335 list_remove(&lsm->icl_login_events, ctx); 336 idm_sm_audit_event(&lsm->icl_state_audit, 337 SAS_ISCSIT_LOGIN, (int)lsm->icl_login_state, 338 (int)ctx->le_ctx_event, (uintptr_t)pdu); 339 340 /* 341 * If the lsm is in a terminal state, just drain 342 * any remaining events. 343 */ 344 if ((lsm->icl_login_state == ILS_LOGIN_ERROR) || 345 (lsm->icl_login_state == ILS_LOGIN_DONE)) { 346 kmem_free(ctx, sizeof (*ctx)); 347 continue; 348 } 349 mutex_exit(&lsm->icl_mutex); 350 login_sm_event_dispatch(lsm, ict, ctx); 351 mutex_enter(&lsm->icl_mutex); 352 } 353 lsm->icl_busy = B_FALSE; 354 355 /* 356 * When the state machine reaches ILS_LOGIN_DONE or 357 * ILS_LOGIN_ERROR state the login process has completed 358 * and it's time to cleanup. The state machine code will 359 * mark itself "complete" when this happens. 360 * 361 * To protect against spurious events (which shouldn't 362 * happen) set icl_busy again. 363 */ 364 if (lsm->icl_login_complete) { 365 lsm->icl_busy = B_TRUE; 366 if (taskq_dispatch(iscsit_global.global_dispatch_taskq, 367 login_sm_complete, ict, DDI_SLEEP) == NULL) { 368 cmn_err(CE_WARN, "iscsit_login_sm_event_locked:" 369 " Failed to dispatch task"); 370 } 371 } 372 } 373 } 374 375 static void 376 login_sm_complete(void *ict_void) 377 { 378 iscsit_conn_t *ict = ict_void; 379 380 /* 381 * State machine has run to completion, resources 382 * will be cleaned up when connection is destroyed. 383 */ 384 iscsit_conn_rele(ict); 385 } 386 387 static void 388 login_sm_event_dispatch(iscsit_conn_login_t *lsm, iscsit_conn_t *ict, 389 login_event_ctx_t *ctx) 390 { 391 idm_pdu_t *pdu = ctx->le_pdu; /* Only valid for some events */ 392 393 DTRACE_PROBE2(login__event, iscsit_conn_t *, ict, 394 login_event_ctx_t *, ctx); 395 396 IDM_SM_LOG(CE_NOTE, "login_sm_event_dispatch: ict %p event %s(%d)", 397 (void *)ict, 398 iscsit_ile_name[ctx->le_ctx_event], ctx->le_ctx_event); 399 400 /* State independent actions */ 401 switch (ctx->le_ctx_event) { 402 case ILE_LOGIN_RCV: 403 /* Perform basic sanity checks on the header */ 404 if (login_sm_req_pdu_check(ict, pdu) != IDM_STATUS_SUCCESS) { 405 idm_pdu_t *rpdu; 406 407 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR, 408 ISCSI_LOGIN_STATUS_INVALID_REQUEST); 409 /* 410 * If we haven't processed any PDU's yet then use 411 * this one as a template for the response 412 */ 413 if (ict->ict_login_sm.icl_login_resp_tmpl->opcode == 0) 414 login_sm_handle_initial_login(ict, pdu); 415 rpdu = login_sm_build_login_response(ict); 416 login_sm_send_next_response(ict, rpdu); 417 idm_pdu_complete(pdu, IDM_STATUS_SUCCESS); 418 kmem_free(ctx, sizeof (*ctx)); 419 return; 420 } 421 break; 422 default: 423 break; 424 } 425 426 /* State dependent actions */ 427 switch (lsm->icl_login_state) { 428 case ILS_LOGIN_INIT: 429 login_sm_init(ict, ctx); 430 break; 431 case ILS_LOGIN_WAITING: 432 login_sm_waiting(ict, ctx); 433 break; 434 case ILS_LOGIN_PROCESSING: 435 login_sm_processing(ict, ctx); 436 break; 437 case ILS_LOGIN_RESPONDING: 438 login_sm_responding(ict, ctx); 439 break; 440 case ILS_LOGIN_RESPONDED: 441 login_sm_responded(ict, ctx); 442 break; 443 case ILS_LOGIN_FFP: 444 login_sm_ffp(ict, ctx); 445 break; 446 case ILS_LOGIN_DONE: 447 login_sm_done(ict, ctx); 448 break; 449 case ILS_LOGIN_ERROR: 450 login_sm_error(ict, ctx); 451 break; 452 } 453 454 kmem_free(ctx, sizeof (*ctx)); 455 } 456 457 static void 458 login_sm_init(iscsit_conn_t *ict, login_event_ctx_t *ctx) 459 { 460 idm_pdu_t *pdu; 461 462 switch (ctx->le_ctx_event) { 463 case ILE_LOGIN_RCV: 464 pdu = ctx->le_pdu; 465 466 /* 467 * This is the first login PDU we've received so use 468 * it to build the login response template and set our CSG. 469 */ 470 login_sm_handle_initial_login(ict, pdu); 471 472 /* 473 * Accumulate all the login PDU's that make up this 474 * request on a queue. 475 */ 476 mutex_enter(&ict->ict_login_sm.icl_mutex); 477 list_insert_tail(&ict->ict_login_sm.icl_pdu_list, pdu); 478 mutex_exit(&ict->ict_login_sm.icl_mutex); 479 480 if (pdu->isp_hdr->flags & ISCSI_FLAG_LOGIN_CONTINUE) { 481 login_sm_send_ack(ict, pdu); 482 login_sm_new_state(ict, ctx, ILS_LOGIN_WAITING); 483 } else { 484 login_sm_new_state(ict, ctx, ILS_LOGIN_PROCESSING); 485 } 486 break; 487 case ILE_LOGIN_CONN_ERROR: 488 case ILE_LOGIN_ERROR: 489 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR); 490 break; 491 default: 492 ASSERT(0); 493 } 494 } 495 496 static void 497 login_sm_waiting(iscsit_conn_t *ict, login_event_ctx_t *ctx) 498 { 499 idm_pdu_t *pdu; 500 501 switch (ctx->le_ctx_event) { 502 case ILE_LOGIN_RCV: 503 pdu = ctx->le_pdu; 504 mutex_enter(&ict->ict_login_sm.icl_mutex); 505 list_insert_tail(&ict->ict_login_sm.icl_pdu_list, pdu); 506 mutex_exit(&ict->ict_login_sm.icl_mutex); 507 if (!(pdu->isp_hdr->flags & ISCSI_FLAG_LOGIN_CONTINUE)) { 508 login_sm_new_state(ict, ctx, ILS_LOGIN_PROCESSING); 509 } else { 510 login_sm_send_ack(ict, pdu); 511 } 512 break; 513 case ILE_LOGIN_ERROR: 514 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR); 515 break; 516 case ILE_LOGIN_RESP_COMPLETE: 517 break; 518 default: 519 ASSERT(0); 520 } 521 } 522 523 static void 524 login_sm_processing(iscsit_conn_t *ict, login_event_ctx_t *ctx) 525 { 526 switch (ctx->le_ctx_event) { 527 case ILE_LOGIN_RESP_READY: 528 login_sm_new_state(ict, ctx, ILS_LOGIN_RESPONDING); 529 break; 530 case ILE_LOGIN_RCV: 531 idm_pdu_complete(ctx->le_pdu, IDM_STATUS_SUCCESS); 532 /*FALLTHROUGH*/ 533 case ILE_LOGIN_CONN_ERROR: 534 case ILE_LOGIN_ERROR: 535 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR); 536 break; 537 default: 538 ASSERT(0); 539 } 540 } 541 542 static void 543 login_sm_responding(iscsit_conn_t *ict, login_event_ctx_t *ctx) 544 { 545 idm_pdu_t *pdu, *rpdu; 546 547 switch (ctx->le_ctx_event) { 548 case ILE_LOGIN_RCV: 549 pdu = ctx->le_pdu; 550 /* 551 * We should only be in "responding" state if we have not 552 * sent the last PDU of a multi-PDU login response sequence. 553 * In that case we expect this received PDU to be an 554 * acknowledgement from the initiator (login PDU with C 555 * bit cleared and no data). If it's the acknowledgement 556 * we are expecting then we send the next PDU in the login 557 * response sequence. Otherwise it's a protocol error and 558 * the login fails. 559 */ 560 if (login_sm_validate_ack(ict, pdu) == IDM_STATUS_SUCCESS) { 561 rpdu = login_sm_build_login_response(ict); 562 login_sm_send_next_response(ict, rpdu); 563 } else { 564 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR); 565 } 566 idm_pdu_complete(pdu, IDM_STATUS_SUCCESS); 567 break; 568 case ILE_LOGIN_FFP: 569 login_sm_new_state(ict, ctx, ILS_LOGIN_FFP); 570 break; 571 case ILE_LOGIN_RESP_COMPLETE: 572 login_sm_new_state(ict, ctx, ILS_LOGIN_RESPONDED); 573 break; 574 case ILE_LOGIN_CONN_ERROR: 575 case ILE_LOGIN_ERROR: 576 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR); 577 break; 578 default: 579 ASSERT(0); 580 } 581 } 582 583 static void 584 login_sm_responded(iscsit_conn_t *ict, login_event_ctx_t *ctx) 585 { 586 idm_pdu_t *pdu; 587 iscsi_login_hdr_t *lh; 588 589 switch (ctx->le_ctx_event) { 590 case ILE_LOGIN_RCV: 591 pdu = ctx->le_pdu; 592 lh = (iscsi_login_hdr_t *)pdu->isp_hdr; 593 /* 594 * Set the CSG, NSG and Transit bits based on the this PDU. 595 * The CSG already validated in login_sm_req_pdu_check(). 596 * We'll clear the transit bit if we encounter any login 597 * parameters in the request that required an additional 598 * login transfer (i.e. no acceptable 599 * choices in range or we needed to change a boolean 600 * value from "Yes" to "No"). 601 */ 602 ict->ict_login_sm.icl_login_csg = 603 ISCSI_LOGIN_CURRENT_STAGE(lh->flags); 604 ict->ict_login_sm.icl_login_nsg = 605 ISCSI_LOGIN_NEXT_STAGE(lh->flags); 606 ict->ict_login_sm.icl_login_transit = 607 lh->flags & ISCSI_FLAG_LOGIN_TRANSIT; 608 mutex_enter(&ict->ict_login_sm.icl_mutex); 609 list_insert_tail(&ict->ict_login_sm.icl_pdu_list, pdu); 610 mutex_exit(&ict->ict_login_sm.icl_mutex); 611 if (pdu->isp_hdr->flags & ISCSI_FLAG_LOGIN_CONTINUE) { 612 login_sm_send_ack(ict, pdu); 613 login_sm_new_state(ict, ctx, ILS_LOGIN_WAITING); 614 } else { 615 login_sm_new_state(ict, ctx, ILS_LOGIN_PROCESSING); 616 } 617 break; 618 case ILE_LOGIN_CONN_ERROR: 619 case ILE_LOGIN_ERROR: 620 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR); 621 break; 622 default: 623 ASSERT(0); 624 } 625 } 626 627 static void 628 login_sm_ffp(iscsit_conn_t *ict, login_event_ctx_t *ctx) 629 { 630 switch (ctx->le_ctx_event) { 631 case ILE_LOGIN_RESP_COMPLETE: 632 login_sm_new_state(ict, ctx, ILS_LOGIN_DONE); 633 break; 634 case ILE_LOGIN_CONN_ERROR: 635 case ILE_LOGIN_ERROR: 636 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR); 637 break; 638 default: 639 ASSERT(0); 640 } 641 642 } 643 644 /*ARGSUSED*/ 645 static void 646 login_sm_done(iscsit_conn_t *ict, login_event_ctx_t *ctx) 647 { 648 /* Terminal state, we should get no events */ 649 switch (ctx->le_ctx_event) { 650 case ILE_LOGIN_RCV: 651 /* 652 * We've already processed everything we're going to 653 * process. Drop any additional login PDU's. 654 */ 655 idm_pdu_complete(ctx->le_pdu, IDM_STATUS_SUCCESS); 656 break; 657 case ILE_LOGIN_CONN_ERROR: 658 /* Don't care */ 659 break; 660 default: 661 ASSERT(0); 662 } 663 } 664 665 /*ARGSUSED*/ 666 static void 667 login_sm_error(iscsit_conn_t *ict, login_event_ctx_t *ctx) 668 { 669 switch (ctx->le_ctx_event) { 670 case ILE_LOGIN_RCV: 671 /* 672 * We've already processed everything we're going to 673 * process. Drop any additional login PDU's. 674 */ 675 idm_pdu_complete(ctx->le_pdu, IDM_STATUS_SUCCESS); 676 break; 677 case ILE_LOGIN_CONN_ERROR: 678 /* Don't care */ 679 break; 680 default: 681 ASSERT(0); 682 } 683 } 684 685 static void 686 login_sm_new_state(iscsit_conn_t *ict, login_event_ctx_t *ctx, 687 iscsit_login_state_t new_state) 688 { 689 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 690 idm_pdu_t *rpdu; 691 692 /* 693 * Validate new state 694 */ 695 ASSERT(new_state != ILS_UNDEFINED); 696 ASSERT3U(new_state, <, ILS_MAX_STATE); 697 698 new_state = (new_state < ILS_MAX_STATE) ? 699 new_state : ILS_UNDEFINED; 700 701 IDM_SM_LOG(CE_NOTE, "login_sm_new_state: conn %p " 702 "%s (%d) --> %s (%d)\n", (void *)ict->ict_ic, 703 iscsit_ils_name[lsm->icl_login_state], lsm->icl_login_state, 704 iscsit_ils_name[new_state], new_state); 705 706 DTRACE_PROBE3(login__state__change, 707 iscsit_conn_t *, ict, login_event_ctx_t *, ctx, 708 iscsit_login_state_t, new_state); 709 710 mutex_enter(&lsm->icl_mutex); 711 idm_sm_audit_state_change(&lsm->icl_state_audit, SAS_ISCSIT_LOGIN, 712 (int)lsm->icl_login_state, (int)new_state); 713 lsm->icl_login_last_state = lsm->icl_login_state; 714 lsm->icl_login_state = new_state; 715 mutex_exit(&lsm->icl_mutex); 716 717 switch (lsm->icl_login_state) { 718 case ILS_LOGIN_WAITING: 719 /* Do nothing, waiting for more login PDU's */ 720 break; 721 case ILS_LOGIN_PROCESSING: 722 /* All login PDU's received, process login request */ 723 login_sm_process_request(ict); 724 break; 725 case ILS_LOGIN_RESPONDING: 726 rpdu = login_sm_build_login_response(ict); 727 login_sm_send_next_response(ict, rpdu); 728 break; 729 case ILS_LOGIN_RESPONDED: 730 /* clean up the login response idm text buffer */ 731 if (lsm->icl_login_resp_itb != NULL) { 732 idm_itextbuf_free(lsm->icl_login_resp_itb); 733 lsm->icl_login_resp_itb = NULL; 734 } 735 break; 736 case ILS_LOGIN_FFP: 737 login_sm_ffp_actions(ict); 738 break; 739 case ILS_LOGIN_DONE: 740 case ILS_LOGIN_ERROR: 741 /* 742 * Flag the terminal state for the dispatcher 743 */ 744 lsm->icl_login_complete = B_TRUE; 745 break; 746 case ILS_LOGIN_INIT: /* Initial state, can't return */ 747 default: 748 ASSERT(0); 749 /*NOTREACHED*/ 750 } 751 } 752 753 /*ARGSUSED*/ 754 static void 755 login_sm_send_ack(iscsit_conn_t *ict, idm_pdu_t *pdu) 756 { 757 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 758 idm_pdu_t *lack; 759 760 /* 761 * allocate the response pdu 762 */ 763 lack = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0); 764 idm_pdu_init(lack, ict->ict_ic, ict, login_resp_complete_cb); 765 lack->isp_flags |= IDM_PDU_LOGIN_TX; 766 767 /* 768 * copy the response template into the response pdu 769 */ 770 bcopy(lsm->icl_login_resp_tmpl, lack->isp_hdr, sizeof (iscsi_hdr_t)); 771 772 iscsit_conn_hold(ict); 773 idm_pdu_tx(lack); 774 } 775 776 /*ARGSUSED*/ 777 static idm_status_t 778 login_sm_validate_ack(iscsit_conn_t *ict, idm_pdu_t *pdu) 779 { 780 iscsi_hdr_t *ihp = pdu->isp_hdr; 781 if (ihp->flags & ISCSI_FLAG_TEXT_CONTINUE) { 782 return (IDM_STATUS_FAIL); 783 } 784 if (ntoh24(ihp->dlength) != 0) { 785 return (IDM_STATUS_FAIL); 786 } 787 return (IDM_STATUS_SUCCESS); 788 } 789 790 static boolean_t 791 login_sm_is_last_response(idm_pdu_t *pdu) 792 { 793 794 if (pdu->isp_hdr->flags & ISCSI_FLAG_LOGIN_CONTINUE) { 795 return (B_FALSE); 796 } 797 return (B_TRUE); 798 } 799 800 801 static void 802 login_sm_handle_initial_login(iscsit_conn_t *ict, idm_pdu_t *pdu) 803 { 804 iscsi_login_hdr_t *lh_req = (iscsi_login_hdr_t *)pdu->isp_hdr; 805 iscsi_login_rsp_hdr_t *lh_resp = 806 ict->ict_login_sm.icl_login_resp_tmpl; 807 808 /* 809 * First login PDU, this connection should not have a sesssion 810 * associated. 811 */ 812 ASSERT(ict->ict_sess == NULL); 813 814 /* 815 * Save off TSIH and ISID for later use in finding a session 816 */ 817 ict->ict_login_sm.icl_cmdsn = ntohl(lh_req->cmdsn); 818 ict->ict_login_sm.icl_tsih = ntohs(lh_req->tsid); 819 bcopy(lh_req->isid, ict->ict_login_sm.icl_isid, ISCSI_ISID_LEN); 820 821 /* 822 * We'll need the CID as well 823 */ 824 ict->ict_cid = ntohs(lh_req->cid); 825 826 /* 827 * Set the CSG, NSG and Transit bits based on the first PDU 828 * in the login sequence. The CSG already validated in 829 * login_sm_req_pdu_check(). We'll clear the transit bit if 830 * we encounter any login parameters in the request that 831 * required an additional login transfer (i.e. no acceptable 832 * choices in range or we needed to change a boolean 833 * value from "Yes" to "No"). 834 */ 835 ict->ict_login_sm.icl_login_csg = 836 ISCSI_LOGIN_CURRENT_STAGE(lh_req->flags); 837 ict->ict_login_sm.icl_login_nsg = 838 ISCSI_LOGIN_NEXT_STAGE(lh_req->flags); 839 ict->ict_login_sm.icl_login_transit = 840 lh_req->flags & ISCSI_FLAG_LOGIN_TRANSIT; 841 842 /* 843 * Initialize header for login reject response. This will also 844 * be copied for use as a template for other login responses 845 */ 846 lh_resp->opcode = ISCSI_OP_LOGIN_RSP; 847 lh_resp->max_version = ISCSIT_MAX_VERSION; 848 849 /* 850 * We already validated that we can support one of the initiator's 851 * versions in login_sm_req_pdu_check(). 852 */ 853 #if (ISCSIT_MAX_VERSION > 0) 854 if (ISCSIT_MAX_VERSION >= lh_req->min_version) { 855 lh_resp->active_version = 856 MIN(lh_req->max_version, ISCSIT_MAX_VERSION); 857 } else { 858 ASSERT(ISCSIT_MAX_VERSION <= lh_req->max_version); 859 lh_resp->active_version = ISCSIT_MAX_VERSION; 860 } 861 #endif 862 863 lh_resp->hlength = 0; /* No AHS */ 864 bcopy(lh_req->isid, lh_resp->isid, ISCSI_ISID_LEN); 865 lh_resp->tsid = lh_req->tsid; 866 lh_resp->itt = lh_req->itt; 867 868 /* 869 * StatSn, ExpCmdSn and MaxCmdSn will be set immediately before 870 * transmission 871 */ 872 } 873 874 static void 875 login_sm_send_next_response(iscsit_conn_t *ict, idm_pdu_t *pdu) 876 { 877 iscsi_login_rsp_hdr_t *lh_resp = (iscsi_login_rsp_hdr_t *)pdu->isp_hdr; 878 879 /* Make sure this PDU is part of the login phase */ 880 ASSERT((pdu->isp_flags & IDM_PDU_LOGIN_TX) != 0); 881 882 /* 883 * Fill in header values 884 */ 885 hton24(lh_resp->dlength, pdu->isp_datalen); 886 887 /* 888 * If this is going to be the last PDU of a login response 889 * that moves us to FFP then generate the ILE_LOGIN_FFP event. 890 */ 891 if (lh_resp->status_class == ISCSI_STATUS_CLASS_SUCCESS) { 892 ASSERT(ict->ict_sess != NULL); 893 894 if ((lh_resp->flags & ISCSI_FLAG_LOGIN_TRANSIT) && 895 (ISCSI_LOGIN_NEXT_STAGE(lh_resp->flags) == 896 ISCSI_FULL_FEATURE_PHASE) && 897 !(lh_resp->flags & ISCSI_FLAG_LOGIN_CONTINUE)) { 898 iscsit_login_sm_event(ict, ILE_LOGIN_FFP, NULL); 899 } 900 if (login_sm_is_last_response(pdu) == B_TRUE) { 901 /* 902 * The last of a potentially mult-PDU response finished. 903 */ 904 iscsit_login_sm_event(ict, ILE_LOGIN_RESP_COMPLETE, 905 NULL); 906 } 907 908 iscsit_conn_hold(ict); 909 iscsit_pdu_tx(pdu); 910 } else { 911 /* 912 * If status_class != ISCSI_STATUS_CLASS_SUCCESS then 913 * StatSN is not valid and we can call idm_pdu_tx instead 914 * of iscsit_pdu_tx. This is very good thing since in 915 * some cases of login failure we may not have a session. 916 * Since iscsit_calc_rspsn grabs the session mutex while 917 * it is retrieving values for expcmdsn and maxcmdsn this 918 * would cause a panic. 919 * 920 * Since we still want a value for expcmdsn, fill in an 921 * appropriate value based on the login request before 922 * sending the response. Cmdsn/expcmdsn do not advance during 923 * login phase. 924 */ 925 lh_resp->expcmdsn = htonl(ict->ict_login_sm.icl_cmdsn); 926 lh_resp->maxcmdsn = htonl(ict->ict_login_sm.icl_cmdsn + 1); 927 928 iscsit_conn_hold(ict); 929 idm_pdu_tx(pdu); 930 } 931 932 } 933 934 static void 935 login_sm_process_request(iscsit_conn_t *ict) 936 { 937 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 938 uint8_t error_class = 0; 939 uint8_t error_detail = 0; 940 941 /* 942 * First walk all the PDU's that make up this login request 943 * and compile all the iSCSI key-value pairs into nvlist format. 944 */ 945 946 ASSERT(lsm->icl_request_nvlist == NULL); 947 /* create an nvlist for request key/value pairs */ 948 if (idm_pdu_list_to_nvlist(&lsm->icl_pdu_list, 949 &lsm->icl_request_nvlist, &error_detail) != IDM_STATUS_SUCCESS) { 950 error_class = ISCSI_STATUS_CLASS_TARGET_ERR; 951 SET_LOGIN_ERROR(ict, error_class, error_detail); 952 goto request_fail; 953 } 954 955 /* Allocate a new nvlist for response key/value pairs */ 956 ASSERT(lsm->icl_response_nvlist == NULL); 957 if (nvlist_alloc(&lsm->icl_response_nvlist, NV_UNIQUE_NAME, 958 KM_NOSLEEP) != 0) { 959 error_class = ISCSI_STATUS_CLASS_TARGET_ERR; 960 error_detail = ISCSI_LOGIN_STATUS_NO_RESOURCES; 961 SET_LOGIN_ERROR(ict, error_class, error_detail); 962 goto request_fail; 963 } 964 965 /* 966 * This would be a very good time to make sure we have 967 * negotiated the required values for the login phase. For 968 * example we definitely should have defined InitiatorName, 969 * and Target name regardless of our current login phase. 970 */ 971 if (!ict->ict_op.op_initial_params_set) { 972 if (login_sm_validate_initial_parameters(ict) != 973 IDM_STATUS_SUCCESS) { 974 goto request_fail; 975 } 976 977 /* 978 * Now setup our session association. This includes 979 * create a new session or looking up an existing session, 980 * and if this is not a discovery session then we will 981 * also register this session with STMF. 982 */ 983 if (login_sm_session_bind(ict) != IDM_STATUS_SUCCESS) { 984 goto request_fail; 985 } 986 987 if (login_sm_set_auth(ict) != IDM_STATUS_SUCCESS) { 988 goto request_fail; 989 } 990 991 /* 992 * Prepend TargetAlias and PortalGroupTag 993 */ 994 if (ict->ict_op.op_discovery_session == B_FALSE) { 995 if ((lsm->icl_auth.ca_tgt_alias[0]) != '\0') { 996 (void) iscsit_reply_string(ict, 997 "TargetAlias", 998 &lsm->icl_auth.ca_tgt_alias[0]); 999 } 1000 (void) iscsit_reply_numerical(ict, 1001 "TargetPortalGroupTag", 1002 (uint64_t)lsm->icl_tpgt_tag); 1003 } 1004 1005 ict->ict_op.op_initial_params_set = B_TRUE; 1006 } 1007 1008 if (login_sm_process_nvlist(ict) != IDM_STATUS_SUCCESS) { 1009 goto request_fail; 1010 } 1011 1012 if (login_sm_check_security(ict) != IDM_STATUS_SUCCESS) { 1013 goto request_fail; 1014 } 1015 1016 /* clean up request_nvlist */ 1017 if (lsm->icl_request_nvlist != NULL) { 1018 nvlist_free(lsm->icl_request_nvlist); 1019 lsm->icl_request_nvlist = NULL; 1020 } 1021 1022 /* convert any responses to textbuf form */ 1023 ASSERT(lsm->icl_login_resp_itb == NULL); 1024 if (lsm->icl_response_nvlist) { 1025 lsm->icl_login_resp_itb = idm_nvlist_to_itextbuf( 1026 lsm->icl_response_nvlist); 1027 if (lsm->icl_login_resp_itb == NULL) { 1028 /* Still need to send the resp so continue */ 1029 SET_LOGIN_ERROR(ict, 1030 ISCSI_STATUS_CLASS_TARGET_ERR, 1031 ISCSI_LOGIN_STATUS_NO_RESOURCES); 1032 } 1033 /* clean up response_nvlist */ 1034 nvlist_free(lsm->icl_response_nvlist); 1035 lsm->icl_response_nvlist = NULL; 1036 } 1037 1038 /* tell the state machine to send the textbuf */ 1039 iscsit_login_sm_event(ict, ILE_LOGIN_RESP_READY, NULL); 1040 return; 1041 1042 request_fail: 1043 1044 /* clean up request_nvlist and response_nvlist */ 1045 if (lsm->icl_request_nvlist != NULL) { 1046 nvlist_free(lsm->icl_request_nvlist); 1047 lsm->icl_request_nvlist = NULL; 1048 } 1049 if (lsm->icl_response_nvlist != NULL) { 1050 nvlist_free(lsm->icl_response_nvlist); 1051 lsm->icl_response_nvlist = NULL; 1052 } 1053 } 1054 1055 1056 static void 1057 login_sm_ffp_actions(iscsit_conn_t *ict) 1058 { 1059 iscsit_process_negotiated_values(ict); 1060 } 1061 1062 static idm_status_t 1063 login_sm_validate_initial_parameters(iscsit_conn_t *ict) 1064 { 1065 int nvrc; 1066 char *string_val; 1067 uint8_t error_class = ISCSI_STATUS_CLASS_INITIATOR_ERR; 1068 uint8_t error_detail = ISCSI_LOGIN_STATUS_MISSING_FIELDS; 1069 idm_status_t status = IDM_STATUS_FAIL; 1070 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 1071 1072 /* 1073 * Make sure we received the required information from the initial 1074 * login. Add these declaratives to the negotiated list and 1075 * remove them from the request list as we go. If anything fails, 1076 * the caller will clean-up the nvlists. 1077 */ 1078 1079 /* 1080 * Initiator name 1081 */ 1082 if ((nvrc = nvlist_lookup_string(lsm->icl_request_nvlist, 1083 "InitiatorName", &string_val)) != 0) { 1084 goto initial_params_done; 1085 } 1086 if ((nvrc = nvlist_add_string(lsm->icl_negotiated_values, 1087 "InitiatorName", string_val)) != 0) { 1088 goto initial_params_done; 1089 } 1090 if ((nvrc = nvlist_lookup_string(lsm->icl_negotiated_values, 1091 "InitiatorName", &string_val)) != 0) { 1092 goto initial_params_done; 1093 } 1094 lsm->icl_initiator_name = string_val; 1095 idm_conn_set_initiator_name(ict->ict_ic, lsm->icl_initiator_name); 1096 if ((nvrc = nvlist_remove(lsm->icl_request_nvlist, 1097 "InitiatorName", DATA_TYPE_STRING)) != 0) { 1098 goto initial_params_done; 1099 } 1100 1101 /* 1102 * Session type 1103 */ 1104 ict->ict_op.op_discovery_session = B_FALSE; 1105 nvrc = nvlist_lookup_string(lsm->icl_request_nvlist, 1106 "SessionType", &string_val); 1107 if (nvrc != ENOENT && nvrc != 0) { 1108 goto initial_params_done; 1109 } 1110 if (nvrc == 0) { 1111 if (strcmp(string_val, "Discovery") == 0) { 1112 ict->ict_op.op_discovery_session = B_TRUE; 1113 } else if (strcmp(string_val, "Normal") != 0) { 1114 goto initial_params_done; 1115 } 1116 if ((nvrc = nvlist_add_string(lsm->icl_negotiated_values, 1117 "SessionType", string_val)) != 0) { 1118 goto initial_params_done; 1119 } 1120 if ((nvrc = nvlist_remove(lsm->icl_request_nvlist, 1121 "SessionType", DATA_TYPE_STRING)) != 0) { 1122 goto initial_params_done; 1123 } 1124 } 1125 1126 /* 1127 * Must have either TargetName or SessionType==Discovery 1128 */ 1129 lsm->icl_target_name = NULL; 1130 nvrc = nvlist_lookup_string(lsm->icl_request_nvlist, 1131 "TargetName", &string_val); 1132 if (nvrc != ENOENT && nvrc != 0) { 1133 goto initial_params_done; 1134 } 1135 if (nvrc == 0) { 1136 if ((nvrc = nvlist_add_string(lsm->icl_negotiated_values, 1137 "TargetName", string_val)) != 0) { 1138 goto initial_params_done; 1139 } 1140 if ((nvrc = nvlist_lookup_string(lsm->icl_negotiated_values, 1141 "TargetName", &string_val)) != 0) { 1142 goto initial_params_done; 1143 } 1144 lsm->icl_target_name = string_val; 1145 idm_conn_set_target_name(ict->ict_ic, lsm->icl_target_name); 1146 if ((nvrc = nvlist_remove(lsm->icl_request_nvlist, 1147 "TargetName", DATA_TYPE_STRING)) != 0) { 1148 goto initial_params_done; 1149 } 1150 } else if (ict->ict_op.op_discovery_session == B_FALSE) { 1151 /* 1152 * Missing target name 1153 */ 1154 goto initial_params_done; 1155 } 1156 1157 idm_conn_set_isid(ict->ict_ic, lsm->icl_isid); 1158 (void) snprintf(ict->ict_ic->ic_tsih, ISCSI_MAX_TSIH_LEN + 1, "0x%04x", 1159 lsm->icl_tsih); 1160 1161 IDM_SM_LOG(CE_NOTE, "conn %p: initiator=%s", (void *)ict->ict_ic, 1162 (lsm->icl_initiator_name == NULL) ? "N/A" : 1163 lsm->icl_initiator_name); 1164 IDM_SM_LOG(CE_NOTE, "conn %p: target=%s", (void *)ict->ict_ic, 1165 (lsm->icl_target_name == NULL) ? "N/A" : 1166 lsm->icl_target_name); 1167 IDM_SM_LOG(CE_NOTE, "conn %p: sessiontype=%s", (void *)ict->ict_ic, 1168 ict->ict_op.op_discovery_session ? "Discovery" : "Normal"); 1169 1170 /* Sucess */ 1171 status = IDM_STATUS_SUCCESS; 1172 error_class = ISCSI_STATUS_CLASS_SUCCESS; 1173 error_detail = ISCSI_LOGIN_STATUS_ACCEPT; 1174 1175 initial_params_done: 1176 SET_LOGIN_ERROR(ict, error_class, error_detail); 1177 return (status); 1178 } 1179 1180 1181 /* 1182 * login_sm_session_bind 1183 * 1184 * This function looks at the data from the initial login request 1185 * of a new connection and either looks up and existing session, 1186 * creates a new session, or returns an error. RFC3720 section 5.3.1 1187 * defines these rules: 1188 * 1189 * +------------------------------------------------------------------+ 1190 * |ISID | TSIH | CID | Target action | 1191 * +------------------------------------------------------------------+ 1192 * |new | non-zero | any | fail the login | 1193 * | | | | ("session does not exist") | 1194 * +------------------------------------------------------------------+ 1195 * |new | zero | any | instantiate a new session | 1196 * +------------------------------------------------------------------+ 1197 * |existing | zero | any | do session reinstatement | 1198 * | | | | (see section 5.3.5) | 1199 * +------------------------------------------------------------------+ 1200 * |existing | non-zero | new | add a new connection to | 1201 * | | existing | | the session | 1202 * +------------------------------------------------------------------+ 1203 * |existing | non-zero |existing| do connection reinstatement| 1204 * | | existing | | (see section 5.3.4) | 1205 * +------------------------------------------------------------------+ 1206 * |existing | non-zero | any | fail the login | 1207 * | | new | | ("session does not exist") | 1208 * +------------------------------------------------------------------+ 1209 * 1210 */ 1211 1212 /* 1213 * Map an <ipv6,port> address to an <ipv4,port> address if possible. 1214 * Returns: 1215 * 1 - success 1216 * 0 - address not mapable 1217 */ 1218 1219 static int 1220 iscsit_is_v4_mapped(struct sockaddr_storage *sa, struct sockaddr_storage *v4sa) 1221 { 1222 struct sockaddr_in *sin; 1223 struct in_addr *in; 1224 struct sockaddr_in6 *sin6; 1225 struct in6_addr *in6; 1226 int ret = 0; 1227 1228 sin6 = (struct sockaddr_in6 *)sa; 1229 in6 = &sin6->sin6_addr; 1230 if ((sa->ss_family == AF_INET6) && 1231 (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6))) { 1232 sin = (struct sockaddr_in *)v4sa; 1233 in = &sin->sin_addr; 1234 v4sa->ss_family = AF_INET; 1235 sin->sin_port = sin6->sin6_port; 1236 IN6_V4MAPPED_TO_INADDR(in6, in); 1237 ret = 1; 1238 } 1239 return (ret); 1240 } 1241 1242 static idm_status_t 1243 login_sm_session_bind(iscsit_conn_t *ict) 1244 { 1245 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 1246 iscsit_tgt_t *tgt = NULL; 1247 iscsit_tpgt_t *tpgt = NULL; 1248 iscsit_portal_t *portal = NULL; 1249 iscsit_sess_t *existing_sess = NULL; 1250 iscsit_sess_t *new_sess = NULL; 1251 iscsit_conn_t *existing_ict = NULL; 1252 uint8_t error_class; 1253 uint8_t error_detail; 1254 1255 /* 1256 * Look up target and then check if there are sessions or connections 1257 * that match this request (see below). Any holds taken on objects 1258 * must be released at the end of the function (let's keep things 1259 * simple). 1260 * 1261 * If target name is set then we should have a corresponding target 1262 * context configured. 1263 */ 1264 if (lsm->icl_target_name != NULL) { 1265 /* 1266 * iscsit_tgt_lookup implicitly takes a ref on the target 1267 */ 1268 ISCSIT_GLOBAL_LOCK(RW_READER); 1269 tgt = iscsit_tgt_lookup_locked(lsm->icl_target_name); 1270 if (tgt == NULL) { 1271 ISCSIT_GLOBAL_UNLOCK(); 1272 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR, 1273 ISCSI_LOGIN_STATUS_TGT_NOT_FOUND); 1274 goto session_bind_error; 1275 } else { 1276 mutex_enter(&tgt->target_mutex); 1277 tpgt = avl_first(&tgt->target_tpgt_list); 1278 1279 if (IS_DEFAULT_TPGT(tpgt)) { 1280 lsm->icl_tpgt_tag = ISCSIT_DEFAULT_TPGT; 1281 } else { 1282 /* 1283 * Find the portal group tag for the 1284 * login response. 1285 */ 1286 struct sockaddr_storage v4sa, *sa; 1287 1288 sa = &ict->ict_ic->ic_laddr; 1289 portal = iscsit_tgt_lookup_portal(tgt, 1290 sa, &tpgt); 1291 if (portal == NULL && 1292 iscsit_is_v4_mapped(sa, &v4sa)) { 1293 /* 1294 * Try again if the local address 1295 * was v6 mappable to v4. 1296 */ 1297 portal = iscsit_tgt_lookup_portal(tgt, 1298 &v4sa, &tpgt); 1299 1300 } 1301 if (portal == NULL) { 1302 /* 1303 * Initiator came in on wrong address 1304 */ 1305 SET_LOGIN_ERROR(ict, 1306 ISCSI_STATUS_CLASS_INITIATOR_ERR, 1307 ISCSI_LOGIN_STATUS_TGT_NOT_FOUND); 1308 mutex_exit(&tgt->target_mutex); 1309 ISCSIT_GLOBAL_UNLOCK(); 1310 goto session_bind_error; 1311 } 1312 1313 /* 1314 * Need to release holds on the portal and 1315 * tpgt after processing is complete. 1316 */ 1317 lsm->icl_tpgt_tag = tpgt->tpgt_tag; 1318 iscsit_portal_rele(portal); 1319 iscsit_tpgt_rele(tpgt); 1320 } 1321 1322 if ((tgt->target_state != TS_STMF_ONLINE) || 1323 ((iscsit_global.global_svc_state != ISE_ENABLED) && 1324 ((iscsit_global.global_svc_state != ISE_BUSY)))) { 1325 SET_LOGIN_ERROR(ict, 1326 ISCSI_STATUS_CLASS_TARGET_ERR, 1327 ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); 1328 mutex_exit(&tgt->target_mutex); 1329 ISCSIT_GLOBAL_UNLOCK(); 1330 goto session_bind_error; 1331 } 1332 mutex_exit(&tgt->target_mutex); 1333 ISCSIT_GLOBAL_UNLOCK(); 1334 } 1335 } 1336 1337 ASSERT((tgt != NULL) || (ict->ict_op.op_discovery_session == B_TRUE)); 1338 1339 /* 1340 * Check if there is an existing session matching this ISID. If 1341 * tgt == NULL then we'll look for the session on the global list 1342 * of discovery session. If we find a session then the ISID 1343 * exists. 1344 */ 1345 existing_sess = iscsit_tgt_lookup_sess(tgt, lsm->icl_initiator_name, 1346 lsm->icl_isid, lsm->icl_tsih, lsm->icl_tpgt_tag); 1347 if (existing_sess != NULL) { 1348 existing_ict = iscsit_sess_lookup_conn(existing_sess, 1349 ict->ict_cid); 1350 } 1351 1352 /* 1353 * If this is a discovery session, make sure it has appropriate 1354 * parameters. 1355 */ 1356 if ((ict->ict_op.op_discovery_session == B_TRUE) && 1357 ((lsm->icl_tsih != ISCSI_UNSPEC_TSIH) || (existing_sess != NULL))) { 1358 /* XXX Do we need to check for existing ISID (sess != NULL)? */ 1359 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR, 1360 ISCSI_LOGIN_STATUS_INVALID_REQUEST); 1361 goto session_bind_error; 1362 } 1363 1364 /* 1365 * Check the two error conditions from the table. 1366 * 1367 * ISID=new, TSIH=non-zero 1368 */ 1369 if ((existing_sess == NULL) && (lsm->icl_tsih != ISCSI_UNSPEC_TSIH)) { 1370 /* fail the login */ 1371 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR, 1372 ISCSI_LOGIN_STATUS_NO_SESSION); 1373 goto session_bind_error; 1374 } 1375 1376 /* ISID=existing, TSIH=non-zero new */ 1377 if ((existing_sess != NULL) && (lsm->icl_tsih != 0) && 1378 (existing_sess->ist_tsih != lsm->icl_tsih)) { 1379 /* fail the login */ 1380 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR, 1381 ISCSI_LOGIN_STATUS_NO_SESSION); 1382 goto session_bind_error; 1383 } 1384 1385 /* 1386 * Handle the remaining table cases in order 1387 */ 1388 if (existing_sess == NULL) { 1389 /* Should have caught this above */ 1390 ASSERT(lsm->icl_tsih == ISCSI_UNSPEC_TSIH); 1391 /* 1392 * ISID=new, TSIH=zero --> instantiate a new session 1393 */ 1394 new_sess = iscsit_sess_create(tgt, ict, lsm->icl_cmdsn, 1395 lsm->icl_isid, lsm->icl_tpgt_tag, lsm->icl_initiator_name, 1396 lsm->icl_target_name, &error_class, &error_detail); 1397 ASSERT(new_sess != NULL); 1398 1399 /* Session create may have failed even if it returned a value */ 1400 if (error_class != ISCSI_STATUS_CLASS_SUCCESS) { 1401 SET_LOGIN_ERROR(ict, error_class, error_detail); 1402 goto session_bind_error; 1403 } 1404 1405 /* 1406 * If we don't already have an STMF session and this is not 1407 * a discovery session then we need to allocate and register 1408 * one. 1409 */ 1410 if (!ict->ict_op.op_discovery_session) { 1411 if (login_sm_session_register(ict) != 1412 IDM_STATUS_SUCCESS) { 1413 /* login_sm_session_register sets error codes */ 1414 goto session_bind_error; 1415 } 1416 } 1417 1418 } else { 1419 if (lsm->icl_tsih == ISCSI_UNSPEC_TSIH) { 1420 /* 1421 * ISID=existing, TSIH=zero --> Session reinstatement 1422 */ 1423 new_sess = iscsit_sess_reinstate(tgt, existing_sess, 1424 ict, &error_class, &error_detail); 1425 ASSERT(new_sess != NULL); 1426 1427 if (error_class != ISCSI_STATUS_CLASS_SUCCESS) { 1428 SET_LOGIN_ERROR(ict, error_class, error_detail); 1429 goto session_bind_error; 1430 } 1431 1432 /* 1433 * If we don't already have an STMF session and this is 1434 * not a discovery session then we need to allocate and 1435 * register one. 1436 */ 1437 if (!ict->ict_op.op_discovery_session) { 1438 if (login_sm_session_register(ict) != 1439 IDM_STATUS_SUCCESS) { 1440 /* 1441 * login_sm_session_register sets 1442 * error codes 1443 */ 1444 goto session_bind_error; 1445 } 1446 } 1447 } else { 1448 /* 1449 * The following code covers these two cases: 1450 * ISID=existing, TSIH=non-zero existing, CID=new 1451 * --> add new connection to MC/S session 1452 * ISID=existing, TSIH=non-zero existing, CID=existing 1453 * --> do connection reinstatement 1454 * 1455 * Session continuation uses this path as well 1456 */ 1457 cmn_err(CE_NOTE, "login_sm_session_bind: add new " 1458 "conn/sess continue"); 1459 if (existing_ict != NULL) { 1460 /* 1461 * ISID=existing, TSIH=non-zero existing, 1462 * CID=existing --> do connection reinstatement 1463 */ 1464 if (iscsit_conn_reinstate(existing_ict, ict) != 1465 IDM_STATUS_SUCCESS) { 1466 /* 1467 * Most likely this means the connection 1468 * the initiator is trying to reinstate 1469 * is not in an acceptable state. 1470 */ 1471 SET_LOGIN_ERROR(ict, 1472 ISCSI_STATUS_CLASS_INITIATOR_ERR, 1473 ISCSI_LOGIN_STATUS_INIT_ERR); 1474 goto session_bind_error; 1475 } 1476 } 1477 1478 iscsit_sess_sm_event(existing_sess, SE_CONN_IN_LOGIN, 1479 ict); 1480 } 1481 } 1482 1483 if (tgt != NULL) 1484 iscsit_tgt_rele(tgt); 1485 if (existing_sess != NULL) 1486 iscsit_sess_rele(existing_sess); 1487 if (existing_ict != NULL) 1488 iscsit_conn_rele(existing_ict); 1489 1490 return (IDM_STATUS_SUCCESS); 1491 1492 session_bind_error: 1493 if (tgt != NULL) 1494 iscsit_tgt_rele(tgt); 1495 if (existing_sess != NULL) 1496 iscsit_sess_rele(existing_sess); 1497 if (existing_ict != NULL) 1498 iscsit_conn_rele(existing_ict); 1499 1500 /* 1501 * If session bind fails we will fail the login but don't destroy 1502 * the session until later. 1503 */ 1504 return (IDM_STATUS_FAIL); 1505 } 1506 1507 1508 static idm_status_t 1509 login_sm_set_auth(iscsit_conn_t *ict) 1510 { 1511 idm_status_t idmrc = IDM_STATUS_SUCCESS; 1512 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 1513 iscsit_ini_t *ini; 1514 iscsit_tgt_t *tgt; 1515 char *auth = ""; 1516 char *radiusserver = ""; 1517 char *radiussecret = ""; 1518 char *chapuser = ""; 1519 char *chapsecret = ""; 1520 char *targetchapuser = ""; 1521 char *targetchapsecret = ""; 1522 char *targetalias = ""; 1523 int i; 1524 1525 ISCSIT_GLOBAL_LOCK(RW_READER); 1526 1527 /* 1528 * Set authentication method to none for discovery session. 1529 */ 1530 if (ict->ict_op.op_discovery_session == B_TRUE) { 1531 lsm->icl_auth.ca_method_valid_list[0] = AM_NONE; 1532 ISCSIT_GLOBAL_UNLOCK(); 1533 return (idmrc); 1534 } 1535 1536 /* 1537 * Get all the authentication parameters we need -- since we hold 1538 * the global config lock we guarantee that the parameters will 1539 * be consistent with each other. 1540 */ 1541 (void) nvlist_lookup_string(iscsit_global.global_props, 1542 PROP_AUTH, &auth); 1543 (void) nvlist_lookup_string(iscsit_global.global_props, 1544 PROP_RADIUS_SERVER, &radiusserver); 1545 (void) nvlist_lookup_string(iscsit_global.global_props, 1546 PROP_RADIUS_SECRET, &radiussecret); 1547 1548 ini = iscsit_ini_lookup_locked(lsm->icl_initiator_name); 1549 if (ini != NULL) { 1550 /* Get Initiator CHAP parameters */ 1551 (void) nvlist_lookup_string(ini->ini_props, PROP_CHAP_USER, 1552 &chapuser); 1553 (void) nvlist_lookup_string(ini->ini_props, PROP_CHAP_SECRET, 1554 &chapsecret); 1555 } 1556 1557 tgt = ict->ict_sess->ist_tgt; 1558 if (tgt != NULL) { 1559 /* See if we have a target-specific authentication setting */ 1560 (void) nvlist_lookup_string(tgt->target_props, PROP_AUTH, 1561 &auth); 1562 /* Get target CHAP parameters */ 1563 (void) nvlist_lookup_string(tgt->target_props, 1564 PROP_TARGET_CHAP_USER, &targetchapuser); 1565 (void) nvlist_lookup_string(tgt->target_props, 1566 PROP_TARGET_CHAP_SECRET, &targetchapsecret); 1567 /* Get alias */ 1568 (void) nvlist_lookup_string(tgt->target_props, 1569 PROP_ALIAS, &targetalias); 1570 } 1571 1572 /* Set authentication method */ 1573 i = 0; 1574 if (strcmp(auth, PA_AUTH_RADIUS) == 0) { 1575 /* CHAP authentication using RADIUS server */ 1576 lsm->icl_auth.ca_method_valid_list[i++] = AM_CHAP; 1577 lsm->icl_auth.ca_use_radius = B_TRUE; 1578 } else if (strcmp(auth, PA_AUTH_CHAP) == 0) { 1579 /* Local CHAP authentication */ 1580 lsm->icl_auth.ca_method_valid_list[i++] = AM_CHAP; 1581 lsm->icl_auth.ca_use_radius = B_FALSE; 1582 } else if ((strcmp(auth, PA_AUTH_NONE) == 0) || 1583 (strcmp(auth, "") == 0)) { 1584 /* No authentication */ 1585 lsm->icl_auth.ca_method_valid_list[i++] = AM_NONE; 1586 } 1587 1588 /* 1589 * If initiator/target CHAP username is not set then use the 1590 * node name. If lsm->icl_target_name == NULL then this is 1591 * a discovery session so we don't need to work about the target. 1592 */ 1593 if (strcmp(chapuser, "") == 0) { 1594 (void) strlcpy(lsm->icl_auth.ca_ini_chapuser, 1595 lsm->icl_initiator_name, 1596 min(iscsitAuthStringMaxLength, MAX_ISCSI_NODENAMELEN)); 1597 } else { 1598 (void) strlcpy(lsm->icl_auth.ca_ini_chapuser, chapuser, 1599 iscsitAuthStringMaxLength); 1600 } 1601 if ((lsm->icl_target_name != NULL) && 1602 (strcmp(targetchapuser, "") == 0)) { 1603 (void) strlcpy(lsm->icl_auth.ca_tgt_chapuser, 1604 lsm->icl_target_name, 1605 min(iscsitAuthStringMaxLength, MAX_ISCSI_NODENAMELEN)); 1606 } else { 1607 (void) strlcpy(lsm->icl_auth.ca_tgt_chapuser, 1608 targetchapuser, iscsitAuthStringMaxLength); 1609 } 1610 1611 /* 1612 * Secrets are stored in base64-encoded format so we need to 1613 * decode them into binary form 1614 */ 1615 if (strcmp(chapsecret, "") == 0) { 1616 lsm->icl_auth.ca_ini_chapsecretlen = 0; 1617 } else { 1618 if (iscsi_base64_str_to_binary(chapsecret, 1619 strnlen(chapsecret, iscsitAuthStringMaxLength), 1620 lsm->icl_auth.ca_ini_chapsecret, iscsitAuthStringMaxLength, 1621 &lsm->icl_auth.ca_ini_chapsecretlen) != 0) { 1622 cmn_err(CE_WARN, "Corrupted CHAP secret" 1623 " for initiator %s", lsm->icl_initiator_name); 1624 lsm->icl_auth.ca_ini_chapsecretlen = 0; 1625 } 1626 } 1627 if (strcmp(targetchapsecret, "") == 0) { 1628 lsm->icl_auth.ca_tgt_chapsecretlen = 0; 1629 } else { 1630 if (iscsi_base64_str_to_binary(targetchapsecret, 1631 strnlen(targetchapsecret, iscsitAuthStringMaxLength), 1632 lsm->icl_auth.ca_tgt_chapsecret, iscsitAuthStringMaxLength, 1633 &lsm->icl_auth.ca_tgt_chapsecretlen) != 0) { 1634 cmn_err(CE_WARN, "Corrupted CHAP secret" 1635 " for target %s", lsm->icl_target_name); 1636 lsm->icl_auth.ca_tgt_chapsecretlen = 0; 1637 } 1638 } 1639 if (strcmp(radiussecret, "") == 0) { 1640 lsm->icl_auth.ca_radius_secretlen = 0; 1641 } else { 1642 if (iscsi_base64_str_to_binary(radiussecret, 1643 strnlen(radiussecret, iscsitAuthStringMaxLength), 1644 lsm->icl_auth.ca_radius_secret, iscsitAuthStringMaxLength, 1645 &lsm->icl_auth.ca_radius_secretlen) != 0) { 1646 cmn_err(CE_WARN, "Corrupted RADIUS secret"); 1647 lsm->icl_auth.ca_radius_secretlen = 0; 1648 } 1649 } 1650 1651 /* 1652 * Set alias 1653 */ 1654 (void) strlcpy(lsm->icl_auth.ca_tgt_alias, targetalias, 1655 MAX_ISCSI_NODENAMELEN); 1656 1657 /* 1658 * Now that authentication parameters are setup, validate the parameters 1659 * against the authentication mode 1660 * Decode RADIUS server value int lsm->icl_auth.ca_radius_server 1661 */ 1662 if ((strcmp(auth, PA_AUTH_RADIUS) == 0) && 1663 ((lsm->icl_auth.ca_radius_secretlen == 0) || 1664 (strcmp(radiusserver, "") == 0) || 1665 it_common_convert_sa(radiusserver, 1666 &lsm->icl_auth.ca_radius_server, 1667 DEFAULT_RADIUS_PORT) == NULL)) { 1668 cmn_err(CE_WARN, "RADIUS authentication selected " 1669 "for target %s but RADIUS parameters are not " 1670 "configured.", lsm->icl_target_name); 1671 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR, 1672 ISCSI_LOGIN_STATUS_TARGET_ERROR); 1673 idmrc = IDM_STATUS_FAIL; 1674 } else if ((strcmp(auth, PA_AUTH_CHAP) == 0) && 1675 (lsm->icl_auth.ca_ini_chapsecretlen == 0)) { 1676 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR, 1677 ISCSI_LOGIN_STATUS_AUTH_FAILED); 1678 idmrc = IDM_STATUS_FAIL; 1679 } 1680 1681 ISCSIT_GLOBAL_UNLOCK(); 1682 1683 return (idmrc); 1684 } 1685 1686 1687 static idm_status_t 1688 login_sm_session_register(iscsit_conn_t *ict) 1689 { 1690 iscsit_sess_t *ist = ict->ict_sess; 1691 stmf_scsi_session_t *ss; 1692 1693 /* 1694 * Hold target mutex until we have finished registering with STMF 1695 */ 1696 mutex_enter(&ist->ist_tgt->target_mutex); 1697 if (ist->ist_tgt->target_state != TS_STMF_ONLINE) { 1698 mutex_exit(&ist->ist_tgt->target_mutex); 1699 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR, 1700 ISCSI_LOGIN_STATUS_TGT_REMOVED); 1701 return (IDM_STATUS_FAIL); 1702 } 1703 1704 ss = stmf_alloc(STMF_STRUCT_SCSI_SESSION, 0, 1705 0); 1706 if (ss == NULL) { 1707 mutex_exit(&ist->ist_tgt->target_mutex); 1708 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR, 1709 ISCSI_LOGIN_STATUS_NO_RESOURCES); 1710 return (IDM_STATUS_FAIL); 1711 } 1712 1713 ss->ss_rport_id = kmem_zalloc(sizeof (scsi_devid_desc_t) + 1714 strlen(ist->ist_initiator_name) + 1, KM_SLEEP); 1715 (void) strcpy((char *)ss->ss_rport_id->ident, ist->ist_initiator_name); 1716 ss->ss_rport_id->ident_length = strlen(ist->ist_initiator_name); 1717 ss->ss_rport_id->protocol_id = PROTOCOL_iSCSI; 1718 ss->ss_rport_id->piv = 1; 1719 ss->ss_rport_id->code_set = CODE_SET_ASCII; 1720 ss->ss_rport_id->association = ID_IS_TARGET_PORT; 1721 1722 ss->ss_lport = ist->ist_lport; 1723 1724 if (stmf_register_scsi_session(ict->ict_sess->ist_lport, ss) != 1725 STMF_SUCCESS) { 1726 mutex_exit(&ist->ist_tgt->target_mutex); 1727 kmem_free(ss->ss_rport_id, 1728 sizeof (scsi_devid_desc_t) + 1729 strlen(ist->ist_initiator_name) + 1); 1730 stmf_free(ss); 1731 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR, 1732 ISCSI_LOGIN_STATUS_TARGET_ERROR); 1733 return (IDM_STATUS_FAIL); 1734 } 1735 1736 ss->ss_port_private = ict->ict_sess; 1737 ict->ict_sess->ist_stmf_sess = ss; 1738 mutex_exit(&ist->ist_tgt->target_mutex); 1739 1740 return (IDM_STATUS_SUCCESS); 1741 } 1742 1743 1744 static idm_status_t 1745 login_sm_req_pdu_check(iscsit_conn_t *ict, idm_pdu_t *pdu) 1746 { 1747 uint8_t csg_req; 1748 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 1749 iscsi_login_hdr_t *lh = (iscsi_login_hdr_t *)pdu->isp_hdr; 1750 iscsi_login_rsp_hdr_t *lh_resp = lsm->icl_login_resp_tmpl; 1751 1752 /* 1753 * Check CSG 1754 */ 1755 csg_req = ISCSI_LOGIN_CURRENT_STAGE(lh->flags); 1756 switch (csg_req) { 1757 case ISCSI_SECURITY_NEGOTIATION_STAGE: 1758 case ISCSI_OP_PARMS_NEGOTIATION_STAGE: 1759 if ((csg_req != lsm->icl_login_csg) && 1760 (lsm->icl_login_state != ILS_LOGIN_INIT)) { 1761 /* 1762 * Inappropriate CSG change. Initiator can only 1763 * change CSG after we've responded with the 1764 * transit bit set. If we had responded with 1765 * a CSG change previous we would have updated 1766 * our copy of CSG. 1767 * 1768 * The exception is when we are in ILS_LOGIN_INIT 1769 * state since we haven't determined our initial 1770 * CSG value yet. 1771 */ 1772 goto pdu_check_fail; 1773 } 1774 break; 1775 case ISCSI_FULL_FEATURE_PHASE: 1776 default: 1777 goto pdu_check_fail; 1778 } 1779 1780 /* 1781 * If this is the first login PDU for a new connection then 1782 * the session will be NULL. 1783 */ 1784 if (ict->ict_sess != NULL) { 1785 /* 1786 * We've already created a session on a previous PDU. Make 1787 * sure this PDU is consistent with what we've already seen 1788 */ 1789 if ((ict->ict_cid != ntohs(lh->cid)) || 1790 (bcmp(ict->ict_sess->ist_isid, lh->isid, 1791 ISCSI_ISID_LEN) != 0)) { 1792 goto pdu_check_fail; 1793 } 1794 } 1795 1796 /* 1797 * Make sure we are compatible with the version range 1798 */ 1799 #if (ISCSIT_MAX_VERSION > 0) 1800 if ((lh->min_version > ISCSIT_MAX_VERSION) || 1801 (lh->max_version < ISCSIT_MIN_VERSION)) { 1802 goto pdu_check_fail; 1803 } 1804 #endif 1805 1806 /* 1807 * Just in case the initiator changes things up on us along the way 1808 * check against our active_version -- we can't change the active 1809 * version and the initiator is not *supposed* to change its 1810 * min_version and max_version values so this should never happen. 1811 * Of course we only do this if the response header template has 1812 * been built. 1813 */ 1814 if ((lh_resp->opcode == ISCSI_OP_LOGIN_RSP) && /* header valid */ 1815 ((lh->min_version > lh_resp->active_version) || 1816 (lh->max_version < lh_resp->active_version))) { 1817 goto pdu_check_fail; 1818 } 1819 1820 return (IDM_STATUS_SUCCESS); 1821 1822 pdu_check_fail: 1823 return (IDM_STATUS_FAIL); 1824 } 1825 1826 static idm_status_t 1827 login_sm_process_nvlist(iscsit_conn_t *ict) 1828 { 1829 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 1830 char *nvp_name; 1831 nvpair_t *nvp; 1832 nvpair_t *next_nvp; 1833 nvpair_t *negotiated_nvp; 1834 kv_status_t kvrc; 1835 uint8_t error_class; 1836 uint8_t error_detail; 1837 idm_status_t idm_status; 1838 1839 error_class = ISCSI_STATUS_CLASS_SUCCESS; 1840 error_detail = ISCSI_LOGIN_STATUS_ACCEPT; 1841 1842 /* First, request that the transport process the list */ 1843 kvrc = idm_negotiate_key_values(ict->ict_ic, lsm->icl_request_nvlist, 1844 lsm->icl_response_nvlist, lsm->icl_negotiated_values); 1845 idm_kvstat_to_error(kvrc, &error_class, &error_detail); 1846 if (error_class != ISCSI_STATUS_CLASS_SUCCESS) { 1847 SET_LOGIN_ERROR(ict, error_class, error_detail); 1848 idm_status = IDM_STATUS_FAIL; 1849 return (idm_status); 1850 } 1851 1852 /* Ensure we clear transit bit if the transport layer has countered */ 1853 if (kvrc == KV_HANDLED_NO_TRANSIT) { 1854 lsm->icl_login_transit = B_FALSE; 1855 } 1856 1857 /* Now, move on and process the rest of the pairs */ 1858 nvp = nvlist_next_nvpair(lsm->icl_request_nvlist, NULL); 1859 while (nvp != NULL) { 1860 next_nvp = nvlist_next_nvpair(lsm->icl_request_nvlist, nvp); 1861 nvp_name = nvpair_name(nvp); 1862 /* 1863 * If we've already agreed upon a value then make sure this 1864 * is not attempting to change that value. From RFC3270 1865 * section 5.3: 1866 * 1867 * "Neither the initiator nor the target should attempt to 1868 * declare or negotiate a parameter more than once during 1869 * login except for responses to specific keys that 1870 * explicitly allow repeated key declarations (e.g., 1871 * TargetAddress). An attempt to renegotiate/redeclare 1872 * parameters not specifically allowed MUST be detected 1873 * by the initiator and target. If such an attempt is 1874 * detected by the target, the target MUST respond 1875 * with Login reject (initiator error); ..." 1876 */ 1877 if (nvlist_lookup_nvpair(lsm->icl_negotiated_values, 1878 nvp_name, &negotiated_nvp) == 0) { 1879 kvrc = KV_HANDLED; 1880 } else { 1881 kvrc = iscsit_handle_key(ict, nvp, nvp_name); 1882 } 1883 1884 idm_kvstat_to_error(kvrc, &error_class, &error_detail); 1885 if (error_class != ISCSI_STATUS_CLASS_SUCCESS) { 1886 break; 1887 } 1888 1889 nvp = next_nvp; 1890 } 1891 1892 if (error_class == ISCSI_STATUS_CLASS_SUCCESS) { 1893 idm_status = IDM_STATUS_SUCCESS; 1894 } else { 1895 /* supply login class/detail for login errors */ 1896 SET_LOGIN_ERROR(ict, error_class, error_detail); 1897 idm_status = IDM_STATUS_FAIL; 1898 } 1899 1900 return (idm_status); 1901 } 1902 1903 static idm_status_t 1904 login_sm_check_security(iscsit_conn_t *ict) 1905 { 1906 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 1907 conn_auth_t *auth = &lsm->icl_auth; 1908 iscsit_auth_method_t *am_list = &auth->ca_method_valid_list[0]; 1909 kv_status_t kvrc; 1910 uint8_t error_class; 1911 uint8_t error_detail; 1912 idm_status_t idm_status; 1913 1914 error_class = ISCSI_STATUS_CLASS_SUCCESS; 1915 error_detail = ISCSI_LOGIN_STATUS_ACCEPT; 1916 1917 /* Check authentication status. */ 1918 if (lsm->icl_login_csg == ISCSI_SECURITY_NEGOTIATION_STAGE) { 1919 /* 1920 * We should have some authentication key/value pair(s) 1921 * received from initiator and the authentication phase 1922 * has been shifted when the key/value pair(s) are being 1923 * handled in the previous call iscsit_handle_security_key. 1924 * Now it turns to target to check the authentication phase 1925 * and shift it after taking some authentication action. 1926 */ 1927 kvrc = iscsit_reply_security_key(ict); 1928 idm_kvstat_to_error(kvrc, &error_class, &error_detail); 1929 } else if (!ict->ict_login_sm.icl_auth_pass) { 1930 /* 1931 * Check to see if the target allows initiators to bypass the 1932 * security check. If the target is configured to require 1933 * authentication, we reject the connection. 1934 */ 1935 if (am_list[0] == AM_NONE || am_list[0] == 0) { 1936 ict->ict_login_sm.icl_auth_pass = 1; 1937 } else { 1938 error_class = ISCSI_STATUS_CLASS_INITIATOR_ERR; 1939 error_detail = ISCSI_LOGIN_STATUS_AUTH_FAILED; 1940 } 1941 } 1942 1943 if (error_class == ISCSI_STATUS_CLASS_SUCCESS) { 1944 idm_status = IDM_STATUS_SUCCESS; 1945 } else { 1946 /* supply login class/detail for login errors */ 1947 SET_LOGIN_ERROR(ict, error_class, error_detail); 1948 idm_status = IDM_STATUS_FAIL; 1949 } 1950 1951 return (idm_status); 1952 } 1953 1954 static idm_pdu_t * 1955 login_sm_build_login_response(iscsit_conn_t *ict) 1956 { 1957 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 1958 iscsi_login_rsp_hdr_t *lh; 1959 int transit, text_transit = 1; 1960 idm_pdu_t *login_resp; 1961 1962 /* 1963 * Create a response PDU and fill it with as much of 1964 * the response text that will fit. 1965 */ 1966 1967 if (lsm->icl_login_resp_itb) { 1968 /* allocate a pdu with space for text */ 1969 login_resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), 1970 ISCSI_DEFAULT_MAX_RECV_SEG_LEN); 1971 /* copy a chunk of text into the pdu */ 1972 lsm->icl_login_resp_buf = idm_pdu_init_text_data( 1973 login_resp, lsm->icl_login_resp_itb, 1974 ISCSI_DEFAULT_MAX_RECV_SEG_LEN, 1975 lsm->icl_login_resp_buf, &text_transit); 1976 if (text_transit) { 1977 /* text buf has been consumed */ 1978 idm_itextbuf_free(lsm->icl_login_resp_itb); 1979 lsm->icl_login_resp_itb = NULL; 1980 lsm->icl_login_resp_buf = NULL; 1981 } 1982 } else { 1983 /* allocate a pdu for just a header */ 1984 login_resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0); 1985 } 1986 /* finish initializing the pdu */ 1987 idm_pdu_init(login_resp, 1988 ict->ict_ic, ict, login_resp_complete_cb); 1989 login_resp->isp_flags |= IDM_PDU_LOGIN_TX; 1990 1991 /* 1992 * Use the BHS header values from the response template 1993 */ 1994 bcopy(lsm->icl_login_resp_tmpl, 1995 login_resp->isp_hdr, sizeof (iscsi_login_rsp_hdr_t)); 1996 1997 lh = (iscsi_login_rsp_hdr_t *)login_resp->isp_hdr; 1998 1999 /* Set error class/detail */ 2000 lh->status_class = lsm->icl_login_resp_err_class; 2001 lh->status_detail = lsm->icl_login_resp_err_detail; 2002 /* Set CSG, NSG and Transit */ 2003 lh->flags = 0; 2004 lh->flags |= lsm->icl_login_csg << 2; 2005 2006 2007 if (lh->status_class == ISCSI_STATUS_CLASS_SUCCESS) { 2008 if (lsm->icl_login_transit && 2009 lsm->icl_auth_pass != 0) { 2010 transit = 1; 2011 } else { 2012 transit = 0; 2013 } 2014 /* 2015 * inititalize the text data 2016 */ 2017 if (transit == 1 && text_transit == 1) { 2018 lh->flags |= lsm->icl_login_nsg; 2019 lsm->icl_login_csg = lsm->icl_login_nsg; 2020 lh->flags |= ISCSI_FLAG_LOGIN_TRANSIT; 2021 } else { 2022 lh->flags &= ~ISCSI_FLAG_LOGIN_TRANSIT; 2023 } 2024 2025 /* If we are transitioning to FFP then set TSIH */ 2026 if (transit && (lh->flags & ISCSI_FLAG_LOGIN_TRANSIT) && 2027 lsm->icl_login_csg == ISCSI_FULL_FEATURE_PHASE) { 2028 lh->tsid = htons(ict->ict_sess->ist_tsih); 2029 } 2030 } else { 2031 login_resp->isp_data = 0; 2032 login_resp->isp_datalen = 0; 2033 } 2034 return (login_resp); 2035 } 2036 2037 static kv_status_t 2038 iscsit_handle_key(iscsit_conn_t *ict, nvpair_t *nvp, char *nvp_name) 2039 { 2040 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 2041 kv_status_t kvrc; 2042 const idm_kv_xlate_t *ikvx; 2043 2044 ikvx = idm_lookup_kv_xlate(nvp_name, strlen(nvp_name)); 2045 if (ikvx->ik_key_id == KI_MAX_KEY) { 2046 /* 2047 * Any key not understood by the acceptor may be igonred 2048 * by the acceptor without affecting the basic function. 2049 * However, the answer for a key not understood MUST be 2050 * key=NotUnderstood. 2051 */ 2052 kvrc = iscsit_reply_string(ict, nvp_name, 2053 ISCSI_TEXT_NOTUNDERSTOOD); 2054 } else { 2055 kvrc = iscsit_handle_common_key(ict, nvp, ikvx); 2056 if (kvrc == KV_UNHANDLED) { 2057 switch (lsm->icl_login_csg) { 2058 case ISCSI_SECURITY_NEGOTIATION_STAGE: 2059 kvrc = iscsit_handle_security_key( 2060 ict, nvp, ikvx); 2061 break; 2062 case ISCSI_OP_PARMS_NEGOTIATION_STAGE: 2063 kvrc = iscsit_handle_operational_key( 2064 ict, nvp, ikvx); 2065 break; 2066 case ISCSI_FULL_FEATURE_PHASE: 2067 default: 2068 /* What are we doing here? */ 2069 ASSERT(0); 2070 kvrc = KV_UNHANDLED; 2071 } 2072 } 2073 } 2074 2075 return (kvrc); 2076 } 2077 2078 static kv_status_t 2079 iscsit_handle_common_key(iscsit_conn_t *ict, nvpair_t *nvp, 2080 const idm_kv_xlate_t *ikvx) 2081 { 2082 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 2083 kv_status_t kvrc; 2084 char *string_val; 2085 int nvrc; 2086 2087 switch (ikvx->ik_key_id) { 2088 case KI_INITIATOR_NAME: 2089 case KI_INITIATOR_ALIAS: 2090 nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, nvp); 2091 kvrc = idm_nvstat_to_kvstat(nvrc); 2092 break; 2093 case KI_TARGET_NAME: 2094 /* We'll validate the target during login_sm_session_bind() */ 2095 nvrc = nvpair_value_string(nvp, &string_val); 2096 ASSERT(nvrc == 0); /* We built this nvlist */ 2097 2098 nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, nvp); 2099 kvrc = idm_nvstat_to_kvstat(nvrc); 2100 break; 2101 case KI_TARGET_ALIAS: 2102 case KI_TARGET_ADDRESS: 2103 case KI_TARGET_PORTAL_GROUP_TAG: 2104 kvrc = KV_TARGET_ONLY; /* Only the target can declare this */ 2105 break; 2106 case KI_SESSION_TYPE: 2107 /* 2108 * If we don't receive this key on the initial login 2109 * we assume this is a normal session. 2110 */ 2111 nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, nvp); 2112 kvrc = idm_nvstat_to_kvstat(nvrc); 2113 nvrc = nvpair_value_string(nvp, &string_val); 2114 ASSERT(nvrc == 0); /* We built this nvlist */ 2115 ict->ict_op.op_discovery_session = 2116 strcmp(string_val, "Discovery") == 0 ? B_TRUE : B_FALSE; 2117 break; 2118 default: 2119 /* 2120 * This is not really an error but we should 2121 * leave this nvpair on the list since we 2122 * didn't do anything with it. Either 2123 * the security or operational phase 2124 * handling functions should process it. 2125 */ 2126 kvrc = KV_UNHANDLED; 2127 break; 2128 } 2129 2130 return (kvrc); 2131 } 2132 2133 static kv_status_t 2134 iscsit_handle_security_key(iscsit_conn_t *ict, nvpair_t *nvp, 2135 const idm_kv_xlate_t *ikvx) 2136 { 2137 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 2138 iscsit_auth_client_t *client = &lsm->icl_auth_client; 2139 iscsikey_id_t kv_id; 2140 kv_status_t kvrc; 2141 iscsit_auth_handler_t handler; 2142 2143 /* 2144 * After all of security keys are handled, this function will 2145 * be called again to verify current authentication status 2146 * and perform some actual authentication work. At this time, 2147 * the nvp and ikvx will be passed in as NULLs. 2148 */ 2149 if (ikvx != NULL) { 2150 kv_id = ikvx->ik_key_id; 2151 } else { 2152 kv_id = 0; 2153 } 2154 2155 handler = iscsit_auth_get_handler(client, kv_id); 2156 if (handler) { 2157 kvrc = handler(ict, nvp, ikvx); 2158 } else { 2159 kvrc = KV_UNHANDLED; /* invalid request */ 2160 } 2161 2162 return (kvrc); 2163 } 2164 2165 static kv_status_t 2166 iscsit_reply_security_key(iscsit_conn_t *ict) 2167 { 2168 return (iscsit_handle_security_key(ict, NULL, NULL)); 2169 } 2170 2171 static kv_status_t 2172 iscsit_handle_operational_key(iscsit_conn_t *ict, nvpair_t *nvp, 2173 const idm_kv_xlate_t *ikvx) 2174 { 2175 kv_status_t kvrc = KV_UNHANDLED; 2176 boolean_t bool_val; 2177 uint64_t num_val; 2178 int nvrc; 2179 2180 /* 2181 * Retrieve values. All value lookups are expected to succeed 2182 * since we build the nvlist while decoding the text buffer. This 2183 * step is intended to eliminate some duplication of code (for example 2184 * we only need to code the numerical value lookup once). We will 2185 * handle the values (if necessary) below. 2186 */ 2187 switch (ikvx->ik_key_id) { 2188 /* Lists */ 2189 case KI_HEADER_DIGEST: 2190 case KI_DATA_DIGEST: 2191 break; 2192 /* Booleans */ 2193 case KI_INITIAL_R2T: 2194 case KI_IMMEDIATE_DATA: 2195 case KI_DATA_PDU_IN_ORDER: 2196 case KI_DATA_SEQUENCE_IN_ORDER: 2197 case KI_IFMARKER: 2198 case KI_OFMARKER: 2199 nvrc = nvpair_value_boolean_value(nvp, &bool_val); 2200 ASSERT(nvrc == 0); /* We built this nvlist */ 2201 break; 2202 /* Numericals */ 2203 case KI_MAX_CONNECTIONS: 2204 case KI_MAX_RECV_DATA_SEGMENT_LENGTH: 2205 case KI_MAX_BURST_LENGTH: 2206 case KI_FIRST_BURST_LENGTH: 2207 case KI_DEFAULT_TIME_2_WAIT: 2208 case KI_DEFAULT_TIME_2_RETAIN: 2209 case KI_MAX_OUTSTANDING_R2T: 2210 case KI_ERROR_RECOVERY_LEVEL: 2211 nvrc = nvpair_value_uint64(nvp, &num_val); 2212 ASSERT(nvrc == 0); 2213 break; 2214 /* Ranges */ 2215 case KI_OFMARKERINT: 2216 case KI_IFMARKERINT: 2217 break; 2218 default: 2219 break; 2220 } 2221 2222 /* 2223 * Now handle the values according to the key name. Sometimes we 2224 * don't care what the value is -- in that case we just add the nvpair 2225 * to the negotiated values list. 2226 */ 2227 switch (ikvx->ik_key_id) { 2228 case KI_HEADER_DIGEST: 2229 kvrc = iscsit_handle_digest(ict, nvp, ikvx); 2230 break; 2231 case KI_DATA_DIGEST: 2232 kvrc = iscsit_handle_digest(ict, nvp, ikvx); 2233 break; 2234 case KI_INITIAL_R2T: 2235 /* We *require* INITIAL_R2T=yes */ 2236 kvrc = iscsit_handle_boolean(ict, nvp, bool_val, ikvx, 2237 B_TRUE); 2238 break; 2239 case KI_IMMEDIATE_DATA: 2240 kvrc = iscsit_handle_boolean(ict, nvp, bool_val, ikvx, 2241 bool_val); 2242 break; 2243 case KI_DATA_PDU_IN_ORDER: 2244 kvrc = iscsit_handle_boolean(ict, nvp, bool_val, ikvx, 2245 B_TRUE); 2246 break; 2247 case KI_DATA_SEQUENCE_IN_ORDER: 2248 /* We allow any value for DATA_SEQUENCE_IN_ORDER */ 2249 kvrc = iscsit_handle_boolean(ict, nvp, bool_val, ikvx, 2250 bool_val); 2251 break; 2252 case KI_OFMARKER: 2253 case KI_IFMARKER: 2254 /* We don't support markers */ 2255 kvrc = iscsit_handle_boolean(ict, nvp, bool_val, ikvx, 2256 B_FALSE); 2257 break; 2258 case KI_MAX_CONNECTIONS: 2259 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx, 2260 ISCSI_MIN_CONNECTIONS, 2261 ISCSI_MAX_CONNECTIONS, 2262 ISCSIT_MAX_CONNECTIONS); 2263 break; 2264 case KI_MAX_RECV_DATA_SEGMENT_LENGTH: 2265 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx, 2266 ISCSI_MIN_RECV_DATA_SEGMENT_LENGTH, 2267 ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH, 2268 ISCSIT_MAX_RECV_DATA_SEGMENT_LENGTH); 2269 break; 2270 case KI_MAX_BURST_LENGTH: 2271 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx, 2272 ISCSI_MIN_MAX_BURST_LENGTH, 2273 ISCSI_MAX_BURST_LENGTH, 2274 ISCSIT_MAX_BURST_LENGTH); 2275 break; 2276 case KI_FIRST_BURST_LENGTH: 2277 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx, 2278 ISCSI_MIN_FIRST_BURST_LENGTH, 2279 ISCSI_MAX_FIRST_BURST_LENGTH, 2280 ISCSIT_MAX_FIRST_BURST_LENGTH); 2281 break; 2282 case KI_DEFAULT_TIME_2_WAIT: 2283 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx, 2284 ISCSI_MIN_TIME2WAIT, 2285 ISCSI_MAX_TIME2WAIT, 2286 ISCSIT_MAX_TIME2WAIT); 2287 break; 2288 case KI_DEFAULT_TIME_2_RETAIN: 2289 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx, 2290 ISCSI_MIN_TIME2RETAIN, 2291 ISCSI_MAX_TIME2RETAIN, 2292 ISCSIT_MAX_TIME2RETAIN); 2293 break; 2294 case KI_MAX_OUTSTANDING_R2T: 2295 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx, 2296 ISCSI_MIN_MAX_OUTSTANDING_R2T, 2297 ISCSI_MAX_OUTSTANDING_R2T, 2298 ISCSIT_MAX_OUTSTANDING_R2T); 2299 break; 2300 case KI_ERROR_RECOVERY_LEVEL: 2301 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx, 2302 ISCSI_MIN_ERROR_RECOVERY_LEVEL, 2303 ISCSI_MAX_ERROR_RECOVERY_LEVEL, 2304 ISCSIT_MAX_ERROR_RECOVERY_LEVEL); 2305 break; 2306 case KI_OFMARKERINT: 2307 case KI_IFMARKERINT: 2308 kvrc = iscsit_reply_string(ict, ikvx->ik_key_name, 2309 ISCSI_TEXT_IRRELEVANT); 2310 break; 2311 default: 2312 kvrc = KV_UNHANDLED; /* invalid request */ 2313 break; 2314 } 2315 2316 return (kvrc); 2317 } 2318 2319 static kv_status_t 2320 iscsit_reply_numerical(iscsit_conn_t *ict, 2321 const char *nvp_name, const uint64_t value) 2322 { 2323 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 2324 kv_status_t kvrc; 2325 int nvrc; 2326 2327 nvrc = nvlist_add_uint64(lsm->icl_response_nvlist, 2328 nvp_name, value); 2329 kvrc = idm_nvstat_to_kvstat(nvrc); 2330 2331 return (kvrc); 2332 } 2333 2334 static kv_status_t 2335 iscsit_reply_string(iscsit_conn_t *ict, 2336 const char *nvp_name, const char *text) 2337 { 2338 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 2339 kv_status_t kvrc; 2340 int nvrc; 2341 2342 nvrc = nvlist_add_string(lsm->icl_response_nvlist, 2343 nvp_name, text); 2344 kvrc = idm_nvstat_to_kvstat(nvrc); 2345 2346 return (kvrc); 2347 } 2348 2349 static kv_status_t 2350 iscsit_handle_digest(iscsit_conn_t *ict, nvpair_t *choices, 2351 const idm_kv_xlate_t *ikvx) 2352 { 2353 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 2354 kv_status_t kvrc = KV_VALUE_ERROR; 2355 int nvrc; 2356 nvpair_t *digest_choice; 2357 char *digest_choice_string; 2358 2359 /* 2360 * Need to add persistent config here if we want users to allow 2361 * disabling of digests on the target side. You could argue that 2362 * this makes things too complicated... just let the initiator state 2363 * what it wants and we'll take it. For now that's exactly what 2364 * we'll do. 2365 * 2366 * Basic digest negotiation happens here at iSCSI level. IDM 2367 * can override this during negotiate_key_values phase to 2368 * decline to set up any digest processing. 2369 */ 2370 digest_choice = idm_get_next_listvalue(choices, NULL); 2371 2372 /* 2373 * Loop through all choices. As soon as we find a choice 2374 * that we support add the value to our negotiated values list 2375 * and respond with that value in the login response. 2376 */ 2377 while (digest_choice != NULL) { 2378 nvrc = nvpair_value_string(digest_choice, 2379 &digest_choice_string); 2380 ASSERT(nvrc == 0); 2381 2382 if ((strcasecmp(digest_choice_string, "crc32c") == 0) || 2383 (strcasecmp(digest_choice_string, "none") == 0)) { 2384 /* Add to negotiated values list */ 2385 nvrc = nvlist_add_string(lsm->icl_negotiated_values, 2386 ikvx->ik_key_name, digest_choice_string); 2387 kvrc = idm_nvstat_to_kvstat(nvrc); 2388 if (nvrc == 0) { 2389 /* Add to login response list */ 2390 nvrc = nvlist_add_string( 2391 lsm->icl_response_nvlist, 2392 ikvx->ik_key_name, digest_choice_string); 2393 kvrc = idm_nvstat_to_kvstat(nvrc); 2394 } 2395 break; 2396 } 2397 digest_choice = idm_get_next_listvalue(choices, 2398 digest_choice); 2399 } 2400 2401 if (digest_choice == NULL) 2402 kvrc = KV_VALUE_ERROR; 2403 2404 return (kvrc); 2405 } 2406 2407 static kv_status_t 2408 iscsit_handle_boolean(iscsit_conn_t *ict, nvpair_t *nvp, boolean_t value, 2409 const idm_kv_xlate_t *ikvx, boolean_t iscsit_value) 2410 { 2411 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 2412 kv_status_t kvrc; 2413 int nvrc; 2414 2415 if (value != iscsit_value) { 2416 /* Respond back to initiator with our value */ 2417 value = iscsit_value; 2418 lsm->icl_login_transit = B_FALSE; 2419 nvrc = 0; 2420 } else { 2421 /* Add this to our negotiated values */ 2422 nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, 2423 nvp); 2424 } 2425 2426 /* Response of Simple-value Negotiation */ 2427 if (nvrc == 0 && !ikvx->ik_declarative) { 2428 nvrc = nvlist_add_boolean_value( 2429 lsm->icl_response_nvlist, ikvx->ik_key_name, value); 2430 } 2431 kvrc = idm_nvstat_to_kvstat(nvrc); 2432 2433 return (kvrc); 2434 } 2435 2436 static kv_status_t 2437 iscsit_handle_numerical(iscsit_conn_t *ict, nvpair_t *nvp, uint64_t value, 2438 const idm_kv_xlate_t *ikvx, 2439 uint64_t iscsi_min_value, uint64_t iscsi_max_value, 2440 uint64_t iscsit_max_value) 2441 { 2442 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 2443 kv_status_t kvrc; 2444 int nvrc; 2445 2446 /* Validate against standard */ 2447 if ((value < iscsi_min_value) || (value > iscsi_max_value)) { 2448 kvrc = KV_VALUE_ERROR; 2449 } else { 2450 if (value > iscsit_max_value) { 2451 /* Respond back to initiator with our value */ 2452 value = iscsit_max_value; 2453 lsm->icl_login_transit = B_FALSE; 2454 nvrc = 0; 2455 } else { 2456 /* Add this to our negotiated values */ 2457 nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, 2458 nvp); 2459 } 2460 2461 /* Response of Simple-value Negotiation */ 2462 if (nvrc == 0 && !ikvx->ik_declarative) { 2463 nvrc = nvlist_add_uint64(lsm->icl_response_nvlist, 2464 ikvx->ik_key_name, value); 2465 } 2466 kvrc = idm_nvstat_to_kvstat(nvrc); 2467 } 2468 2469 return (kvrc); 2470 } 2471 2472 2473 static void 2474 iscsit_process_negotiated_values(iscsit_conn_t *ict) 2475 { 2476 iscsit_conn_login_t *lsm = &ict->ict_login_sm; 2477 char *string_val; 2478 boolean_t boolean_val; 2479 uint64_t uint64_val; 2480 int nvrc; 2481 2482 /* Let the IDM level activate its parameters first */ 2483 idm_notice_key_values(ict->ict_ic, lsm->icl_negotiated_values); 2484 2485 /* 2486 * Initiator alias and target alias 2487 */ 2488 if ((nvrc = nvlist_lookup_string(lsm->icl_negotiated_values, 2489 "InitiatorAlias", &string_val)) != ENOENT) { 2490 ASSERT(nvrc == 0); 2491 ict->ict_sess->ist_initiator_alias = 2492 kmem_alloc(strlen(string_val) + 1, KM_SLEEP); 2493 (void) strcpy(ict->ict_sess->ist_initiator_alias, string_val); 2494 } 2495 2496 if ((nvrc = nvlist_lookup_string(lsm->icl_negotiated_values, 2497 "TargetAlias", &string_val)) != ENOENT) { 2498 ASSERT(nvrc == 0); 2499 ict->ict_sess->ist_target_alias = 2500 kmem_alloc(strlen(string_val) + 1, KM_SLEEP); 2501 (void) strcpy(ict->ict_sess->ist_target_alias, string_val); 2502 } 2503 2504 /* 2505 * Operational parameters. We process SessionType when it is 2506 * initially received since it is required on the initial login. 2507 */ 2508 if ((nvrc = nvlist_lookup_boolean_value(lsm->icl_negotiated_values, 2509 "InitialR2T", &boolean_val)) != ENOENT) { 2510 ASSERT(nvrc == 0); 2511 ict->ict_op.op_initial_r2t = boolean_val; 2512 } 2513 2514 if ((nvrc = nvlist_lookup_boolean_value(lsm->icl_negotiated_values, 2515 "ImmediateData", &boolean_val)) != ENOENT) { 2516 ASSERT(nvrc == 0); 2517 ict->ict_op.op_immed_data = boolean_val; 2518 } 2519 2520 if ((nvrc = nvlist_lookup_boolean_value(lsm->icl_negotiated_values, 2521 "DataPDUInOrder", &boolean_val)) != ENOENT) { 2522 ASSERT(nvrc == 0); 2523 ict->ict_op.op_data_pdu_in_order = boolean_val; 2524 } 2525 2526 if ((nvrc = nvlist_lookup_boolean_value(lsm->icl_negotiated_values, 2527 "DataSequenceInOrder", &boolean_val)) != ENOENT) { 2528 ASSERT(nvrc == 0); 2529 ict->ict_op.op_data_sequence_in_order = boolean_val; 2530 } 2531 2532 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values, 2533 "MaxConnections", &uint64_val)) != ENOENT) { 2534 ASSERT(nvrc == 0); 2535 ict->ict_op.op_max_connections = uint64_val; 2536 } 2537 2538 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values, 2539 "MaxRecvDataSegmentLength", &uint64_val)) != ENOENT) { 2540 ASSERT(nvrc == 0); 2541 ict->ict_op.op_max_recv_data_segment_length = uint64_val; 2542 } 2543 2544 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values, 2545 "MaxBurstLength", &uint64_val)) != ENOENT) { 2546 ASSERT(nvrc == 0); 2547 ict->ict_op.op_max_burst_length = uint64_val; 2548 } 2549 2550 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values, 2551 "FirstBurstLength", &uint64_val)) != ENOENT) { 2552 ASSERT(nvrc == 0); 2553 ict->ict_op.op_first_burst_length = uint64_val; 2554 } 2555 2556 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values, 2557 "DefaultTime2Wait", &uint64_val)) != ENOENT) { 2558 ASSERT(nvrc == 0); 2559 ict->ict_op.op_default_time_2_wait = uint64_val; 2560 } 2561 2562 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values, 2563 "DefaultTime2Retain", &uint64_val)) != ENOENT) { 2564 ASSERT(nvrc == 0); 2565 ict->ict_op.op_default_time_2_retain = uint64_val; 2566 } 2567 2568 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values, 2569 "MaxOutstandingR2T", &uint64_val)) != ENOENT) { 2570 ASSERT(nvrc == 0); 2571 ict->ict_op.op_max_outstanding_r2t = uint64_val; 2572 } 2573 2574 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values, 2575 "ErrorRecoveryLevel", &uint64_val)) != ENOENT) { 2576 ASSERT(nvrc == 0); 2577 ict->ict_op.op_error_recovery_level = uint64_val; 2578 } 2579 } 2580