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