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 2000 by Cisco Systems, Inc. All rights reserved. 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24 * 25 * iSCSI protocol login and enumeration 26 */ 27 28 #include "iscsi.h" 29 #include <sys/iscsi_protocol.h> 30 #include <sys/scsi/adapters/iscsi_door.h> 31 32 boolean_t iscsi_login_logging = B_FALSE; 33 34 /* internal login protocol interfaces */ 35 static iscsi_status_t iscsi_login(iscsi_conn_t *icp, 36 uint8_t *status_class, uint8_t *status_detail); 37 static int iscsi_add_text(idm_pdu_t *text_pdu, 38 int max_data_length, char *param, char *value); 39 static int iscsi_find_key_value(char *param, char *ihp, char *pdu_end, 40 char **value_start, char **value_end); 41 static void iscsi_null_callback(void *user_handle, void *message_handle, 42 int auth_status); 43 static iscsi_status_t iscsi_process_login_response(iscsi_conn_t *icp, 44 iscsi_login_rsp_hdr_t *ilrhp, char *data, int max_data_length); 45 static iscsi_status_t iscsi_make_login_pdu(iscsi_conn_t *icp, 46 idm_pdu_t *text_pdu, char *data, int max_data_length); 47 static iscsi_status_t iscsi_update_address(iscsi_conn_t *icp, 48 char *address); 49 static char *iscsi_login_failure_str(uchar_t status_class, 50 uchar_t status_detail); 51 static void iscsi_login_end(iscsi_conn_t *icp, 52 iscsi_status_t status, iscsi_task_t *itp); 53 static iscsi_status_t iscsi_login_connect(iscsi_conn_t *icp); 54 static void iscsi_login_disconnect(iscsi_conn_t *icp); 55 static void iscsi_notice_key_values(iscsi_conn_t *icp); 56 57 #define ISCSI_LOGIN_RETRY_DELAY 5 /* seconds */ 58 59 #define ISCSI_LOGIN_TRANSIT_FFP(flags) \ 60 (!(flags & ISCSI_FLAG_LOGIN_CONTINUE) && \ 61 (flags & ISCSI_FLAG_LOGIN_TRANSIT) && \ 62 (ISCSI_LOGIN_CURRENT_STAGE(flags) == \ 63 ISCSI_OP_PARMS_NEGOTIATION_STAGE) && \ 64 (ISCSI_LOGIN_NEXT_STAGE(flags) == \ 65 ISCSI_FULL_FEATURE_PHASE)) 66 67 /* 68 * +--------------------------------------------------------------------+ 69 * | External Login Interface | 70 * +--------------------------------------------------------------------+ 71 */ 72 73 void 74 iscsi_login_cb(void *arg) 75 { 76 (void) iscsi_login_start(arg); 77 } 78 79 /* 80 * iscsi_login_start - connect and perform iscsi protocol login 81 */ 82 iscsi_status_t 83 iscsi_login_start(void *arg) 84 { 85 iscsi_task_t *itp = (iscsi_task_t *)arg; 86 iscsi_status_t rval = ISCSI_STATUS_LOGIN_FAILED; 87 iscsi_conn_t *icp; 88 iscsi_sess_t *isp; 89 iscsi_hba_t *ihp; 90 unsigned char status_class; 91 unsigned char status_detail; 92 93 ASSERT(itp != NULL); 94 icp = (iscsi_conn_t *)itp->t_arg; 95 ASSERT(icp != NULL); 96 isp = icp->conn_sess; 97 ASSERT(isp != NULL); 98 ihp = isp->sess_hba; 99 ASSERT(ihp != NULL); 100 101 login_start: 102 ASSERT((icp->conn_state == ISCSI_CONN_STATE_IN_LOGIN) || 103 (icp->conn_state == ISCSI_CONN_STATE_FAILED) || 104 (icp->conn_state == ISCSI_CONN_STATE_POLLING)); 105 106 icp->conn_state_ffp = B_FALSE; 107 icp->conn_login_status = ISCSI_INITIAL_LOGIN_STAGE; 108 109 /* reset connection statsn */ 110 icp->conn_expstatsn = 0; 111 icp->conn_laststatsn = 0; 112 113 /* sync up authentication information */ 114 (void) iscsi_sess_set_auth(isp); 115 116 /* sync up login and session parameters */ 117 if (!ISCSI_SUCCESS(iscsi_conn_sync_params(icp))) { 118 /* unable to sync params. fail connection attempts */ 119 iscsi_login_end(icp, ISCSI_STATUS_LOGIN_FAILED, itp); 120 return (ISCSI_STATUS_LOGIN_FAILED); 121 } 122 123 /* 124 * Attempt to open TCP connection, associated IDM connection will 125 * have a hold on it that must be released after the call to 126 * iscsi_login() below. 127 */ 128 if (!ISCSI_SUCCESS(iscsi_login_connect(icp))) { 129 if ((isp->sess_boot == B_TRUE) && 130 (ihp->hba_service_status_overwrite == B_TRUE) && 131 (isp->sess_boot_nic_reset == B_FALSE)) { 132 /* 133 * The connection to boot target failed 134 * before the system fully started. 135 * Reset the boot nic to the settings from 136 * firmware before retrying the connect to 137 * save the the system. 138 */ 139 if (iscsi_net_interface(B_TRUE) == 140 ISCSI_STATUS_SUCCESS) { 141 isp->sess_boot_nic_reset = B_TRUE; 142 } 143 } 144 /* retry this failure */ 145 goto login_retry; 146 } 147 148 /* 149 * allocate response buffer with based on default max 150 * transfer size. This size might shift during login. 151 */ 152 icp->conn_login_max_data_length = 153 icp->conn_params.max_xmit_data_seg_len; 154 icp->conn_login_data = kmem_zalloc(icp->conn_login_max_data_length, 155 KM_SLEEP); 156 157 /* 158 * Start protocol login, upon return we will be either logged in 159 * or disconnected 160 */ 161 rval = iscsi_login(icp, &status_class, &status_detail); 162 163 /* done with buffer */ 164 kmem_free(icp->conn_login_data, icp->conn_login_max_data_length); 165 166 /* Release connection hold */ 167 idm_conn_rele(icp->conn_ic); 168 169 /* hard failure in login */ 170 if (!ISCSI_SUCCESS(rval)) { 171 /* 172 * We should just give up retry if these failures are 173 * detected. 174 */ 175 switch (rval) { 176 /* 177 * We should just give up retry if these 178 * failures are detected. 179 */ 180 case ISCSI_STATUS_AUTHENTICATION_FAILED: 181 case ISCSI_STATUS_INTERNAL_ERROR: 182 case ISCSI_STATUS_VERSION_MISMATCH: 183 case ISCSI_STATUS_NEGO_FAIL: 184 case ISCSI_STATUS_LOGIN_TPGT_NEGO_FAIL: 185 /* we don't want to retry this failure */ 186 iscsi_login_end(icp, ISCSI_STATUS_LOGIN_FAILED, itp); 187 return (ISCSI_STATUS_LOGIN_FAILED); 188 default: 189 /* retry this failure */ 190 goto login_retry; 191 } 192 } 193 194 /* soft failure with reason */ 195 switch (status_class) { 196 case ISCSI_STATUS_CLASS_SUCCESS: 197 /* login was successful */ 198 iscsi_login_end(icp, ISCSI_STATUS_SUCCESS, itp); 199 return (ISCSI_STATUS_SUCCESS); 200 case ISCSI_STATUS_CLASS_REDIRECT: 201 /* Retry at the redirected address */ 202 goto login_start; 203 case ISCSI_STATUS_CLASS_TARGET_ERR: 204 /* retry this failure */ 205 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 206 "%s (0x%02x/0x%02x)", icp->conn_oid, 207 iscsi_login_failure_str(status_class, status_detail), 208 status_class, status_detail); 209 goto login_retry; 210 case ISCSI_STATUS_CLASS_INITIATOR_ERR: 211 default: 212 /* All other errors are hard failures */ 213 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 214 "%s (0x%02x/0x%02x) Target: %s, TPGT: %d", 215 icp->conn_oid, 216 iscsi_login_failure_str(status_class, status_detail), 217 status_class, status_detail, isp->sess_name, 218 isp->sess_tpgt_conf); 219 220 /* we don't want to retry this failure */ 221 iscsi_login_end(icp, ISCSI_STATUS_LOGIN_FAILED, itp); 222 break; 223 } 224 225 return (ISCSI_STATUS_LOGIN_FAILED); 226 227 login_retry: 228 /* retry this failure if we haven't run out of time */ 229 if (icp->conn_login_max > ddi_get_lbolt()) { 230 231 if (icp->conn_state == ISCSI_CONN_STATE_POLLING) { 232 icp->conn_login_min = ddi_get_lbolt() + 233 SEC_TO_TICK(icp->conn_tunable_params. 234 polling_login_delay); 235 } else { 236 icp->conn_login_min = ddi_get_lbolt() + 237 SEC_TO_TICK(ISCSI_LOGIN_RETRY_DELAY); 238 } 239 240 if (itp->t_blocking == B_TRUE) { 241 goto login_start; 242 } else { 243 if (ddi_taskq_dispatch(isp->sess_login_taskq, 244 iscsi_login_cb, itp, DDI_SLEEP) != 245 DDI_SUCCESS) { 246 iscsi_login_end(icp, 247 ISCSI_STATUS_LOGIN_TIMED_OUT, itp); 248 } 249 return (ISCSI_STATUS_SUCCESS); 250 } 251 } else { 252 /* Retries exceeded */ 253 iscsi_login_end(icp, ISCSI_STATUS_LOGIN_TIMED_OUT, itp); 254 } 255 256 return (ISCSI_STATUS_LOGIN_FAILED); 257 } 258 259 static void 260 iscsi_login_end(iscsi_conn_t *icp, iscsi_status_t status, iscsi_task_t *itp) 261 { 262 iscsi_sess_t *isp; 263 uint32_t event_count; 264 265 ASSERT(icp != NULL); 266 isp = icp->conn_sess; 267 ASSERT(isp != NULL); 268 269 if (status == ISCSI_STATUS_SUCCESS) { 270 /* Inform IDM of the relevant negotiated values */ 271 iscsi_notice_key_values(icp); 272 273 /* We are now logged in */ 274 iscsi_conn_update_state(icp, ISCSI_CONN_STATE_LOGGED_IN); 275 276 /* startup TX thread */ 277 (void) iscsi_thread_start(icp->conn_tx_thread); 278 279 /* 280 * Move login state machine to LOGIN_FFP. This will 281 * release the taskq thread handling the CN_FFP_ENABLED 282 * allowing the IDM connection state machine to resume 283 * processing events 284 */ 285 iscsi_login_update_state(icp, LOGIN_FFP); 286 287 /* Notify the session that a connection is logged in */ 288 event_count = atomic_inc_32_nv(&isp->sess_state_event_count); 289 iscsi_sess_enter_state_zone(isp); 290 iscsi_sess_state_machine(isp, ISCSI_SESS_EVENT_N1, event_count); 291 iscsi_sess_exit_state_zone(isp); 292 } else { 293 /* If login failed reset nego tpgt */ 294 isp->sess_tpgt_nego = ISCSI_DEFAULT_TPGT; 295 296 mutex_enter(&icp->conn_state_mutex); 297 switch (icp->conn_state) { 298 case ISCSI_CONN_STATE_IN_LOGIN: 299 iscsi_conn_update_state_locked(icp, 300 ISCSI_CONN_STATE_FREE); 301 mutex_exit(&icp->conn_state_mutex); 302 break; 303 case ISCSI_CONN_STATE_FAILED: 304 if (status == ISCSI_STATUS_LOGIN_FAILED) { 305 iscsi_conn_update_state_locked(icp, 306 ISCSI_CONN_STATE_FREE); 307 } else { 308 /* ISCSI_STATUS_LOGIN_TIMED_OUT */ 309 iscsi_conn_update_state_locked(icp, 310 ISCSI_CONN_STATE_POLLING); 311 } 312 mutex_exit(&icp->conn_state_mutex); 313 event_count = atomic_inc_32_nv( 314 &isp->sess_state_event_count); 315 iscsi_sess_enter_state_zone(isp); 316 iscsi_sess_state_machine(isp, ISCSI_SESS_EVENT_N6, 317 event_count); 318 iscsi_sess_exit_state_zone(isp); 319 320 if (status == ISCSI_STATUS_LOGIN_TIMED_OUT) { 321 iscsi_conn_retry(isp, icp); 322 } 323 break; 324 case ISCSI_CONN_STATE_POLLING: 325 if (status == ISCSI_STATUS_LOGIN_FAILED) { 326 iscsi_conn_update_state_locked(icp, 327 ISCSI_CONN_STATE_FREE); 328 mutex_exit(&icp->conn_state_mutex); 329 event_count = atomic_inc_32_nv( 330 &isp->sess_state_event_count); 331 iscsi_sess_enter_state_zone(isp); 332 333 iscsi_sess_state_machine(isp, 334 ISCSI_SESS_EVENT_N6, event_count); 335 336 iscsi_sess_exit_state_zone(isp); 337 } else { 338 /* ISCSI_STATUS_LOGIN_TIMED_OUT */ 339 if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 340 mutex_exit(&icp->conn_state_mutex); 341 342 iscsi_conn_retry(isp, icp); 343 } else { 344 iscsi_conn_update_state_locked(icp, 345 ISCSI_CONN_STATE_FREE); 346 mutex_exit(&icp->conn_state_mutex); 347 } 348 } 349 break; 350 case ISCSI_CONN_STATE_FREE: 351 mutex_exit(&icp->conn_state_mutex); 352 break; 353 default: 354 mutex_exit(&icp->conn_state_mutex); 355 ASSERT(0); 356 break; 357 } 358 } 359 360 if (itp->t_blocking == B_FALSE) { 361 kmem_free(itp, sizeof (iscsi_task_t)); 362 } 363 364 isp->sess_boot_nic_reset = B_FALSE; 365 } 366 367 /* 368 * +--------------------------------------------------------------------+ 369 * | Begin of protocol login routines | 370 * +--------------------------------------------------------------------+ 371 */ 372 373 /* 374 * iscsi_login - Attempt to login to the target. The caller 375 * must check the status class to determine if the login succeeded. 376 * A return of 1 does not mean the login succeeded, it just means 377 * this function worked, and the status class is valid info. This 378 * allows the caller to decide whether or not to retry logins, so 379 * that we don't have any policy logic here. 380 */ 381 iscsi_status_t 382 iscsi_login(iscsi_conn_t *icp, uint8_t *status_class, uint8_t *status_detail) 383 { 384 iscsi_status_t rval = ISCSI_STATUS_INTERNAL_ERROR; 385 struct iscsi_sess *isp = NULL; 386 IscsiAuthClient *auth_client = NULL; 387 int max_data_length = 0; 388 char *data = NULL; 389 idm_pdu_t *text_pdu; 390 char *buffer; 391 size_t bufsize; 392 iscsi_login_rsp_hdr_t *ilrhp; 393 clock_t response_timeout, timeout_result; 394 395 buffer = icp->conn_login_data; 396 bufsize = icp->conn_login_max_data_length; 397 398 ASSERT(icp != NULL); 399 ASSERT(buffer != NULL); 400 ASSERT(status_class != NULL); 401 ASSERT(status_detail != NULL); 402 isp = icp->conn_sess; 403 ASSERT(isp != NULL); 404 405 /* 406 * prepare the connection, hold IDM connection until login completes 407 */ 408 icp->conn_current_stage = ISCSI_INITIAL_LOGIN_STAGE; 409 icp->conn_partial_response = 0; 410 411 if (isp->sess_auth.auth_buffers && 412 isp->sess_auth.num_auth_buffers) { 413 414 auth_client = (IscsiAuthClient *)isp-> 415 sess_auth.auth_buffers[0].address; 416 417 /* 418 * prepare for authentication 419 */ 420 if (iscsiAuthClientInit(iscsiAuthNodeTypeInitiator, 421 isp->sess_auth.num_auth_buffers, 422 isp->sess_auth.auth_buffers) != 423 iscsiAuthStatusNoError) { 424 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 425 "unable to initialize authentication", 426 icp->conn_oid); 427 icp->conn_login_status = ISCSI_STATUS_INTERNAL_ERROR; 428 iscsi_login_disconnect(icp); 429 iscsi_login_update_state(icp, LOGIN_DONE); 430 return (ISCSI_STATUS_INTERNAL_ERROR); 431 } 432 433 if (iscsiAuthClientSetVersion(auth_client, 434 iscsiAuthVersionRfc) != iscsiAuthStatusNoError) { 435 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 436 "unable to set authentication", icp->conn_oid); 437 goto iscsi_login_done; 438 } 439 440 if (isp->sess_auth.username && 441 (iscsiAuthClientSetUsername(auth_client, 442 isp->sess_auth.username) != 443 iscsiAuthStatusNoError)) { 444 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 445 "unable to set username", icp->conn_oid); 446 goto iscsi_login_done; 447 } 448 449 if (isp->sess_auth.password && 450 (iscsiAuthClientSetPassword(auth_client, 451 isp->sess_auth.password, isp->sess_auth.password_length) != 452 iscsiAuthStatusNoError)) { 453 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 454 "unable to set password", icp->conn_oid); 455 goto iscsi_login_done; 456 } 457 458 if (iscsiAuthClientSetIpSec(auth_client, 1) != 459 iscsiAuthStatusNoError) { 460 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 461 "unable to set ipsec", icp->conn_oid); 462 goto iscsi_login_done; 463 } 464 465 if (iscsiAuthClientSetAuthRemote(auth_client, 466 isp->sess_auth.bidirectional_auth) != 467 iscsiAuthStatusNoError) { 468 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 469 "unable to set remote authentication", 470 icp->conn_oid); 471 goto iscsi_login_done; 472 } 473 } 474 475 /* 476 * exchange PDUs until the login stage is complete, or an error occurs 477 */ 478 do { 479 /* setup */ 480 bzero(buffer, bufsize); 481 data = buffer; 482 max_data_length = bufsize; 483 rval = ISCSI_STATUS_INTERNAL_ERROR; 484 485 text_pdu = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0); 486 idm_pdu_init(text_pdu, icp->conn_ic, NULL, NULL); 487 488 /* 489 * fill in the PDU header and text data based on the 490 * login stage that we're in 491 */ 492 rval = iscsi_make_login_pdu(icp, text_pdu, data, 493 max_data_length); 494 if (!ISCSI_SUCCESS(rval)) { 495 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 496 "unable to make login pdu", icp->conn_oid); 497 goto iscsi_login_done; 498 } 499 500 mutex_enter(&icp->conn_login_mutex); 501 /* 502 * Make sure we are still in LOGIN_START or LOGIN_RX 503 * state before switching to LOGIN_TX. It's possible 504 * for a connection failure to move us to LOGIN_ERROR 505 * before we get to this point. 506 */ 507 if (((icp->conn_login_state != LOGIN_READY) && 508 (icp->conn_login_state != LOGIN_RX)) || 509 !icp->conn_state_idm_connected) { 510 /* Error occurred */ 511 mutex_exit(&icp->conn_login_mutex); 512 rval = (ISCSI_STATUS_INTERNAL_ERROR); 513 goto iscsi_login_done; 514 } 515 516 icp->conn_login_resp_hdr.opcode = 0; 517 iscsi_login_update_state_locked(icp, LOGIN_TX); 518 icp->conn_login_data = data; 519 icp->conn_login_max_data_length = max_data_length; 520 521 /* 522 * send a PDU to the target. This is asynchronous but 523 * we don't have any particular need for a TX completion 524 * notification since we are going to block waiting for the 525 * receive. 526 */ 527 response_timeout = ddi_get_lbolt() + 528 SEC_TO_TICK(icp->conn_tunable_params. 529 recv_login_rsp_timeout); 530 idm_pdu_tx(text_pdu); 531 532 /* 533 * Wait for login failure indication or login RX. 534 * Handler for login response PDU will copy any data into 535 * the buffer pointed to by icp->conn_login_data 536 */ 537 while (icp->conn_login_state == LOGIN_TX) { 538 timeout_result = cv_timedwait(&icp->conn_login_cv, 539 &icp->conn_login_mutex, response_timeout); 540 if (timeout_result == -1) 541 break; 542 } 543 544 /* 545 * We have either received a login response or the connection 546 * has gone down or both. If a login response is present, 547 * then process it. 548 */ 549 ilrhp = (iscsi_login_rsp_hdr_t *)&icp->conn_login_resp_hdr; 550 if (icp->conn_login_state != LOGIN_RX && ilrhp->opcode == 0) { 551 /* connection down, with no login response */ 552 mutex_exit(&icp->conn_login_mutex); 553 rval = (ISCSI_STATUS_INTERNAL_ERROR); 554 goto iscsi_login_done; 555 } 556 mutex_exit(&icp->conn_login_mutex); 557 558 /* check the PDU response type */ 559 if (ilrhp->opcode != ISCSI_OP_LOGIN_RSP) { 560 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 561 "received invalid login response (0x%02x)", 562 icp->conn_oid, ilrhp->opcode); 563 rval = (ISCSI_STATUS_PROTOCOL_ERROR); 564 goto iscsi_login_done; 565 } 566 567 /* 568 * give the caller the status class and detail from the 569 * last login response PDU received 570 */ 571 if (status_class) { 572 *status_class = ilrhp->status_class; 573 } 574 if (status_detail) { 575 *status_detail = ilrhp->status_detail; 576 } 577 578 switch (ilrhp->status_class) { 579 case ISCSI_STATUS_CLASS_SUCCESS: 580 /* 581 * process this response and possibly continue 582 * sending PDUs 583 */ 584 rval = iscsi_process_login_response(icp, 585 ilrhp, (char *)icp->conn_login_data, 586 icp->conn_login_max_data_length); 587 /* pass back whatever error we discovered */ 588 if (!ISCSI_SUCCESS(rval)) { 589 if (ISCSI_LOGIN_TRANSIT_FFP(ilrhp->flags)) { 590 /* 591 * iSCSI connection transit to next 592 * FFP stage while iscsi params 593 * ngeotiate error, LOGIN_ERROR 594 * marked so CN_FFP_ENABLED can 595 * be fully handled before 596 * CN_FFP_DISABLED can be processed. 597 */ 598 iscsi_login_update_state(icp, 599 LOGIN_ERROR); 600 } 601 goto iscsi_login_done; 602 } 603 604 break; 605 case ISCSI_STATUS_CLASS_REDIRECT: 606 /* 607 * we need to process this response to get the 608 * TargetAddress of the redirect, but we don't 609 * care about the return code. 610 */ 611 (void) iscsi_process_login_response(icp, 612 ilrhp, (char *)icp->conn_login_data, 613 icp->conn_login_max_data_length); 614 rval = ISCSI_STATUS_SUCCESS; 615 goto iscsi_login_done; 616 case ISCSI_STATUS_CLASS_INITIATOR_ERR: 617 if (ilrhp->status_detail == 618 ISCSI_LOGIN_STATUS_AUTH_FAILED) { 619 cmn_err(CE_WARN, "iscsi connection(%u) login " 620 "failed - login failed to authenticate " 621 "with target", icp->conn_oid); 622 } 623 rval = ISCSI_STATUS_SUCCESS; 624 goto iscsi_login_done; 625 default: 626 /* 627 * some sort of error, login terminated unsuccessfully, 628 * though this function did it's job. the caller must 629 * check the status_class and status_detail and decide 630 * what to do next. 631 */ 632 rval = ISCSI_STATUS_SUCCESS; 633 goto iscsi_login_done; 634 } 635 636 } while (icp->conn_current_stage != ISCSI_FULL_FEATURE_PHASE); 637 638 rval = ISCSI_STATUS_SUCCESS; 639 640 iscsi_login_done: 641 if (auth_client) { 642 if (iscsiAuthClientFinish(auth_client) != 643 iscsiAuthStatusNoError) { 644 cmn_err(CE_WARN, "iscsi connection(%u) login " 645 "failed - login failed to authenticate " 646 "with target", icp->conn_oid); 647 if (ISCSI_SUCCESS(rval)) 648 rval = ISCSI_STATUS_INTERNAL_ERROR; 649 } 650 } 651 652 icp->conn_login_status = rval; 653 if (ISCSI_SUCCESS(rval) && 654 (*status_class == ISCSI_STATUS_CLASS_SUCCESS)) { 655 mutex_enter(&icp->conn_state_mutex); 656 while (!icp->conn_state_ffp) 657 cv_wait(&icp->conn_state_change, 658 &icp->conn_state_mutex); 659 mutex_exit(&icp->conn_state_mutex); 660 } else { 661 iscsi_login_disconnect(icp); 662 } 663 664 iscsi_login_update_state(icp, LOGIN_DONE); 665 666 return (rval); 667 } 668 669 670 /* 671 * iscsi_make_login_pdu - 672 * 673 */ 674 static iscsi_status_t 675 iscsi_make_login_pdu(iscsi_conn_t *icp, idm_pdu_t *text_pdu, 676 char *data, int max_data_length) 677 { 678 struct iscsi_sess *isp = NULL; 679 int transit = 0; 680 iscsi_hdr_t *ihp = text_pdu->isp_hdr; 681 iscsi_login_hdr_t *ilhp = 682 (iscsi_login_hdr_t *)text_pdu->isp_hdr; 683 IscsiAuthClient *auth_client = NULL; 684 int keytype = 0; 685 int rc = 0; 686 char value[iscsiAuthStringMaxLength]; 687 688 ASSERT(icp != NULL); 689 ASSERT(text_pdu != NULL); 690 isp = icp->conn_sess; 691 ASSERT(isp != NULL); 692 693 auth_client = 694 (isp->sess_auth.auth_buffers && isp->sess_auth.num_auth_buffers) ? 695 (IscsiAuthClient *)isp->sess_auth.auth_buffers[0].address : NULL; 696 697 /* 698 * initialize the PDU header 699 */ 700 bzero(ilhp, sizeof (*ilhp)); 701 ilhp->opcode = ISCSI_OP_LOGIN_CMD | ISCSI_OP_IMMEDIATE; 702 ilhp->cid = icp->conn_cid; 703 bcopy(&isp->sess_isid[0], &ilhp->isid[0], sizeof (isp->sess_isid)); 704 ilhp->tsid = 0; 705 706 /* 707 * Set data buffer pointer. The calls to iscsi_add_text will update the 708 * data length. 709 */ 710 text_pdu->isp_data = (uint8_t *)data; 711 712 /* don't increment on immediate */ 713 ilhp->cmdsn = htonl(isp->sess_cmdsn); 714 715 ilhp->min_version = ISCSI_DRAFT20_VERSION; 716 ilhp->max_version = ISCSI_DRAFT20_VERSION; 717 718 /* 719 * we have to send 0 until full-feature stage 720 */ 721 ilhp->expstatsn = htonl(icp->conn_expstatsn); 722 723 /* 724 * the very first Login PDU has some additional requirements, 725 * * and we need to decide what stage to start in. 726 */ 727 if (icp->conn_current_stage == ISCSI_INITIAL_LOGIN_STAGE) { 728 if ((isp->sess_hba->hba_name) && 729 (isp->sess_hba->hba_name[0])) { 730 if (!iscsi_add_text(text_pdu, max_data_length, 731 "InitiatorName", 732 (char *)isp->sess_hba->hba_name)) { 733 return (ISCSI_STATUS_INTERNAL_ERROR); 734 } 735 } else { 736 cmn_err(CE_WARN, "iscsi connection(%u) login " 737 "failed - initiator name is required", 738 icp->conn_oid); 739 return (ISCSI_STATUS_INTERNAL_ERROR); 740 } 741 742 if ((isp->sess_hba->hba_alias) && 743 (isp->sess_hba->hba_alias[0])) { 744 if (!iscsi_add_text(text_pdu, max_data_length, 745 "InitiatorAlias", 746 (char *)isp->sess_hba->hba_alias)) { 747 return (ISCSI_STATUS_INTERNAL_ERROR); 748 } 749 } 750 751 if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 752 if (isp->sess_name[0] != '\0') { 753 if (!iscsi_add_text(text_pdu, max_data_length, 754 "TargetName", (char *)isp->sess_name)) { 755 return (ISCSI_STATUS_INTERNAL_ERROR); 756 } 757 } 758 759 if (!iscsi_add_text(text_pdu, max_data_length, 760 "SessionType", "Normal")) { 761 return (ISCSI_STATUS_INTERNAL_ERROR); 762 } 763 } else if (isp->sess_type == ISCSI_SESS_TYPE_DISCOVERY) { 764 if (!iscsi_add_text(text_pdu, max_data_length, 765 "SessionType", "Discovery")) { 766 return (ISCSI_STATUS_INTERNAL_ERROR); 767 } 768 } else { 769 return (ISCSI_STATUS_INTERNAL_ERROR); 770 } 771 772 if (auth_client) { 773 /* we're prepared to do authentication */ 774 icp->conn_current_stage = 775 ISCSI_SECURITY_NEGOTIATION_STAGE; 776 } else { 777 /* can't do any authentication, skip that stage */ 778 icp->conn_current_stage = 779 ISCSI_OP_PARMS_NEGOTIATION_STAGE; 780 } 781 } 782 783 /* 784 * fill in text based on the stage 785 */ 786 switch (icp->conn_current_stage) { 787 case ISCSI_OP_PARMS_NEGOTIATION_STAGE: 788 /* 789 * we always try to go from op params to full 790 * feature stage 791 */ 792 icp->conn_next_stage = ISCSI_FULL_FEATURE_PHASE; 793 transit = 1; 794 795 /* 796 * The terminology here may have gotten dated. A partial 797 * response is a login response that doesn't complete a 798 * login. If we haven't gotten a partial response, then 799 * either we shouldn't be here, or we just switched to 800 * this stage, and need to start offering keys. 801 */ 802 if (!icp->conn_partial_response) { 803 /* 804 * request the desired settings the first time 805 * we are in this stage 806 */ 807 switch (icp->conn_params.header_digest) { 808 case ISCSI_DIGEST_NONE: 809 if (!iscsi_add_text(text_pdu, 810 max_data_length, "HeaderDigest", "None")) { 811 return (ISCSI_STATUS_INTERNAL_ERROR); 812 } 813 break; 814 case ISCSI_DIGEST_CRC32C: 815 if (!iscsi_add_text(text_pdu, 816 max_data_length, 817 "HeaderDigest", "CRC32C")) { 818 return (ISCSI_STATUS_INTERNAL_ERROR); 819 } 820 break; 821 case ISCSI_DIGEST_CRC32C_NONE: 822 if (!iscsi_add_text(text_pdu, 823 max_data_length, "HeaderDigest", 824 "CRC32C,None")) { 825 return (ISCSI_STATUS_INTERNAL_ERROR); 826 } 827 break; 828 default: 829 case ISCSI_DIGEST_NONE_CRC32C: 830 if (!iscsi_add_text(text_pdu, 831 max_data_length, "HeaderDigest", 832 "None,CRC32C")) { 833 return (ISCSI_STATUS_INTERNAL_ERROR); 834 } 835 break; 836 } 837 838 switch (icp->conn_params.data_digest) { 839 case ISCSI_DIGEST_NONE: 840 if (!iscsi_add_text(text_pdu, 841 max_data_length, "DataDigest", "None")) { 842 return (ISCSI_STATUS_INTERNAL_ERROR); 843 } 844 break; 845 case ISCSI_DIGEST_CRC32C: 846 if (!iscsi_add_text(text_pdu, 847 max_data_length, "DataDigest", "CRC32C")) { 848 return (ISCSI_STATUS_INTERNAL_ERROR); 849 } 850 break; 851 case ISCSI_DIGEST_CRC32C_NONE: 852 if (!iscsi_add_text(text_pdu, 853 max_data_length, "DataDigest", 854 "CRC32C,None")) { 855 return (ISCSI_STATUS_INTERNAL_ERROR); 856 } 857 break; 858 default: 859 case ISCSI_DIGEST_NONE_CRC32C: 860 if (!iscsi_add_text(text_pdu, 861 max_data_length, "DataDigest", 862 "None,CRC32C")) { 863 return (ISCSI_STATUS_INTERNAL_ERROR); 864 } 865 break; 866 } 867 868 (void) sprintf(value, "%d", 869 icp->conn_params.max_recv_data_seg_len); 870 if (!iscsi_add_text(text_pdu, max_data_length, 871 "MaxRecvDataSegmentLength", value)) { 872 return (ISCSI_STATUS_INTERNAL_ERROR); 873 } 874 875 (void) sprintf(value, "%d", 876 icp->conn_params.default_time_to_wait); 877 if (!iscsi_add_text(text_pdu, 878 max_data_length, "DefaultTime2Wait", value)) { 879 return (ISCSI_STATUS_INTERNAL_ERROR); 880 } 881 882 (void) sprintf(value, "%d", 883 icp->conn_params.default_time_to_retain); 884 if (!iscsi_add_text(text_pdu, 885 max_data_length, "DefaultTime2Retain", value)) { 886 return (ISCSI_STATUS_INTERNAL_ERROR); 887 } 888 889 (void) sprintf(value, "%d", 890 icp->conn_params.error_recovery_level); 891 if (!iscsi_add_text(text_pdu, 892 max_data_length, "ErrorRecoveryLevel", "0")) { 893 return (ISCSI_STATUS_INTERNAL_ERROR); 894 } 895 896 if (!iscsi_add_text(text_pdu, 897 max_data_length, "IFMarker", 898 icp->conn_params.ifmarker ? "Yes" : "No")) { 899 return (ISCSI_STATUS_INTERNAL_ERROR); 900 } 901 902 if (!iscsi_add_text(text_pdu, 903 max_data_length, "OFMarker", 904 icp->conn_params.ofmarker ? "Yes" : "No")) { 905 return (ISCSI_STATUS_INTERNAL_ERROR); 906 } 907 908 /* 909 * The following login parameters are "Irrelevant" 910 * for discovery sessions 911 */ 912 if (isp->sess_type != ISCSI_SESS_TYPE_DISCOVERY) { 913 914 if (!iscsi_add_text(text_pdu, 915 max_data_length, "InitialR2T", 916 icp->conn_params.initial_r2t ? 917 "Yes" : "No")) { 918 return (ISCSI_STATUS_INTERNAL_ERROR); 919 } 920 921 if (!iscsi_add_text(text_pdu, 922 max_data_length, "ImmediateData", 923 icp->conn_params.immediate_data ? 924 "Yes" : "No")) { 925 return (ISCSI_STATUS_INTERNAL_ERROR); 926 } 927 928 (void) sprintf(value, "%d", 929 icp->conn_params.max_burst_length); 930 if (!iscsi_add_text(text_pdu, 931 max_data_length, "MaxBurstLength", value)) { 932 return (ISCSI_STATUS_INTERNAL_ERROR); 933 } 934 935 (void) sprintf(value, "%d", 936 icp->conn_params.first_burst_length); 937 if (!iscsi_add_text(text_pdu, max_data_length, 938 "FirstBurstLength", value)) { 939 return (ISCSI_STATUS_INTERNAL_ERROR); 940 } 941 942 (void) sprintf(value, "%d", 943 icp->conn_params.max_outstanding_r2t); 944 if (!iscsi_add_text(text_pdu, max_data_length, 945 "MaxOutstandingR2T", value)) { 946 return (ISCSI_STATUS_INTERNAL_ERROR); 947 } 948 949 (void) sprintf(value, "%d", 950 icp->conn_params.max_connections); 951 if (!iscsi_add_text(text_pdu, max_data_length, 952 "MaxConnections", value)) { 953 return (ISCSI_STATUS_INTERNAL_ERROR); 954 } 955 956 if (!iscsi_add_text(text_pdu, 957 max_data_length, "DataPDUInOrder", 958 icp->conn_params.data_pdu_in_order ? 959 "Yes" : "No")) { 960 return (ISCSI_STATUS_INTERNAL_ERROR); 961 } 962 963 if (!iscsi_add_text(text_pdu, 964 max_data_length, "DataSequenceInOrder", 965 icp->conn_params.data_sequence_in_order ? 966 "Yes" : "No")) { 967 return (ISCSI_STATUS_INTERNAL_ERROR); 968 } 969 } 970 } 971 break; 972 973 case ISCSI_SECURITY_NEGOTIATION_STAGE: 974 keytype = iscsiAuthKeyTypeNone; 975 rc = iscsiAuthClientSendTransitBit(auth_client, &transit); 976 977 /* 978 * see if we're ready for a stage change 979 */ 980 if (rc == iscsiAuthStatusNoError) { 981 if (transit) { 982 icp->conn_next_stage = 983 ISCSI_OP_PARMS_NEGOTIATION_STAGE; 984 } else { 985 icp->conn_next_stage = 986 ISCSI_SECURITY_NEGOTIATION_STAGE; 987 } 988 } else { 989 return (ISCSI_STATUS_INTERNAL_ERROR); 990 } 991 992 /* 993 * enumerate all the keys the auth code might want to send 994 */ 995 while (iscsiAuthClientGetNextKeyType(&keytype) == 996 iscsiAuthStatusNoError) { 997 int present = 0; 998 char *key = (char *)iscsiAuthClientGetKeyName(keytype); 999 int key_length = key ? strlen(key) : 0; 1000 int pdu_length = text_pdu->isp_datalen; 1001 char *auth_value = data + pdu_length + key_length + 1; 1002 unsigned int max_length = max_data_length - 1003 (pdu_length + key_length + 1); 1004 1005 /* 1006 * add the key/value pairs the auth code wants to 1007 * send directly to the PDU, since they could in 1008 * theory be large. 1009 */ 1010 rc = iscsiAuthClientSendKeyValue(auth_client, keytype, 1011 &present, auth_value, max_length); 1012 if ((rc == iscsiAuthStatusNoError) && present) { 1013 /* 1014 * actually fill in the key 1015 */ 1016 (void) strncpy(&data[pdu_length], key, 1017 key_length); 1018 pdu_length += key_length; 1019 data[pdu_length] = '='; 1020 pdu_length++; 1021 /* 1022 * adjust the PDU's data segment length to 1023 * include the value and trailing NULL 1024 */ 1025 pdu_length += strlen(auth_value) + 1; 1026 text_pdu->isp_datalen = pdu_length; 1027 hton24(ihp->dlength, pdu_length); 1028 } 1029 } 1030 1031 break; 1032 case ISCSI_FULL_FEATURE_PHASE: 1033 cmn_err(CE_WARN, "iscsi connection(%u) login " 1034 "failed - can't send login in full feature stage", 1035 icp->conn_oid); 1036 return (ISCSI_STATUS_INTERNAL_ERROR); 1037 default: 1038 cmn_err(CE_WARN, "iscsi connection(%u) login " 1039 "failed - can't send login in unknown stage (%d)", 1040 icp->conn_oid, icp->conn_current_stage); 1041 return (ISCSI_STATUS_INTERNAL_ERROR); 1042 } 1043 1044 /* fill in the flags */ 1045 ilhp->flags = icp->conn_current_stage << 2; 1046 if (transit) { 1047 /* transit to the next stage */ 1048 ilhp->flags |= icp->conn_next_stage; 1049 ilhp->flags |= ISCSI_FLAG_LOGIN_TRANSIT; 1050 } else { 1051 /* next == current */ 1052 ilhp->flags |= icp->conn_current_stage; 1053 } 1054 1055 return (ISCSI_STATUS_SUCCESS); 1056 } 1057 1058 1059 /* 1060 * iscsi_process_login_response - This assumes the text data is 1061 * always NUL terminated. The caller can always arrange for that by 1062 * using a slightly larger buffer than the max PDU size, and then 1063 * appending a NUL to the PDU. 1064 */ 1065 static iscsi_status_t 1066 iscsi_process_login_response(iscsi_conn_t *icp, 1067 iscsi_login_rsp_hdr_t *ilrhp, char *data, int max_data_length) 1068 { 1069 iscsi_sess_t *isp = NULL; 1070 IscsiAuthClient *auth_client = NULL; 1071 int transit = 0; 1072 char *text = data; 1073 char *end = NULL; 1074 int pdu_current_stage = 0; 1075 int pdu_next_stage = 0; 1076 int debug_status = 0; 1077 unsigned long tmp; 1078 char *tmpe; 1079 boolean_t fbl_irrelevant = B_FALSE; 1080 1081 ASSERT(icp != NULL); 1082 ASSERT(ilrhp != NULL); 1083 ASSERT(data != NULL); 1084 isp = icp->conn_sess; 1085 ASSERT(isp != NULL); 1086 1087 auth_client = 1088 (isp->sess_auth.auth_buffers && isp->sess_auth.num_auth_buffers) ? 1089 (IscsiAuthClient *) isp->sess_auth.auth_buffers[0].address : NULL; 1090 transit = ilrhp->flags & ISCSI_FLAG_LOGIN_TRANSIT; 1091 1092 /* verify the initial buffer was big enough to hold everything */ 1093 end = text + ntoh24(ilrhp->dlength) + 1; 1094 if (end >= (data + max_data_length)) { 1095 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1096 "buffer too small", icp->conn_oid); 1097 return (ISCSI_STATUS_INTERNAL_ERROR); 1098 } 1099 *end = '\0'; 1100 1101 /* if the response status was success, sanity check the response */ 1102 if (ilrhp->status_class == ISCSI_STATUS_CLASS_SUCCESS) { 1103 /* check the active version */ 1104 if (ilrhp->active_version != ISCSI_DRAFT20_VERSION) { 1105 cmn_err(CE_WARN, "iscsi connection(%u) login " 1106 "failed - target version incompatible " 1107 "received:0x%0x2x expected:0x%02x", 1108 icp->conn_oid, ilrhp->active_version, 1109 ISCSI_DRAFT20_VERSION); 1110 return (ISCSI_STATUS_VERSION_MISMATCH); 1111 } 1112 1113 /* make sure the current stage matches */ 1114 pdu_current_stage = (ilrhp->flags & 1115 ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2; 1116 if (pdu_current_stage != icp->conn_current_stage) { 1117 cmn_err(CE_WARN, "iscsi connection(%u) login " 1118 "failed - login response contained invalid " 1119 "stage %d", icp->conn_oid, pdu_current_stage); 1120 return (ISCSI_STATUS_PROTOCOL_ERROR); 1121 } 1122 1123 /* 1124 * Make sure that we're actually advancing 1125 * if the T-bit is set 1126 */ 1127 pdu_next_stage = ilrhp->flags & 1128 ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; 1129 if (transit && (pdu_next_stage <= icp->conn_current_stage)) { 1130 cmn_err(CE_WARN, "iscsi connection(%u) login " 1131 "failed - login response wants to go to stage " 1132 "%d, but we want stage %d", icp->conn_oid, 1133 pdu_next_stage, icp->conn_next_stage); 1134 return (ISCSI_STATUS_PROTOCOL_ERROR); 1135 } 1136 } 1137 1138 if (icp->conn_current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE) { 1139 if (iscsiAuthClientRecvBegin(auth_client) != 1140 iscsiAuthStatusNoError) { 1141 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1142 "authentication receive failed", icp->conn_oid); 1143 return (ISCSI_STATUS_INTERNAL_ERROR); 1144 } 1145 1146 if (iscsiAuthClientRecvTransitBit(auth_client, 1147 transit) != iscsiAuthStatusNoError) { 1148 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1149 "authentication transmit failed", icp->conn_oid); 1150 return (ISCSI_STATUS_INTERNAL_ERROR); 1151 } 1152 } 1153 1154 /* 1155 * scan the text data 1156 */ 1157 more_text: 1158 while (text && (text < end)) { 1159 char *value = NULL; 1160 char *value_end = NULL; 1161 1162 /* 1163 * skip any NULs separating each text key=value pair 1164 */ 1165 while ((text < end) && (*text == '\0')) { 1166 text++; 1167 } 1168 if (text >= end) { 1169 break; 1170 } 1171 1172 /* 1173 * handle keys appropriate for each stage 1174 */ 1175 switch (icp->conn_current_stage) { 1176 case ISCSI_SECURITY_NEGOTIATION_STAGE: 1177 /* 1178 * a few keys are possible in Security stage 1179 * * which the auth code doesn't care about, 1180 * * but which we might want to see, or at 1181 * * least not choke on. 1182 */ 1183 if (iscsi_find_key_value("TargetAlias", 1184 text, end, &value, &value_end)) { 1185 isp->sess_alias_length = 1186 sizeof (isp->sess_alias) - 1; 1187 1188 if ((value_end - value) < 1189 isp->sess_alias_length) { 1190 isp->sess_alias_length = 1191 value_end - value; 1192 } 1193 1194 bcopy(value, isp->sess_alias, 1195 isp->sess_alias_length); 1196 isp->sess_alias[isp->sess_alias_length + 1] = 1197 '\0'; 1198 text = value_end; 1199 1200 } else if (iscsi_find_key_value("TargetAddress", 1201 text, end, &value, &value_end)) { 1202 if (!ISCSI_SUCCESS(iscsi_update_address( 1203 icp, value))) { 1204 cmn_err(CE_WARN, "iscsi connection(%u) " 1205 "login failed - login redirection " 1206 "invalid", icp->conn_oid); 1207 return (ISCSI_STATUS_PROTOCOL_ERROR); 1208 } 1209 text = value_end; 1210 } else if (iscsi_find_key_value("TargetPortalGroupTag", 1211 text, end, &value, &value_end)) { 1212 /* 1213 * We should have already obtained this via 1214 * discovery. We've already picked an isid, 1215 * so the most we can do is confirm we reached 1216 * the portal group we were expecting to. 1217 */ 1218 if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1219 return (ISCSI_STATUS_PROTOCOL_ERROR); 1220 } 1221 if (isp->sess_tpgt_conf != ISCSI_DEFAULT_TPGT) { 1222 if (tmp != isp->sess_tpgt_conf) { 1223 1224 cmn_err(CE_WARN, "iscsi connection(%u) login failed - target " 1225 "protocol group tag mismatch, expected %d, received %lu", 1226 icp->conn_oid, isp->sess_tpgt_conf, tmp); 1227 return (ISCSI_STATUS_LOGIN_TPGT_NEGO_FAIL); 1228 1229 } 1230 } 1231 isp->sess_tpgt_nego = (int)tmp; 1232 text = value_end; 1233 } else { 1234 /* 1235 * any key we don't recognize either goes 1236 * to the auth code, or we choke on it 1237 */ 1238 int keytype = iscsiAuthKeyTypeNone; 1239 1240 while (iscsiAuthClientGetNextKeyType( 1241 &keytype) == iscsiAuthStatusNoError) { 1242 1243 char *key = 1244 (char *)iscsiAuthClientGetKeyName( 1245 keytype); 1246 1247 if ((key) && 1248 (iscsi_find_key_value(key, 1249 text, end, &value, &value_end))) { 1250 1251 if (iscsiAuthClientRecvKeyValue 1252 (auth_client, keytype, 1253 value) != 1254 iscsiAuthStatusNoError) { 1255 1256 cmn_err(CE_WARN, "iscsi connection(%u) login failed - can't accept " 1257 "%s in security stage", icp->conn_oid, text); 1258 return (ISCSI_STATUS_NEGO_FAIL); 1259 1260 } 1261 text = value_end; 1262 goto more_text; 1263 } 1264 } 1265 1266 cmn_err(CE_WARN, "iscsi connection(%u) login failed - can't except " 1267 "%s in security stage", icp->conn_oid, text); 1268 1269 return (ISCSI_STATUS_NEGO_FAIL); 1270 } 1271 break; 1272 case ISCSI_OP_PARMS_NEGOTIATION_STAGE: 1273 if (iscsi_find_key_value("TargetAlias", text, 1274 end, &value, &value_end)) { 1275 isp->sess_alias_length = 1276 sizeof (isp->sess_alias) - 1; 1277 1278 if ((value_end - value) < 1279 isp->sess_alias_length) { 1280 isp->sess_alias_length = 1281 value_end - value; 1282 } 1283 1284 bcopy(value, isp->sess_alias, 1285 isp->sess_alias_length); 1286 isp->sess_alias[isp->sess_alias_length + 1] = 1287 '\0'; 1288 text = value_end; 1289 1290 } else if (iscsi_find_key_value("TargetAddress", 1291 text, end, &value, &value_end)) { 1292 if (!ISCSI_SUCCESS(iscsi_update_address( 1293 icp, value))) { 1294 1295 cmn_err(CE_WARN, "iscsi connection(%u) login failed - login " 1296 "redirection invalid", icp->conn_oid); 1297 1298 return (ISCSI_STATUS_PROTOCOL_ERROR); 1299 } 1300 text = value_end; 1301 } else if (iscsi_find_key_value("TargetPortalGroupTag", 1302 text, end, &value, &value_end)) { 1303 /* 1304 * We should have already obtained this via 1305 * discovery. We've already picked an isid, 1306 * so the most we can do is confirm we reached 1307 * the portal group we were expecting to. 1308 */ 1309 if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1310 return (ISCSI_STATUS_PROTOCOL_ERROR); 1311 } 1312 if (isp->sess_tpgt_conf != ISCSI_DEFAULT_TPGT) { 1313 if (tmp != isp->sess_tpgt_conf) { 1314 1315 cmn_err(CE_WARN, "iscsi connection(%u) login failed - target portal " 1316 "tag mismatch, expected:%d received:%lu", icp->conn_oid, 1317 isp->sess_tpgt_conf, tmp); 1318 return (ISCSI_STATUS_LOGIN_TPGT_NEGO_FAIL); 1319 1320 } 1321 } 1322 isp->sess_tpgt_nego = (int)tmp; 1323 text = value_end; 1324 1325 } else if (iscsi_find_key_value("InitialR2T", 1326 text, end, &value, &value_end)) { 1327 1328 /* 1329 * iSCSI RFC section 12.10 states that 1330 * InitialR2T is Irrelevant for a 1331 * discovery session. 1332 */ 1333 if (isp->sess_type == 1334 ISCSI_SESS_TYPE_DISCOVERY) { 1335 /* EMPTY */ 1336 } else if (value == NULL) { 1337 cmn_err(CE_WARN, "iscsi connection(%u) " 1338 "login failed - InitialR2T is " 1339 "invalid - protocol error", 1340 icp->conn_oid); 1341 return (ISCSI_STATUS_PROTOCOL_ERROR); 1342 } else if (strcmp(value, "Yes") == 0) { 1343 icp->conn_params.initial_r2t = B_TRUE; 1344 } else if (strcmp(value, "No") == 0) { 1345 icp->conn_params.initial_r2t = B_FALSE; 1346 } else { 1347 cmn_err(CE_WARN, "iscsi connection(%u) " 1348 "login failed - InitialR2T is " 1349 "invalid - protocol error", 1350 icp->conn_oid); 1351 return (ISCSI_STATUS_PROTOCOL_ERROR); 1352 } 1353 text = value_end; 1354 1355 } else if (iscsi_find_key_value("ImmediateData", 1356 text, end, &value, &value_end)) { 1357 1358 /* 1359 * iSCSI RFC section 12.11 states that 1360 * ImmediateData is Irrelevant for a 1361 * discovery session. 1362 */ 1363 if (isp->sess_type == 1364 ISCSI_SESS_TYPE_DISCOVERY) { 1365 /* EMPTY */ 1366 } else if (value == NULL) { 1367 cmn_err(CE_WARN, "iscsi connection(%u) " 1368 "login failed - ImmediateData is " 1369 "invalid - protocol error", 1370 icp->conn_oid); 1371 return (ISCSI_STATUS_PROTOCOL_ERROR); 1372 } else if (strcmp(value, "Yes") == 0) { 1373 icp->conn_params.immediate_data = 1; 1374 } else if (strcmp(value, "No") == 0) { 1375 icp->conn_params.immediate_data = 0; 1376 } else { 1377 cmn_err(CE_WARN, "iscsi connection(%u) " 1378 "login failed - ImmediateData is " 1379 "invalid - protocol error", 1380 icp->conn_oid); 1381 return (ISCSI_STATUS_PROTOCOL_ERROR); 1382 } 1383 text = value_end; 1384 1385 } else if (iscsi_find_key_value( 1386 "MaxRecvDataSegmentLength", text, end, 1387 &value, &value_end)) { 1388 1389 if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1390 cmn_err(CE_WARN, "iscsi connection(%u) " 1391 "login failed - MaxRecvDataSegment" 1392 "Length is invalid - protocol " 1393 "error", icp->conn_oid); 1394 return (ISCSI_STATUS_NEGO_FAIL); 1395 } 1396 icp->conn_params.max_recv_data_seg_len = 1397 icp->conn_params.max_xmit_data_seg_len = 1398 (int)tmp; 1399 1400 text = value_end; 1401 } else if (iscsi_find_key_value("FirstBurstLength", 1402 text, end, &value, &value_end)) { 1403 1404 /* 1405 * iSCSI RFC section 12.14 states that 1406 * FirstBurstLength is Irrelevant if 1407 * InitialR2T=Yes and ImmediateData=No 1408 * or is this is a discovery session. 1409 */ 1410 if ((isp->sess_type == 1411 ISCSI_SESS_TYPE_DISCOVERY)) { 1412 /* EMPTY */ 1413 } else if (value && 1414 (strcmp(value, "Irrelevant") == 0)) { 1415 /* irrelevant */ 1416 fbl_irrelevant = B_TRUE; 1417 } else if (ddi_strtoul( 1418 value, &tmpe, 0, &tmp) != 0) { 1419 /* bad value */ 1420 cmn_err(CE_WARN, "iscsi connection(%u) " 1421 "login failed - FirstBurstLength" 1422 "is invalid - protocol error", 1423 icp->conn_oid); 1424 return (ISCSI_STATUS_PROTOCOL_ERROR); 1425 } else { 1426 /* good value */ 1427 icp->conn_params.first_burst_length = 1428 (int)tmp; 1429 } 1430 text = value_end; 1431 } else if (iscsi_find_key_value("MaxBurstLength", 1432 text, end, &value, &value_end)) { 1433 /* 1434 * iSCSI RFC section 12.13 states that 1435 * MaxBurstLength is Irrelevant for a 1436 * discovery session. 1437 */ 1438 if (isp->sess_type == 1439 ISCSI_SESS_TYPE_DISCOVERY) { 1440 /* EMPTY */ 1441 } else if (ddi_strtoul( 1442 value, &tmpe, 0, &tmp) != 0) { 1443 cmn_err(CE_WARN, "iscsi connection(%u) " 1444 "login failed - MaxBurstLength" 1445 "is invalid - protocol error", 1446 icp->conn_oid); 1447 return (ISCSI_STATUS_PROTOCOL_ERROR); 1448 } else { 1449 icp->conn_params.max_burst_length = 1450 (int)tmp; 1451 } 1452 1453 text = value_end; 1454 1455 } else if (iscsi_find_key_value("HeaderDigest", 1456 text, end, &value, &value_end)) { 1457 1458 if (strcmp(value, "None") == 0) { 1459 if (icp->conn_params.header_digest != 1460 ISCSI_DIGEST_CRC32C) { 1461 icp->conn_params.header_digest = 1462 ISCSI_DIGEST_NONE; 1463 } else { 1464 cmn_err(CE_WARN, "iscsi " 1465 "connection(%u) login " 1466 "failed - HeaderDigest=" 1467 "CRC32 is required, can't " 1468 "accept %s", 1469 icp->conn_oid, text); 1470 return (ISCSI_STATUS_NEGO_FAIL); 1471 } 1472 } else if (strcmp(value, "CRC32C") == 0) { 1473 if (icp->conn_params.header_digest != 1474 ISCSI_DIGEST_NONE) { 1475 icp->conn_params.header_digest = 1476 ISCSI_DIGEST_CRC32C; 1477 } else { 1478 cmn_err(CE_WARN, "iscsi " 1479 "connection(%u) login " 1480 "failed - HeaderDigest=" 1481 "None is required, can't " 1482 "accept %s", 1483 icp->conn_oid, text); 1484 return (ISCSI_STATUS_NEGO_FAIL); 1485 } 1486 } else { 1487 cmn_err(CE_WARN, "iscsi connection(%u) " 1488 "login failed - HeaderDigest " 1489 "can't accept %s", icp->conn_oid, 1490 text); 1491 return (ISCSI_STATUS_NEGO_FAIL); 1492 } 1493 text = value_end; 1494 } else if (iscsi_find_key_value("DataDigest", text, 1495 end, &value, &value_end)) { 1496 1497 if (strcmp(value, "None") == 0) { 1498 if (icp->conn_params.data_digest != 1499 ISCSI_DIGEST_CRC32C) { 1500 icp->conn_params.data_digest = 1501 ISCSI_DIGEST_NONE; 1502 } else { 1503 cmn_err(CE_WARN, "iscsi " 1504 "connection(%u) login " 1505 "failed - DataDigest=" 1506 "CRC32C is required, " 1507 "can't accept %s", 1508 icp->conn_oid, text); 1509 return (ISCSI_STATUS_NEGO_FAIL); 1510 } 1511 } else if (strcmp(value, "CRC32C") == 0) { 1512 if (icp->conn_params.data_digest != 1513 ISCSI_DIGEST_NONE) { 1514 icp->conn_params.data_digest = 1515 ISCSI_DIGEST_CRC32C; 1516 } else { 1517 cmn_err(CE_WARN, "iscsi " 1518 "connection(%u) login " 1519 "failed - DataDigest=None " 1520 "is required, can't " 1521 "accept %s", 1522 icp->conn_oid, text); 1523 return (ISCSI_STATUS_NEGO_FAIL); 1524 } 1525 } else { 1526 cmn_err(CE_WARN, "iscsi connection(%u) " 1527 "login failed - can't accept %s", 1528 icp->conn_oid, text); 1529 return (ISCSI_STATUS_NEGO_FAIL); 1530 } 1531 text = value_end; 1532 1533 } else if (iscsi_find_key_value("DefaultTime2Wait", 1534 text, end, &value, &value_end)) { 1535 1536 if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1537 cmn_err(CE_WARN, "iscsi connection(%u) " 1538 "login failed - DefaultTime2Wait " 1539 "is invalid - protocol error", 1540 icp->conn_oid); 1541 return (ISCSI_STATUS_PROTOCOL_ERROR); 1542 } 1543 icp->conn_params.default_time_to_wait = 1544 (int)tmp; 1545 1546 text = value_end; 1547 1548 } else if (iscsi_find_key_value("DefaultTime2Retain", 1549 text, end, &value, &value_end)) { 1550 1551 if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1552 cmn_err(CE_WARN, "iscsi connection(%u) " 1553 "login failed - DefaultTime2Retain " 1554 "is invalid - protocol error", 1555 icp->conn_oid); 1556 return (ISCSI_STATUS_PROTOCOL_ERROR); 1557 } 1558 icp->conn_params.default_time_to_retain = 1559 (int)tmp; 1560 1561 text = value_end; 1562 1563 } else if (iscsi_find_key_value("OFMarker", text, 1564 end, &value, &value_end)) { 1565 1566 /* 1567 * result function is AND, target must 1568 * honor our No 1569 */ 1570 text = value_end; 1571 1572 } else if (iscsi_find_key_value("OFMarkInt", text, 1573 end, &value, &value_end)) { 1574 1575 /* 1576 * we don't do markers, so we don't care 1577 */ 1578 text = value_end; 1579 1580 } else if (iscsi_find_key_value("IFMarker", text, 1581 end, &value, &value_end)) { 1582 1583 /* 1584 * result function is AND, target must 1585 * honor our No 1586 */ 1587 text = value_end; 1588 1589 } else if (iscsi_find_key_value("IFMarkInt", text, 1590 end, &value, &value_end)) { 1591 1592 /* 1593 * we don't do markers, so we don't care 1594 */ 1595 text = value_end; 1596 1597 } else if (iscsi_find_key_value("DataPDUInOrder", 1598 text, end, &value, &value_end)) { 1599 1600 /* 1601 * iSCSI RFC section 12.18 states that 1602 * DataPDUInOrder is Irrelevant for a 1603 * discovery session. 1604 */ 1605 if (isp->sess_type == 1606 ISCSI_SESS_TYPE_DISCOVERY) { 1607 /* EMPTY */ 1608 } else if (value == NULL) { 1609 cmn_err(CE_WARN, "iscsi connection(%u) " 1610 "login failed - InitialR2T is " 1611 "invalid - protocol error", 1612 icp->conn_oid); 1613 return (ISCSI_STATUS_PROTOCOL_ERROR); 1614 } else if (strcmp(value, "Yes") == 0) { 1615 icp->conn_params.data_pdu_in_order = 1616 B_TRUE; 1617 } else if (strcmp(value, "No") == 0) { 1618 icp->conn_params.data_pdu_in_order = 1619 B_FALSE; 1620 } else { 1621 cmn_err(CE_WARN, "iscsi connection(%u) " 1622 "login failed - InitialR2T is " 1623 "invalid - protocol error", 1624 icp->conn_oid); 1625 return (ISCSI_STATUS_PROTOCOL_ERROR); 1626 } 1627 text = value_end; 1628 1629 } else if (iscsi_find_key_value("DataSequenceInOrder", 1630 text, end, &value, &value_end)) { 1631 1632 /* 1633 * iSCSI RFC section 12.19 states that 1634 * DataSequenceInOrder is Irrelevant for a 1635 * discovery session. 1636 */ 1637 if (isp->sess_type == 1638 ISCSI_SESS_TYPE_DISCOVERY) { 1639 /* EMPTY */ 1640 } else if (value == NULL) { 1641 cmn_err(CE_WARN, "iscsi connection(%u) " 1642 "login failed - InitialR2T is " 1643 "invalid - protocol error", 1644 icp->conn_oid); 1645 return (ISCSI_STATUS_PROTOCOL_ERROR); 1646 } else if (strcmp(value, "Yes") == 0) { 1647 icp->conn_params. 1648 data_sequence_in_order = B_TRUE; 1649 } else if (strcmp(value, "No") == 0) { 1650 icp->conn_params. 1651 data_sequence_in_order = B_FALSE; 1652 } else { 1653 cmn_err(CE_WARN, "iscsi connection(%u) " 1654 "login failed - InitialR2T is " 1655 "invalid - protocol error", 1656 icp->conn_oid); 1657 return (ISCSI_STATUS_PROTOCOL_ERROR); 1658 } 1659 text = value_end; 1660 1661 } else if (iscsi_find_key_value("MaxOutstandingR2T", 1662 text, end, &value, &value_end)) { 1663 1664 /* 1665 * iSCSI RFC section 12.17 states that 1666 * MaxOutstandingR2T is Irrelevant for a 1667 * discovery session. 1668 */ 1669 if (isp->sess_type == 1670 ISCSI_SESS_TYPE_DISCOVERY) { 1671 /* EMPTY */ 1672 } else if (strcmp(value, "1")) { 1673 cmn_err(CE_WARN, "iscsi connection(%u) " 1674 "login failed - can't accept " 1675 "MaxOutstandingR2T %s", 1676 icp->conn_oid, value); 1677 return (ISCSI_STATUS_NEGO_FAIL); 1678 } 1679 text = value_end; 1680 1681 } else if (iscsi_find_key_value("MaxConnections", 1682 text, end, &value, &value_end)) { 1683 1684 /* 1685 * iSCSI RFC section 12.2 states that 1686 * MaxConnections is Irrelevant for a 1687 * discovery session. 1688 */ 1689 if (isp->sess_type == 1690 ISCSI_SESS_TYPE_DISCOVERY) { 1691 /* EMPTY */ 1692 } else if (strcmp(value, "1")) { 1693 cmn_err(CE_WARN, "iscsi connection(%u) " 1694 "login failed - can't accept " 1695 "MaxConnections %s", 1696 icp->conn_oid, value); 1697 return (ISCSI_STATUS_NEGO_FAIL); 1698 } 1699 text = value_end; 1700 1701 } else if (iscsi_find_key_value("ErrorRecoveryLevel", 1702 text, end, &value, &value_end)) { 1703 1704 if (strcmp(value, "0")) { 1705 1706 cmn_err(CE_WARN, "iscsi connection(%u) " 1707 "login failed - can't accept " 1708 "ErrorRecoveryLevel %s", 1709 icp->conn_oid, value); 1710 return (ISCSI_STATUS_NEGO_FAIL); 1711 } 1712 text = value_end; 1713 1714 } else { 1715 cmn_err(CE_WARN, "iscsi connection(%u) " 1716 "login failed - ignoring login " 1717 "parameter %s", icp->conn_oid, value); 1718 text = value_end; 1719 } 1720 break; 1721 default: 1722 return (ISCSI_STATUS_INTERNAL_ERROR); 1723 } 1724 } 1725 1726 /* 1727 * iSCSI RFC section 12.14 states that 1728 * FirstBurstLength is Irrelevant if 1729 * InitialR2T=Yes and ImmediateData=No. 1730 * This is a final check to make sure 1731 * the array didn't make a protocol 1732 * violation. 1733 */ 1734 if ((fbl_irrelevant == B_TRUE) && 1735 ((icp->conn_params.initial_r2t != B_TRUE) || 1736 (icp->conn_params.immediate_data != B_FALSE))) { 1737 cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1738 "FirstBurstLength=Irrelevant and (InitialR2T!=Yes or " 1739 "ImmediateData!=No) - protocol error", icp->conn_oid); 1740 return (ISCSI_STATUS_PROTOCOL_ERROR); 1741 } 1742 1743 if (icp->conn_current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE) { 1744 switch (iscsiAuthClientRecvEnd(auth_client, iscsi_null_callback, 1745 (void *)isp, NULL)) { 1746 case iscsiAuthStatusContinue: 1747 /* 1748 * continue sending PDUs 1749 */ 1750 break; 1751 1752 case iscsiAuthStatusPass: 1753 break; 1754 1755 case iscsiAuthStatusInProgress: 1756 /* 1757 * this should only occur if we were authenticating the 1758 * target, which we don't do yet, so treat this as an 1759 * error. 1760 */ 1761 case iscsiAuthStatusNoError: 1762 /* 1763 * treat this as an error, since we should get a 1764 * different code 1765 */ 1766 case iscsiAuthStatusError: 1767 case iscsiAuthStatusFail: 1768 default: 1769 debug_status = 0; 1770 1771 if (iscsiAuthClientGetDebugStatus(auth_client, 1772 &debug_status) != iscsiAuthStatusNoError) { 1773 1774 cmn_err(CE_WARN, "iscsi connection(%u) login " 1775 "failed - authentication failed with " 1776 "target (%s)", icp->conn_oid, 1777 iscsiAuthClientDebugStatusToText( 1778 debug_status)); 1779 1780 } else { 1781 1782 cmn_err(CE_WARN, "iscsi connection(%u) login " 1783 "failed - authentication failed with " 1784 "target", icp->conn_oid); 1785 1786 } 1787 return (ISCSI_STATUS_AUTHENTICATION_FAILED); 1788 } 1789 } 1790 1791 /* 1792 * record some of the PDU fields for later use 1793 */ 1794 isp->sess_tsid = ntohs(ilrhp->tsid); 1795 isp->sess_expcmdsn = ntohl(ilrhp->expcmdsn); 1796 isp->sess_maxcmdsn = ntohl(ilrhp->maxcmdsn); 1797 if (ilrhp->status_class == ISCSI_STATUS_CLASS_SUCCESS) { 1798 icp->conn_expstatsn = ntohl(ilrhp->statsn) + 1; 1799 } 1800 1801 if (transit) { 1802 /* 1803 * advance to the next stage 1804 */ 1805 icp->conn_partial_response = 0; 1806 icp->conn_current_stage = 1807 ilrhp->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; 1808 } else { 1809 /* 1810 * we got a partial response, don't advance, more 1811 * negotiation to do 1812 */ 1813 icp->conn_partial_response = 1; 1814 } 1815 1816 /* 1817 * this PDU is ok, though the login process 1818 * may not be done yet 1819 */ 1820 return (ISCSI_STATUS_SUCCESS); 1821 } 1822 1823 /* 1824 * iscsi_add_text - caller is assumed to be well-behaved and passing NUL 1825 * terminated strings 1826 */ 1827 int 1828 iscsi_add_text(idm_pdu_t *text_pdu, int max_data_length, 1829 char *param, char *value) 1830 { 1831 int param_len = 0; 1832 int value_len = 0; 1833 int length = 0; 1834 int pdu_length = 0; 1835 char *text = NULL; 1836 char *end = NULL; 1837 1838 ASSERT(text_pdu != NULL); 1839 ASSERT(param != NULL); 1840 ASSERT(value != NULL); 1841 1842 param_len = strlen(param); 1843 value_len = strlen(value); 1844 /* param, separator, value, and trailing NULL */ 1845 length = param_len + 1 + value_len + 1; 1846 pdu_length = text_pdu->isp_datalen; 1847 text = (char *)text_pdu->isp_data + pdu_length; 1848 end = (char *)text_pdu->isp_data + max_data_length; 1849 pdu_length += length; 1850 1851 if (text + length >= end) { 1852 return (0); 1853 } 1854 1855 /* param */ 1856 (void) strncpy(text, param, param_len); 1857 text += param_len; 1858 1859 /* separator */ 1860 *text++ = ISCSI_TEXT_SEPARATOR; 1861 1862 /* value */ 1863 (void) strncpy(text, value, value_len); 1864 text += value_len; 1865 1866 /* NULL */ 1867 *text++ = '\0'; 1868 1869 /* update the length in the PDU header */ 1870 text_pdu->isp_datalen = pdu_length; 1871 hton24(text_pdu->isp_hdr->dlength, pdu_length); 1872 1873 return (1); 1874 } 1875 1876 /* 1877 * iscsi_get_next_text - get the next line of text from the given data 1878 * buffer. This function searches from the address given for the 1879 * curr_text parameter. If curr_text_parameter is NULL return first 1880 * line in buffer. The return value is the address of the next line 1881 * based upon where curr_text is located. 1882 * 1883 */ 1884 char * 1885 iscsi_get_next_text(char *data, int max_data_length, char *curr_text) 1886 { 1887 char *curr_data; 1888 1889 ASSERT(data != NULL); 1890 1891 /* check if any data exists, if not return */ 1892 if (max_data_length == 0) { 1893 return (NULL); 1894 } 1895 1896 /* handle first call to this function */ 1897 if (curr_text == NULL) { 1898 return (data); 1899 } 1900 1901 /* move to next text string */ 1902 curr_data = curr_text; 1903 while ((curr_data < (data + max_data_length)) && *curr_data) { 1904 curr_data++; 1905 } 1906 curr_data++; /* go past the NULL to the next entry */ 1907 1908 /* check whether data end reached */ 1909 if (curr_data >= (data + max_data_length)) { 1910 return (NULL); 1911 } 1912 1913 return (curr_data); 1914 } 1915 1916 1917 /* 1918 * iscsi_find_key_value - 1919 * 1920 */ 1921 static int 1922 iscsi_find_key_value(char *param, char *ihp, char *pdu_end, 1923 char **value_start, char **value_end) 1924 { 1925 char *str = param; 1926 char *text = ihp; 1927 char *value = NULL; 1928 1929 if (value_start) 1930 *value_start = NULL; 1931 if (value_end) 1932 *value_end = NULL; 1933 1934 /* 1935 * make sure they contain the same bytes 1936 */ 1937 while (*str) { 1938 if (text >= pdu_end) { 1939 return (0); 1940 } 1941 if (*text == '\0') { 1942 return (0); 1943 } 1944 if (*str != *text) { 1945 return (0); 1946 } 1947 str++; 1948 text++; 1949 } 1950 1951 if ((text >= pdu_end) || 1952 (*text == '\0') || 1953 (*text != ISCSI_TEXT_SEPARATOR)) { 1954 return (0); 1955 } 1956 1957 /* 1958 * find the value 1959 */ 1960 value = text + 1; 1961 1962 /* 1963 * find the end of the value 1964 */ 1965 while ((text < pdu_end) && (*text)) 1966 text++; 1967 1968 if (value_start) 1969 *value_start = value; 1970 if (value_end) 1971 *value_end = text; 1972 1973 return (1); 1974 } 1975 1976 1977 /* 1978 * iscsi_update_address - This function is used on a login redirection. 1979 * During the login redirection we are asked to switch to an IP address 1980 * port different than the one we were logging into. 1981 */ 1982 static iscsi_status_t 1983 iscsi_update_address(iscsi_conn_t *icp, char *in) 1984 { 1985 char *addr_str, *port_str, *tpgt_str; 1986 int type; 1987 struct hostent *hptr; 1988 unsigned long tmp; 1989 int error_num; 1990 int port; 1991 1992 ASSERT(icp != NULL); 1993 ASSERT(in != NULL); 1994 1995 /* parse login redirection response */ 1996 if (parse_addr_port_tpgt(in, &addr_str, &type, 1997 &port_str, &tpgt_str) == B_FALSE) { 1998 return (ISCSI_STATUS_PROTOCOL_ERROR); 1999 } 2000 2001 /* convert addr_str */ 2002 hptr = kgetipnodebyname(addr_str, type, AI_ALL, &error_num); 2003 if (!hptr) { 2004 return (ISCSI_STATUS_PROTOCOL_ERROR); 2005 } 2006 2007 /* convert port_str */ 2008 if (port_str != NULL) { 2009 (void) ddi_strtoul(port_str, NULL, 0, &tmp); 2010 port = (int)tmp; 2011 } else { 2012 port = ISCSI_LISTEN_PORT; 2013 } 2014 2015 iscsid_addr_to_sockaddr(hptr->h_length, *hptr->h_addr_list, 2016 port, &icp->conn_curr_addr.sin); 2017 2018 kfreehostent(hptr); 2019 return (ISCSI_STATUS_SUCCESS); 2020 } 2021 2022 void 2023 iscsi_login_update_state(iscsi_conn_t *icp, iscsi_login_state_t next_state) 2024 { 2025 mutex_enter(&icp->conn_login_mutex); 2026 (void) iscsi_login_update_state_locked(icp, next_state); 2027 mutex_exit(&icp->conn_login_mutex); 2028 } 2029 2030 void 2031 iscsi_login_update_state_locked(iscsi_conn_t *icp, 2032 iscsi_login_state_t next_state) 2033 { 2034 ASSERT(mutex_owned(&icp->conn_login_mutex)); 2035 next_state = (next_state > LOGIN_MAX) ? LOGIN_MAX : next_state; 2036 idm_sm_audit_state_change(&icp->conn_state_audit, 2037 SAS_ISCSI_LOGIN, icp->conn_login_state, next_state); 2038 2039 ISCSI_LOGIN_LOG(CE_NOTE, "iscsi_login_update_state conn %p %d -> %d", 2040 (void *)icp, icp->conn_login_state, next_state); 2041 2042 icp->conn_login_state = next_state; 2043 cv_broadcast(&icp->conn_login_cv); 2044 } 2045 2046 2047 2048 /* 2049 * iscsi_null_callback - This callback may be used under certain 2050 * conditions when authenticating a target, but I'm not sure what 2051 * we need to do here. 2052 */ 2053 /* ARGSUSED */ 2054 static void 2055 iscsi_null_callback(void *user_handle, void *message_handle, int auth_status) 2056 { 2057 } 2058 2059 2060 /* 2061 * iscsi_login_failure_str - 2062 * 2063 */ 2064 static char * 2065 iscsi_login_failure_str(uchar_t status_class, uchar_t status_detail) 2066 { 2067 switch (status_class) { 2068 case 0x00: 2069 switch (status_detail) { 2070 case 0x00: 2071 return ("Login is proceeding okay."); 2072 default: 2073 break; 2074 } 2075 break; 2076 case 0x01: 2077 switch (status_detail) { 2078 case 0x01: 2079 return ("Requested ITN has moved temporarily to " 2080 "the address provided."); 2081 case 0x02: 2082 return ("Requested ITN has moved permanently to " 2083 "the address provided."); 2084 default: 2085 break; 2086 } 2087 break; 2088 case 0x02: 2089 switch (status_detail) { 2090 case 0x00: 2091 return ("Miscellaneous iSCSI initiator errors."); 2092 case 0x01: 2093 return ("Initiator could not be successfully " 2094 "authenticated."); 2095 case 0x02: 2096 return ("Initiator is not allowed access to the " 2097 "given target."); 2098 case 0x03: 2099 return ("Requested ITN does not exist at this " 2100 "address."); 2101 case 0x04: 2102 return ("Requested ITN has been removed and no " 2103 "forwarding address is provided."); 2104 case 0x05: 2105 return ("Requested iSCSI version range is not " 2106 "supported by the target."); 2107 case 0x06: 2108 return ("No more connections can be accepted on " 2109 "this Session ID (SSID)."); 2110 case 0x07: 2111 return ("Missing parameters (e.g., iSCSI initiator " 2112 "and/or target name)."); 2113 case 0x08: 2114 return ("Target does not support session spanning " 2115 "to this connection (address)."); 2116 case 0x09: 2117 return ("Target does not support this type of " 2118 "session or not from this initiator."); 2119 case 0x0A: 2120 return ("Attempt to add a connection to a " 2121 "nonexistent session."); 2122 case 0x0B: 2123 return ("Invalid request type during login."); 2124 default: 2125 break; 2126 } 2127 break; 2128 case 0x03: 2129 switch (status_detail) { 2130 case 0x00: 2131 return ("Target hardware or software error."); 2132 case 0x01: 2133 return ("iSCSI service or target is not currently " 2134 "operational."); 2135 case 0x02: 2136 return ("Target has insufficient session, connection " 2137 "or other resources."); 2138 default: 2139 break; 2140 } 2141 break; 2142 } 2143 return ("Unknown login response received."); 2144 } 2145 2146 2147 /* 2148 * iscsi_login_connect - 2149 */ 2150 static iscsi_status_t 2151 iscsi_login_connect(iscsi_conn_t *icp) 2152 { 2153 iscsi_hba_t *ihp; 2154 iscsi_sess_t *isp; 2155 struct sockaddr *addr; 2156 idm_conn_req_t cr; 2157 idm_status_t rval; 2158 clock_t lbolt; 2159 2160 ASSERT(icp != NULL); 2161 isp = icp->conn_sess; 2162 ASSERT(isp != NULL); 2163 ihp = isp->sess_hba; 2164 ASSERT(ihp != NULL); 2165 addr = &icp->conn_curr_addr.sin; 2166 2167 /* Make sure that scope_id is zero if it is an IPv6 address */ 2168 if (addr->sa_family == AF_INET6) { 2169 ((struct sockaddr_in6 *)addr)->sin6_scope_id = 0; 2170 } 2171 2172 /* delay the connect process if required */ 2173 lbolt = ddi_get_lbolt(); 2174 if (lbolt < icp->conn_login_min) { 2175 if (icp->conn_login_max < icp->conn_login_min) { 2176 delay(icp->conn_login_max - lbolt); 2177 } else { 2178 delay(icp->conn_login_min - lbolt); 2179 } 2180 } 2181 2182 /* Create IDM connection context */ 2183 cr.cr_domain = addr->sa_family; 2184 cr.cr_type = SOCK_STREAM; 2185 cr.cr_protocol = 0; 2186 cr.cr_bound = icp->conn_bound; 2187 cr.cr_li = icp->conn_sess->sess_hba->hba_li; 2188 cr.icr_conn_ops.icb_rx_misc = &iscsi_rx_misc_pdu; 2189 cr.icr_conn_ops.icb_rx_error = &iscsi_rx_error_pdu; 2190 cr.icr_conn_ops.icb_rx_scsi_rsp = &iscsi_rx_scsi_rsp; 2191 cr.icr_conn_ops.icb_client_notify = &iscsi_client_notify; 2192 cr.icr_conn_ops.icb_build_hdr = &iscsi_build_hdr; 2193 cr.icr_conn_ops.icb_task_aborted = &iscsi_task_aborted; 2194 bcopy(addr, &cr.cr_ini_dst_addr, 2195 sizeof (cr.cr_ini_dst_addr)); 2196 bcopy(&icp->conn_bound_addr, &cr.cr_bound_addr, 2197 sizeof (cr.cr_bound_addr)); 2198 if (isp->sess_boot == B_TRUE) { 2199 cr.cr_boot_conn = B_TRUE; 2200 } else { 2201 cr.cr_boot_conn = B_FALSE; 2202 } 2203 2204 /* 2205 * Allocate IDM connection context 2206 */ 2207 rval = idm_ini_conn_create(&cr, &icp->conn_ic); 2208 if (rval != IDM_STATUS_SUCCESS) { 2209 return (ISCSI_STATUS_LOGIN_FAILED); 2210 } 2211 2212 icp->conn_ic->ic_handle = icp; 2213 2214 /* 2215 * About to initiate connect, reset login state. 2216 */ 2217 iscsi_login_update_state(icp, LOGIN_START); 2218 2219 /* 2220 * Make sure the connection doesn't go away until we are done with it. 2221 * This hold will prevent us from receiving a CN_CONNECT_DESTROY 2222 * notification on this connection until we are ready. 2223 */ 2224 idm_conn_hold(icp->conn_ic); 2225 2226 /* 2227 * When iSCSI initiator to target IO timeout or connection failure 2228 * Connection retry is needed for normal operational session. 2229 */ 2230 if ((icp->conn_sess->sess_type == ISCSI_SESS_TYPE_NORMAL) && 2231 ((icp->conn_state == ISCSI_CONN_STATE_FAILED) || 2232 (icp->conn_state == ISCSI_CONN_STATE_POLLING))) { 2233 icp->conn_ic->ic_conn_params.nonblock_socket = B_TRUE; 2234 icp->conn_ic->ic_conn_params.conn_login_max = 2235 icp->conn_login_max; 2236 if (icp->conn_state == ISCSI_CONN_STATE_POLLING) { 2237 icp->conn_ic->ic_conn_params.conn_login_interval = 2238 icp->conn_tunable_params.polling_login_delay; 2239 } else { 2240 icp->conn_ic->ic_conn_params.conn_login_interval = 2241 ISCSI_LOGIN_RETRY_DELAY; 2242 } 2243 2244 } else { 2245 icp->conn_ic->ic_conn_params.nonblock_socket = B_FALSE; 2246 icp->conn_ic->ic_conn_params.conn_login_max = 0; 2247 icp->conn_ic->ic_conn_params.conn_login_interval = 0; 2248 } 2249 /* 2250 * Attempt connection. Upon return we will either be ready to 2251 * login or disconnected. If idm_ini_conn_connect fails we 2252 * will eventually receive a CN_CONNECT_DESTROY at which point 2253 * we will destroy the connection allocated above (so there 2254 * is no need to explicitly free it here). 2255 */ 2256 rval = idm_ini_conn_connect(icp->conn_ic); 2257 2258 if (rval != IDM_STATUS_SUCCESS) { 2259 cmn_err(CE_NOTE, "iscsi connection(%u) unable to " 2260 "connect to target %s", icp->conn_oid, 2261 icp->conn_sess->sess_name); 2262 idm_conn_rele(icp->conn_ic); 2263 } 2264 2265 return (rval == IDM_STATUS_SUCCESS ? 2266 ISCSI_STATUS_SUCCESS : ISCSI_STATUS_INTERNAL_ERROR); 2267 } 2268 2269 /* 2270 * iscsi_login_disconnect 2271 */ 2272 static void 2273 iscsi_login_disconnect(iscsi_conn_t *icp) 2274 { 2275 /* Tell IDM to disconnect is if we are not already disconnect */ 2276 idm_ini_conn_disconnect_sync(icp->conn_ic); 2277 2278 /* 2279 * The function above may return before the CN_CONNECT_LOST 2280 * notification. Wait for it. 2281 */ 2282 mutex_enter(&icp->conn_state_mutex); 2283 while (icp->conn_state_idm_connected) 2284 cv_wait(&icp->conn_state_change, 2285 &icp->conn_state_mutex); 2286 mutex_exit(&icp->conn_state_mutex); 2287 } 2288 2289 /* 2290 * iscsi_notice_key_values - Create an nvlist containing the values 2291 * that have been negotiated for this connection and pass them down to 2292 * IDM so it can pick up any values that are important. 2293 */ 2294 static void 2295 iscsi_notice_key_values(iscsi_conn_t *icp) 2296 { 2297 nvlist_t *neg_nvl; 2298 int rc; 2299 2300 rc = nvlist_alloc(&neg_nvl, NV_UNIQUE_NAME, KM_SLEEP); 2301 ASSERT(rc == 0); 2302 2303 /* Only crc32c is supported so the digest logic is simple */ 2304 if (icp->conn_params.header_digest) { 2305 rc = nvlist_add_string(neg_nvl, "HeaderDigest", "crc32c"); 2306 } else { 2307 rc = nvlist_add_string(neg_nvl, "HeaderDigest", "none"); 2308 } 2309 ASSERT(rc == 0); 2310 2311 if (icp->conn_params.data_digest) { 2312 rc = nvlist_add_string(neg_nvl, "DataDigest", "crc32c"); 2313 } else { 2314 rc = nvlist_add_string(neg_nvl, "DataDigest", "none"); 2315 } 2316 ASSERT(rc == 0); 2317 2318 rc = nvlist_add_uint64(neg_nvl, "MaxRecvDataSegmentLength", 2319 (uint64_t)icp->conn_params.max_recv_data_seg_len); 2320 ASSERT(rc == 0); 2321 2322 rc = nvlist_add_uint64(neg_nvl, "MaxBurstLength", 2323 (uint64_t)icp->conn_params.max_burst_length); 2324 ASSERT(rc == 0); 2325 2326 rc = nvlist_add_uint64(neg_nvl, "MaxOutstandingR2T", 2327 (uint64_t)icp->conn_params.max_outstanding_r2t); 2328 ASSERT(rc == 0); 2329 2330 rc = nvlist_add_uint64(neg_nvl, "ErrorRecoveryLevel", 2331 (uint64_t)icp->conn_params.error_recovery_level); 2332 ASSERT(rc == 0); 2333 2334 rc = nvlist_add_uint64(neg_nvl, "DefaultTime2Wait", 2335 (uint64_t)icp->conn_params.default_time_to_wait); 2336 ASSERT(rc == 0); 2337 2338 rc = nvlist_add_uint64(neg_nvl, "DefaultTime2Retain", 2339 (uint64_t)icp->conn_params.default_time_to_retain); 2340 ASSERT(rc == 0); 2341 2342 /* Pass the list to IDM to examine, then free it */ 2343 idm_notice_key_values(icp->conn_ic, neg_nvl); 2344 nvlist_free(neg_nvl); 2345 } 2346