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