1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte /* 22fcf3ce44SJohn Forte * Copyright 2000 by Cisco Systems, Inc. All rights reserved. 23*bbe72583SJack Meng * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24fcf3ce44SJohn Forte * Use is subject to license terms. 25fcf3ce44SJohn Forte * 26fcf3ce44SJohn Forte * iSCSI protocol login and enumeration 27fcf3ce44SJohn Forte */ 28fcf3ce44SJohn Forte 29fcf3ce44SJohn Forte #include "iscsi.h" 301a1a84a3SPeter Dunlap #include <sys/iscsi_protocol.h> 31fcf3ce44SJohn Forte #include <sys/scsi/adapters/iscsi_door.h> 32fcf3ce44SJohn Forte 3330e7468fSPeter Dunlap boolean_t iscsi_login_logging = B_FALSE; 3430e7468fSPeter Dunlap 35fcf3ce44SJohn Forte /* internal login protocol interfaces */ 36fcf3ce44SJohn Forte static iscsi_status_t iscsi_login(iscsi_conn_t *icp, 3730e7468fSPeter Dunlap uint8_t *status_class, uint8_t *status_detail); 3830e7468fSPeter Dunlap static int iscsi_add_text(idm_pdu_t *text_pdu, 39fcf3ce44SJohn Forte int max_data_length, char *param, char *value); 40fcf3ce44SJohn Forte static int iscsi_find_key_value(char *param, char *ihp, char *pdu_end, 41fcf3ce44SJohn Forte char **value_start, char **value_end); 42fcf3ce44SJohn Forte static void iscsi_null_callback(void *user_handle, void *message_handle, 43fcf3ce44SJohn Forte int auth_status); 44fcf3ce44SJohn Forte static iscsi_status_t iscsi_process_login_response(iscsi_conn_t *icp, 45fcf3ce44SJohn Forte iscsi_login_rsp_hdr_t *ilrhp, char *data, int max_data_length); 46fcf3ce44SJohn Forte static iscsi_status_t iscsi_make_login_pdu(iscsi_conn_t *icp, 4730e7468fSPeter Dunlap idm_pdu_t *text_pdu, char *data, int max_data_length); 48fcf3ce44SJohn Forte static iscsi_status_t iscsi_update_address(iscsi_conn_t *icp, 49fcf3ce44SJohn Forte char *address); 50fcf3ce44SJohn Forte static char *iscsi_login_failure_str(uchar_t status_class, 51fcf3ce44SJohn Forte uchar_t status_detail); 52fcf3ce44SJohn Forte static void iscsi_login_end(iscsi_conn_t *icp, 5330e7468fSPeter Dunlap iscsi_status_t status, iscsi_task_t *itp); 54fcf3ce44SJohn Forte static iscsi_status_t iscsi_login_connect(iscsi_conn_t *icp); 5530e7468fSPeter Dunlap static void iscsi_login_disconnect(iscsi_conn_t *icp); 5630e7468fSPeter Dunlap static void iscsi_notice_key_values(iscsi_conn_t *icp); 57fcf3ce44SJohn Forte 58fcf3ce44SJohn Forte #define ISCSI_LOGIN_RETRY_DELAY 5 /* seconds */ 59fcf3ce44SJohn Forte 6019944f88Syi zhang - Sun Microsystems - Beijing China #define ISCSI_LOGIN_TRANSIT_FFP(flags) \ 6119944f88Syi zhang - Sun Microsystems - Beijing China (!(flags & ISCSI_FLAG_LOGIN_CONTINUE) && \ 6219944f88Syi zhang - Sun Microsystems - Beijing China (flags & ISCSI_FLAG_LOGIN_TRANSIT) && \ 6319944f88Syi zhang - Sun Microsystems - Beijing China (ISCSI_LOGIN_CURRENT_STAGE(flags) == \ 6419944f88Syi zhang - Sun Microsystems - Beijing China ISCSI_OP_PARMS_NEGOTIATION_STAGE) && \ 6519944f88Syi zhang - Sun Microsystems - Beijing China (ISCSI_LOGIN_NEXT_STAGE(flags) == \ 6619944f88Syi zhang - Sun Microsystems - Beijing China ISCSI_FULL_FEATURE_PHASE)) 6719944f88Syi zhang - Sun Microsystems - Beijing China 68fcf3ce44SJohn Forte /* 69fcf3ce44SJohn Forte * +--------------------------------------------------------------------+ 70fcf3ce44SJohn Forte * | External Login Interface | 71fcf3ce44SJohn Forte * +--------------------------------------------------------------------+ 72fcf3ce44SJohn Forte */ 73fcf3ce44SJohn Forte 74fcf3ce44SJohn Forte /* 75fcf3ce44SJohn Forte * iscsi_login_start - connect and perform iscsi protocol login 76fcf3ce44SJohn Forte */ 77fcf3ce44SJohn Forte iscsi_status_t 78fcf3ce44SJohn Forte iscsi_login_start(void *arg) 79fcf3ce44SJohn Forte { 80fcf3ce44SJohn Forte iscsi_task_t *itp = (iscsi_task_t *)arg; 81fcf3ce44SJohn Forte iscsi_status_t rval = ISCSI_STATUS_LOGIN_FAILED; 82fcf3ce44SJohn Forte iscsi_conn_t *icp; 83fcf3ce44SJohn Forte iscsi_sess_t *isp; 84fcf3ce44SJohn Forte iscsi_hba_t *ihp; 85fcf3ce44SJohn Forte unsigned char status_class; 86fcf3ce44SJohn Forte unsigned char status_detail; 87fcf3ce44SJohn Forte 88fcf3ce44SJohn Forte ASSERT(itp != NULL); 89fcf3ce44SJohn Forte icp = (iscsi_conn_t *)itp->t_arg; 90fcf3ce44SJohn Forte ASSERT(icp != NULL); 91fcf3ce44SJohn Forte isp = icp->conn_sess; 92fcf3ce44SJohn Forte ASSERT(isp != NULL); 93fcf3ce44SJohn Forte ihp = isp->sess_hba; 94fcf3ce44SJohn Forte ASSERT(ihp != NULL); 95fcf3ce44SJohn Forte 96fcf3ce44SJohn Forte login_start: 9730e7468fSPeter Dunlap ASSERT((icp->conn_state == ISCSI_CONN_STATE_IN_LOGIN) || 9830e7468fSPeter Dunlap (icp->conn_state == ISCSI_CONN_STATE_FAILED) || 9930e7468fSPeter Dunlap (icp->conn_state == ISCSI_CONN_STATE_POLLING)); 10030e7468fSPeter Dunlap 10130e7468fSPeter Dunlap icp->conn_state_ffp = B_FALSE; 10230e7468fSPeter Dunlap 103fcf3ce44SJohn Forte /* reset connection statsn */ 104fcf3ce44SJohn Forte icp->conn_expstatsn = 0; 105fcf3ce44SJohn Forte icp->conn_laststatsn = 0; 106fcf3ce44SJohn Forte 107fcf3ce44SJohn Forte /* sync up authentication information */ 108fcf3ce44SJohn Forte (void) iscsi_sess_set_auth(isp); 109fcf3ce44SJohn Forte 110fcf3ce44SJohn Forte /* sync up login and session parameters */ 111fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(iscsi_conn_sync_params(icp))) { 112fcf3ce44SJohn Forte /* unable to sync params. fail connection attempts */ 11330e7468fSPeter Dunlap iscsi_login_end(icp, ISCSI_STATUS_LOGIN_FAILED, itp); 114fcf3ce44SJohn Forte return (ISCSI_STATUS_LOGIN_FAILED); 115fcf3ce44SJohn Forte } 116fcf3ce44SJohn Forte 11730e7468fSPeter Dunlap /* 11830e7468fSPeter Dunlap * Attempt to open TCP connection, associated IDM connection will 11930e7468fSPeter Dunlap * have a hold on it that must be released after the call to 12030e7468fSPeter Dunlap * iscsi_login() below. 12130e7468fSPeter Dunlap */ 122fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(iscsi_login_connect(icp))) { 123*bbe72583SJack Meng if ((isp->sess_boot == B_TRUE) && 124*bbe72583SJack Meng (ihp->hba_service_status_overwrite == B_TRUE) && 125*bbe72583SJack Meng (isp->sess_boot_nic_reset == B_FALSE)) { 126*bbe72583SJack Meng /* 127*bbe72583SJack Meng * The connection to boot target failed 128*bbe72583SJack Meng * before the system fully started. 129*bbe72583SJack Meng * Reset the boot nic to the settings from 130*bbe72583SJack Meng * firmware before retrying the connect to 131*bbe72583SJack Meng * save the the system. 132*bbe72583SJack Meng */ 133*bbe72583SJack Meng if (iscsi_net_interface(B_TRUE) == 134*bbe72583SJack Meng ISCSI_STATUS_SUCCESS) { 135*bbe72583SJack Meng isp->sess_boot_nic_reset = B_TRUE; 136*bbe72583SJack Meng } 137*bbe72583SJack Meng } 138fcf3ce44SJohn Forte /* retry this failure */ 139fcf3ce44SJohn Forte goto login_retry; 140fcf3ce44SJohn Forte } 141fcf3ce44SJohn Forte 142fcf3ce44SJohn Forte /* 143fcf3ce44SJohn Forte * allocate response buffer with based on default max 144fcf3ce44SJohn Forte * transfer size. This size might shift during login. 145fcf3ce44SJohn Forte */ 14630e7468fSPeter Dunlap icp->conn_login_max_data_length = 14730e7468fSPeter Dunlap icp->conn_params.max_xmit_data_seg_len; 14830e7468fSPeter Dunlap icp->conn_login_data = kmem_zalloc(icp->conn_login_max_data_length, 14930e7468fSPeter Dunlap KM_SLEEP); 150fcf3ce44SJohn Forte 15130e7468fSPeter Dunlap /* 15230e7468fSPeter Dunlap * Start protocol login, upon return we will be either logged in 15330e7468fSPeter Dunlap * or disconnected 15430e7468fSPeter Dunlap */ 15530e7468fSPeter Dunlap rval = iscsi_login(icp, &status_class, &status_detail); 156fcf3ce44SJohn Forte 157fcf3ce44SJohn Forte /* done with buffer */ 15830e7468fSPeter Dunlap kmem_free(icp->conn_login_data, icp->conn_login_max_data_length); 15930e7468fSPeter Dunlap 16030e7468fSPeter Dunlap /* Release connection hold */ 16130e7468fSPeter Dunlap idm_conn_rele(icp->conn_ic); 162fcf3ce44SJohn Forte 163fcf3ce44SJohn Forte /* hard failure in login */ 164fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(rval)) { 165fcf3ce44SJohn Forte /* 166fcf3ce44SJohn Forte * We should just give up retry if these failures are 167fcf3ce44SJohn Forte * detected. 168fcf3ce44SJohn Forte */ 169fcf3ce44SJohn Forte switch (rval) { 170fcf3ce44SJohn Forte /* 171fcf3ce44SJohn Forte * We should just give up retry if these 172fcf3ce44SJohn Forte * failures are detected. 173fcf3ce44SJohn Forte */ 174fcf3ce44SJohn Forte case ISCSI_STATUS_AUTHENTICATION_FAILED: 175fcf3ce44SJohn Forte case ISCSI_STATUS_INTERNAL_ERROR: 176fcf3ce44SJohn Forte case ISCSI_STATUS_VERSION_MISMATCH: 177fcf3ce44SJohn Forte case ISCSI_STATUS_NEGO_FAIL: 178fcf3ce44SJohn Forte /* we don't want to retry this failure */ 17930e7468fSPeter Dunlap iscsi_login_end(icp, ISCSI_STATUS_LOGIN_FAILED, itp); 180fcf3ce44SJohn Forte return (ISCSI_STATUS_LOGIN_FAILED); 181fcf3ce44SJohn Forte default: 182fcf3ce44SJohn Forte /* retry this failure */ 183fcf3ce44SJohn Forte goto login_retry; 184fcf3ce44SJohn Forte } 185fcf3ce44SJohn Forte } 186fcf3ce44SJohn Forte 187fcf3ce44SJohn Forte /* soft failure with reason */ 188fcf3ce44SJohn Forte switch (status_class) { 189fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_SUCCESS: 190fcf3ce44SJohn Forte /* login was successful */ 19130e7468fSPeter Dunlap iscsi_login_end(icp, ISCSI_STATUS_SUCCESS, itp); 192fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 193fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_REDIRECT: 194fcf3ce44SJohn Forte /* Retry at the redirected address */ 195fcf3ce44SJohn Forte goto login_start; 196fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_TARGET_ERR: 197fcf3ce44SJohn Forte /* retry this failure */ 198fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 199fcf3ce44SJohn Forte "%s (0x%02x/0x%02x)", icp->conn_oid, 200fcf3ce44SJohn Forte iscsi_login_failure_str(status_class, status_detail), 201fcf3ce44SJohn Forte status_class, status_detail); 202fcf3ce44SJohn Forte goto login_retry; 203fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_INITIATOR_ERR: 204fcf3ce44SJohn Forte default: 205fcf3ce44SJohn Forte /* All other errors are hard failures */ 206fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 2077f848965Sbing zhao - Sun Microsystems - Beijing China "%s (0x%02x/0x%02x) Target: %s, TPGT: %d", 2087f848965Sbing zhao - Sun Microsystems - Beijing China icp->conn_oid, 209fcf3ce44SJohn Forte iscsi_login_failure_str(status_class, status_detail), 2107f848965Sbing zhao - Sun Microsystems - Beijing China status_class, status_detail, isp->sess_name, 2117f848965Sbing zhao - Sun Microsystems - Beijing China isp->sess_tpgt_conf); 212fcf3ce44SJohn Forte 213fcf3ce44SJohn Forte /* we don't want to retry this failure */ 21430e7468fSPeter Dunlap iscsi_login_end(icp, ISCSI_STATUS_LOGIN_FAILED, itp); 215fcf3ce44SJohn Forte break; 216fcf3ce44SJohn Forte } 21730e7468fSPeter Dunlap 218fcf3ce44SJohn Forte return (ISCSI_STATUS_LOGIN_FAILED); 219fcf3ce44SJohn Forte 220fcf3ce44SJohn Forte login_retry: 221fcf3ce44SJohn Forte /* retry this failure if we haven't run out of time */ 222fcf3ce44SJohn Forte if (icp->conn_login_max > ddi_get_lbolt()) { 223fcf3ce44SJohn Forte 224fcf3ce44SJohn Forte if (icp->conn_state == ISCSI_CONN_STATE_POLLING) { 225fcf3ce44SJohn Forte icp->conn_login_min = ddi_get_lbolt() + 226aff4bce5Syi zhang - Sun Microsystems - Beijing China SEC_TO_TICK(icp->conn_tunable_params. 227aff4bce5Syi zhang - Sun Microsystems - Beijing China polling_login_delay); 228fcf3ce44SJohn Forte } else { 229fcf3ce44SJohn Forte icp->conn_login_min = ddi_get_lbolt() + 230fcf3ce44SJohn Forte SEC_TO_TICK(ISCSI_LOGIN_RETRY_DELAY); 231fcf3ce44SJohn Forte } 232fcf3ce44SJohn Forte 233fcf3ce44SJohn Forte if (itp->t_blocking == B_TRUE) { 234fcf3ce44SJohn Forte goto login_start; 235fcf3ce44SJohn Forte } else { 236fcf3ce44SJohn Forte if (ddi_taskq_dispatch(isp->sess_taskq, 237fcf3ce44SJohn Forte (void(*)())iscsi_login_start, itp, DDI_SLEEP) != 238fcf3ce44SJohn Forte DDI_SUCCESS) { 239fcf3ce44SJohn Forte iscsi_login_end(icp, 24030e7468fSPeter Dunlap ISCSI_STATUS_LOGIN_TIMED_OUT, itp); 241fcf3ce44SJohn Forte } 242fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 243fcf3ce44SJohn Forte } 244fcf3ce44SJohn Forte } else { 245fcf3ce44SJohn Forte /* Retries exceeded */ 24630e7468fSPeter Dunlap iscsi_login_end(icp, ISCSI_STATUS_LOGIN_TIMED_OUT, itp); 247fcf3ce44SJohn Forte } 24830e7468fSPeter Dunlap 249fcf3ce44SJohn Forte return (ISCSI_STATUS_LOGIN_FAILED); 250fcf3ce44SJohn Forte } 251fcf3ce44SJohn Forte 252fcf3ce44SJohn Forte static void 25330e7468fSPeter Dunlap iscsi_login_end(iscsi_conn_t *icp, iscsi_status_t status, iscsi_task_t *itp) 254fcf3ce44SJohn Forte { 255fcf3ce44SJohn Forte iscsi_sess_t *isp; 256fcf3ce44SJohn Forte 257fcf3ce44SJohn Forte ASSERT(icp != NULL); 258fcf3ce44SJohn Forte isp = icp->conn_sess; 259fcf3ce44SJohn Forte ASSERT(isp != NULL); 260fcf3ce44SJohn Forte 26130e7468fSPeter Dunlap if (status == ISCSI_STATUS_SUCCESS) { 26230e7468fSPeter Dunlap /* Inform IDM of the relevant negotiated values */ 26330e7468fSPeter Dunlap iscsi_notice_key_values(icp); 26430e7468fSPeter Dunlap 26530e7468fSPeter Dunlap /* We are now logged in */ 26630e7468fSPeter Dunlap iscsi_conn_update_state(icp, ISCSI_CONN_STATE_LOGGED_IN); 26730e7468fSPeter Dunlap 26830e7468fSPeter Dunlap /* startup TX thread */ 26930e7468fSPeter Dunlap (void) iscsi_thread_start(icp->conn_tx_thread); 27030e7468fSPeter Dunlap 27130e7468fSPeter Dunlap /* 27230e7468fSPeter Dunlap * Move login state machine to LOGIN_FFP. This will 27330e7468fSPeter Dunlap * release the taskq thread handling the CN_FFP_ENABLED 27430e7468fSPeter Dunlap * allowing the IDM connection state machine to resume 27530e7468fSPeter Dunlap * processing events 27630e7468fSPeter Dunlap */ 27730e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_FFP); 278fcf3ce44SJohn Forte 27930e7468fSPeter Dunlap /* Notify the session that a connection is logged in */ 28030e7468fSPeter Dunlap mutex_enter(&isp->sess_state_mutex); 28130e7468fSPeter Dunlap iscsi_sess_state_machine(isp, ISCSI_SESS_EVENT_N1); 28230e7468fSPeter Dunlap mutex_exit(&isp->sess_state_mutex); 28330e7468fSPeter Dunlap } else { 28430e7468fSPeter Dunlap /* If login failed reset nego tpgt */ 285fcf3ce44SJohn Forte isp->sess_tpgt_nego = ISCSI_DEFAULT_TPGT; 28630e7468fSPeter Dunlap 28730e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 28830e7468fSPeter Dunlap switch (icp->conn_state) { 28930e7468fSPeter Dunlap case ISCSI_CONN_STATE_IN_LOGIN: 29030e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 29130e7468fSPeter Dunlap ISCSI_CONN_STATE_FREE); 29230e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 29330e7468fSPeter Dunlap break; 29430e7468fSPeter Dunlap case ISCSI_CONN_STATE_FAILED: 29530e7468fSPeter Dunlap if (status == ISCSI_STATUS_LOGIN_FAILED) { 29630e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 29730e7468fSPeter Dunlap ISCSI_CONN_STATE_FREE); 29830e7468fSPeter Dunlap } else { 29930e7468fSPeter Dunlap /* ISCSI_STATUS_LOGIN_TIMED_OUT */ 30030e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 30130e7468fSPeter Dunlap ISCSI_CONN_STATE_POLLING); 30230e7468fSPeter Dunlap } 30330e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 30430e7468fSPeter Dunlap 30530e7468fSPeter Dunlap mutex_enter(&isp->sess_state_mutex); 30630e7468fSPeter Dunlap iscsi_sess_state_machine(isp, ISCSI_SESS_EVENT_N6); 30730e7468fSPeter Dunlap mutex_exit(&isp->sess_state_mutex); 30830e7468fSPeter Dunlap 30930e7468fSPeter Dunlap if (status == ISCSI_STATUS_LOGIN_TIMED_OUT) { 31030e7468fSPeter Dunlap iscsi_conn_retry(isp, icp); 31130e7468fSPeter Dunlap } 31230e7468fSPeter Dunlap break; 31330e7468fSPeter Dunlap case ISCSI_CONN_STATE_POLLING: 31430e7468fSPeter Dunlap if (status == ISCSI_STATUS_LOGIN_FAILED) { 31530e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 31630e7468fSPeter Dunlap ISCSI_CONN_STATE_FREE); 31730e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 31830e7468fSPeter Dunlap 31930e7468fSPeter Dunlap mutex_enter(&isp->sess_state_mutex); 32030e7468fSPeter Dunlap iscsi_sess_state_machine(isp, 32130e7468fSPeter Dunlap ISCSI_SESS_EVENT_N6); 32230e7468fSPeter Dunlap mutex_exit(&isp->sess_state_mutex); 32330e7468fSPeter Dunlap } else { 32430e7468fSPeter Dunlap /* ISCSI_STATUS_LOGIN_TIMED_OUT */ 32530e7468fSPeter Dunlap if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 32630e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 32730e7468fSPeter Dunlap 32830e7468fSPeter Dunlap iscsi_conn_retry(isp, icp); 32930e7468fSPeter Dunlap } else { 33030e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 33130e7468fSPeter Dunlap ISCSI_CONN_STATE_FREE); 33230e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 33330e7468fSPeter Dunlap } 33430e7468fSPeter Dunlap } 33530e7468fSPeter Dunlap break; 33619944f88Syi zhang - Sun Microsystems - Beijing China case ISCSI_CONN_STATE_FREE: 33719944f88Syi zhang - Sun Microsystems - Beijing China mutex_exit(&icp->conn_state_mutex); 33819944f88Syi zhang - Sun Microsystems - Beijing China break; 33930e7468fSPeter Dunlap default: 34019944f88Syi zhang - Sun Microsystems - Beijing China mutex_exit(&icp->conn_state_mutex); 34130e7468fSPeter Dunlap ASSERT(0); 34230e7468fSPeter Dunlap break; 34330e7468fSPeter Dunlap } 344fcf3ce44SJohn Forte } 345fcf3ce44SJohn Forte 346fcf3ce44SJohn Forte if (itp->t_blocking == B_FALSE) { 347fcf3ce44SJohn Forte kmem_free(itp, sizeof (iscsi_task_t)); 348fcf3ce44SJohn Forte } 349*bbe72583SJack Meng 350*bbe72583SJack Meng isp->sess_boot_nic_reset = B_FALSE; 351fcf3ce44SJohn Forte } 352fcf3ce44SJohn Forte 353fcf3ce44SJohn Forte /* 354fcf3ce44SJohn Forte * +--------------------------------------------------------------------+ 355fcf3ce44SJohn Forte * | Begin of protocol login routines | 356fcf3ce44SJohn Forte * +--------------------------------------------------------------------+ 357fcf3ce44SJohn Forte */ 358fcf3ce44SJohn Forte 359fcf3ce44SJohn Forte /* 360fcf3ce44SJohn Forte * iscsi_login - Attempt to login to the target. The caller 361fcf3ce44SJohn Forte * must check the status class to determine if the login succeeded. 362fcf3ce44SJohn Forte * A return of 1 does not mean the login succeeded, it just means 363fcf3ce44SJohn Forte * this function worked, and the status class is valid info. This 364fcf3ce44SJohn Forte * allows the caller to decide whether or not to retry logins, so 365fcf3ce44SJohn Forte * that we don't have any policy logic here. 366fcf3ce44SJohn Forte */ 36730e7468fSPeter Dunlap iscsi_status_t 36830e7468fSPeter Dunlap iscsi_login(iscsi_conn_t *icp, uint8_t *status_class, uint8_t *status_detail) 369fcf3ce44SJohn Forte { 370fcf3ce44SJohn Forte iscsi_status_t rval = ISCSI_STATUS_INTERNAL_ERROR; 371fcf3ce44SJohn Forte struct iscsi_sess *isp = NULL; 372fcf3ce44SJohn Forte IscsiAuthClient *auth_client = NULL; 373fcf3ce44SJohn Forte int max_data_length = 0; 374fcf3ce44SJohn Forte char *data = NULL; 37530e7468fSPeter Dunlap idm_pdu_t *text_pdu; 37630e7468fSPeter Dunlap char *buffer; 37730e7468fSPeter Dunlap size_t bufsize; 37830e7468fSPeter Dunlap iscsi_login_rsp_hdr_t *ilrhp; 37930e7468fSPeter Dunlap clock_t response_timeout, timeout_result; 38030e7468fSPeter Dunlap 38130e7468fSPeter Dunlap buffer = icp->conn_login_data; 38230e7468fSPeter Dunlap bufsize = icp->conn_login_max_data_length; 383fcf3ce44SJohn Forte 384fcf3ce44SJohn Forte ASSERT(icp != NULL); 385fcf3ce44SJohn Forte ASSERT(buffer != NULL); 386fcf3ce44SJohn Forte ASSERT(status_class != NULL); 387fcf3ce44SJohn Forte ASSERT(status_detail != NULL); 388fcf3ce44SJohn Forte isp = icp->conn_sess; 389fcf3ce44SJohn Forte ASSERT(isp != NULL); 390fcf3ce44SJohn Forte 391fcf3ce44SJohn Forte /* 39230e7468fSPeter Dunlap * prepare the connection, hold IDM connection until login completes 393fcf3ce44SJohn Forte */ 394fcf3ce44SJohn Forte icp->conn_current_stage = ISCSI_INITIAL_LOGIN_STAGE; 395fcf3ce44SJohn Forte icp->conn_partial_response = 0; 396fcf3ce44SJohn Forte 397fcf3ce44SJohn Forte if (isp->sess_auth.auth_buffers && 398fcf3ce44SJohn Forte isp->sess_auth.num_auth_buffers) { 399fcf3ce44SJohn Forte 400fcf3ce44SJohn Forte auth_client = (IscsiAuthClient *)isp-> 401fcf3ce44SJohn Forte sess_auth.auth_buffers[0].address; 402fcf3ce44SJohn Forte 403fcf3ce44SJohn Forte /* 404fcf3ce44SJohn Forte * prepare for authentication 405fcf3ce44SJohn Forte */ 406fcf3ce44SJohn Forte if (iscsiAuthClientInit(iscsiAuthNodeTypeInitiator, 407fcf3ce44SJohn Forte isp->sess_auth.num_auth_buffers, 408fcf3ce44SJohn Forte isp->sess_auth.auth_buffers) != 409fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 410fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 411fcf3ce44SJohn Forte "unable to initialize authentication", 412fcf3ce44SJohn Forte icp->conn_oid); 41330e7468fSPeter Dunlap iscsi_login_disconnect(icp); 41430e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_DONE); 415fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 416fcf3ce44SJohn Forte } 417fcf3ce44SJohn Forte 418fcf3ce44SJohn Forte if (iscsiAuthClientSetVersion(auth_client, 419fcf3ce44SJohn Forte iscsiAuthVersionRfc) != iscsiAuthStatusNoError) { 420fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 421fcf3ce44SJohn Forte "unable to set authentication", icp->conn_oid); 422fcf3ce44SJohn Forte goto iscsi_login_done; 423fcf3ce44SJohn Forte } 424fcf3ce44SJohn Forte 425fcf3ce44SJohn Forte if (isp->sess_auth.username && 426fcf3ce44SJohn Forte (iscsiAuthClientSetUsername(auth_client, 427fcf3ce44SJohn Forte isp->sess_auth.username) != 428fcf3ce44SJohn Forte iscsiAuthStatusNoError)) { 429fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 430fcf3ce44SJohn Forte "unable to set username", icp->conn_oid); 431fcf3ce44SJohn Forte goto iscsi_login_done; 432fcf3ce44SJohn Forte } 433fcf3ce44SJohn Forte 434fcf3ce44SJohn Forte if (isp->sess_auth.password && 435fcf3ce44SJohn Forte (iscsiAuthClientSetPassword(auth_client, 436fcf3ce44SJohn Forte isp->sess_auth.password, isp->sess_auth.password_length) != 437fcf3ce44SJohn Forte iscsiAuthStatusNoError)) { 438fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 439fcf3ce44SJohn Forte "unable to set password", icp->conn_oid); 440fcf3ce44SJohn Forte goto iscsi_login_done; 441fcf3ce44SJohn Forte } 442fcf3ce44SJohn Forte 443fcf3ce44SJohn Forte if (iscsiAuthClientSetIpSec(auth_client, 1) != 444fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 445fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 446fcf3ce44SJohn Forte "unable to set ipsec", icp->conn_oid); 447fcf3ce44SJohn Forte goto iscsi_login_done; 448fcf3ce44SJohn Forte } 449fcf3ce44SJohn Forte 450fcf3ce44SJohn Forte if (iscsiAuthClientSetAuthRemote(auth_client, 451fcf3ce44SJohn Forte isp->sess_auth.bidirectional_auth) != 452fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 453fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 454fcf3ce44SJohn Forte "unable to set remote authentication", 455fcf3ce44SJohn Forte icp->conn_oid); 456fcf3ce44SJohn Forte goto iscsi_login_done; 457fcf3ce44SJohn Forte } 458fcf3ce44SJohn Forte } 459fcf3ce44SJohn Forte 460fcf3ce44SJohn Forte /* 461fcf3ce44SJohn Forte * exchange PDUs until the login stage is complete, or an error occurs 462fcf3ce44SJohn Forte */ 463fcf3ce44SJohn Forte do { 464fcf3ce44SJohn Forte /* setup */ 465fcf3ce44SJohn Forte bzero(buffer, bufsize); 466fcf3ce44SJohn Forte data = buffer; 467fcf3ce44SJohn Forte max_data_length = bufsize; 468fcf3ce44SJohn Forte rval = ISCSI_STATUS_INTERNAL_ERROR; 469fcf3ce44SJohn Forte 47030e7468fSPeter Dunlap text_pdu = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0); 47130e7468fSPeter Dunlap idm_pdu_init(text_pdu, icp->conn_ic, NULL, NULL); 47230e7468fSPeter Dunlap 473fcf3ce44SJohn Forte /* 474fcf3ce44SJohn Forte * fill in the PDU header and text data based on the 475fcf3ce44SJohn Forte * login stage that we're in 476fcf3ce44SJohn Forte */ 47730e7468fSPeter Dunlap rval = iscsi_make_login_pdu(icp, text_pdu, data, 47830e7468fSPeter Dunlap max_data_length); 479fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(rval)) { 480fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 481fcf3ce44SJohn Forte "unable to make login pdu", icp->conn_oid); 482fcf3ce44SJohn Forte goto iscsi_login_done; 483fcf3ce44SJohn Forte } 484fcf3ce44SJohn Forte 48530e7468fSPeter Dunlap mutex_enter(&icp->conn_login_mutex); 48630e7468fSPeter Dunlap /* 48730e7468fSPeter Dunlap * Make sure we are still in LOGIN_START or LOGIN_RX 48830e7468fSPeter Dunlap * state before switching to LOGIN_TX. It's possible 48930e7468fSPeter Dunlap * for a connection failure to move us to LOGIN_ERROR 49030e7468fSPeter Dunlap * before we get to this point. 49130e7468fSPeter Dunlap */ 49230e7468fSPeter Dunlap if (((icp->conn_login_state != LOGIN_READY) && 49330e7468fSPeter Dunlap (icp->conn_login_state != LOGIN_RX)) || 49430e7468fSPeter Dunlap !icp->conn_state_idm_connected) { 49530e7468fSPeter Dunlap /* Error occurred */ 49630e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex); 49730e7468fSPeter Dunlap rval = (ISCSI_STATUS_INTERNAL_ERROR); 498fcf3ce44SJohn Forte goto iscsi_login_done; 499fcf3ce44SJohn Forte } 500fcf3ce44SJohn Forte 50130e7468fSPeter Dunlap iscsi_login_update_state_locked(icp, LOGIN_TX); 50230e7468fSPeter Dunlap icp->conn_login_data = data; 50330e7468fSPeter Dunlap icp->conn_login_max_data_length = max_data_length; 50430e7468fSPeter Dunlap 50530e7468fSPeter Dunlap /* 50630e7468fSPeter Dunlap * send a PDU to the target. This is asynchronous but 50730e7468fSPeter Dunlap * we don't have any particular need for a TX completion 50830e7468fSPeter Dunlap * notification since we are going to block waiting for the 50930e7468fSPeter Dunlap * receive. 51030e7468fSPeter Dunlap */ 51130e7468fSPeter Dunlap response_timeout = ddi_get_lbolt() + 512aff4bce5Syi zhang - Sun Microsystems - Beijing China SEC_TO_TICK(icp->conn_tunable_params. 513aff4bce5Syi zhang - Sun Microsystems - Beijing China recv_login_rsp_timeout); 51430e7468fSPeter Dunlap idm_pdu_tx(text_pdu); 51530e7468fSPeter Dunlap 51630e7468fSPeter Dunlap /* 51730e7468fSPeter Dunlap * Wait for login failure indication or login RX. 51830e7468fSPeter Dunlap * Handler for login response PDU will copy any data into 51930e7468fSPeter Dunlap * the buffer pointed to by icp->conn_login_data 52030e7468fSPeter Dunlap */ 52130e7468fSPeter Dunlap while (icp->conn_login_state == LOGIN_TX) { 52230e7468fSPeter Dunlap timeout_result = cv_timedwait(&icp->conn_login_cv, 52330e7468fSPeter Dunlap &icp->conn_login_mutex, response_timeout); 52430e7468fSPeter Dunlap if (timeout_result == -1) 52530e7468fSPeter Dunlap break; 526fcf3ce44SJohn Forte } 527fcf3ce44SJohn Forte 52830e7468fSPeter Dunlap if (icp->conn_login_state != LOGIN_RX) { 52930e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex); 53030e7468fSPeter Dunlap rval = (ISCSI_STATUS_INTERNAL_ERROR); 531fcf3ce44SJohn Forte goto iscsi_login_done; 532fcf3ce44SJohn Forte } 53330e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex); 534fcf3ce44SJohn Forte 535fcf3ce44SJohn Forte /* check the PDU response type */ 53630e7468fSPeter Dunlap ilrhp = (iscsi_login_rsp_hdr_t *)&icp->conn_login_resp_hdr; 53730e7468fSPeter Dunlap if (ilrhp->opcode != ISCSI_OP_LOGIN_RSP) { 538fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 539fcf3ce44SJohn Forte "received invalid login response (0x%02x)", 54030e7468fSPeter Dunlap icp->conn_oid, ilrhp->opcode); 541fcf3ce44SJohn Forte rval = (ISCSI_STATUS_PROTOCOL_ERROR); 542fcf3ce44SJohn Forte goto iscsi_login_done; 543fcf3ce44SJohn Forte } 544fcf3ce44SJohn Forte 545fcf3ce44SJohn Forte /* 546fcf3ce44SJohn Forte * give the caller the status class and detail from the 547fcf3ce44SJohn Forte * last login response PDU received 548fcf3ce44SJohn Forte */ 549fcf3ce44SJohn Forte if (status_class) { 550fcf3ce44SJohn Forte *status_class = ilrhp->status_class; 551fcf3ce44SJohn Forte } 552fcf3ce44SJohn Forte if (status_detail) { 553fcf3ce44SJohn Forte *status_detail = ilrhp->status_detail; 554fcf3ce44SJohn Forte } 555fcf3ce44SJohn Forte 556fcf3ce44SJohn Forte switch (ilrhp->status_class) { 557fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_SUCCESS: 558fcf3ce44SJohn Forte /* 559fcf3ce44SJohn Forte * process this response and possibly continue 560fcf3ce44SJohn Forte * sending PDUs 561fcf3ce44SJohn Forte */ 562fcf3ce44SJohn Forte rval = iscsi_process_login_response(icp, 56330e7468fSPeter Dunlap ilrhp, (char *)icp->conn_login_data, 56430e7468fSPeter Dunlap icp->conn_login_max_data_length); 565fcf3ce44SJohn Forte /* pass back whatever error we discovered */ 566fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(rval)) { 56719944f88Syi zhang - Sun Microsystems - Beijing China if (ISCSI_LOGIN_TRANSIT_FFP(ilrhp->flags)) { 56819944f88Syi zhang - Sun Microsystems - Beijing China /* 56919944f88Syi zhang - Sun Microsystems - Beijing China * iSCSI connection transit to next 57019944f88Syi zhang - Sun Microsystems - Beijing China * FFP stage while iscsi params 57119944f88Syi zhang - Sun Microsystems - Beijing China * ngeotiate error, LOGIN_ERROR 57219944f88Syi zhang - Sun Microsystems - Beijing China * marked so CN_FFP_ENABLED can 57319944f88Syi zhang - Sun Microsystems - Beijing China * be fully handled before 57419944f88Syi zhang - Sun Microsystems - Beijing China * CN_FFP_DISABLED can be processed. 57519944f88Syi zhang - Sun Microsystems - Beijing China */ 57619944f88Syi zhang - Sun Microsystems - Beijing China iscsi_login_update_state(icp, 57719944f88Syi zhang - Sun Microsystems - Beijing China LOGIN_ERROR); 57819944f88Syi zhang - Sun Microsystems - Beijing China } 579fcf3ce44SJohn Forte goto iscsi_login_done; 580fcf3ce44SJohn Forte } 581fcf3ce44SJohn Forte 582fcf3ce44SJohn Forte break; 583fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_REDIRECT: 584fcf3ce44SJohn Forte /* 585fcf3ce44SJohn Forte * we need to process this response to get the 586fcf3ce44SJohn Forte * TargetAddress of the redirect, but we don't 587fcf3ce44SJohn Forte * care about the return code. 588fcf3ce44SJohn Forte */ 58930e7468fSPeter Dunlap (void) iscsi_process_login_response(icp, 59030e7468fSPeter Dunlap ilrhp, (char *)icp->conn_login_data, 59130e7468fSPeter Dunlap icp->conn_login_max_data_length); 592fcf3ce44SJohn Forte rval = ISCSI_STATUS_SUCCESS; 593fcf3ce44SJohn Forte goto iscsi_login_done; 594fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_INITIATOR_ERR: 595fcf3ce44SJohn Forte if (ilrhp->status_detail == 596fcf3ce44SJohn Forte ISCSI_LOGIN_STATUS_AUTH_FAILED) { 597fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 598fcf3ce44SJohn Forte "failed - login failed to authenticate " 599fcf3ce44SJohn Forte "with target", icp->conn_oid); 600fcf3ce44SJohn Forte } 601fcf3ce44SJohn Forte rval = ISCSI_STATUS_SUCCESS; 602fcf3ce44SJohn Forte goto iscsi_login_done; 603fcf3ce44SJohn Forte default: 604fcf3ce44SJohn Forte /* 605fcf3ce44SJohn Forte * some sort of error, login terminated unsuccessfully, 606fcf3ce44SJohn Forte * though this function did it's job. the caller must 607fcf3ce44SJohn Forte * check the status_class and status_detail and decide 608fcf3ce44SJohn Forte * what to do next. 609fcf3ce44SJohn Forte */ 610fcf3ce44SJohn Forte rval = ISCSI_STATUS_SUCCESS; 611fcf3ce44SJohn Forte goto iscsi_login_done; 612fcf3ce44SJohn Forte } 613fcf3ce44SJohn Forte 614fcf3ce44SJohn Forte } while (icp->conn_current_stage != ISCSI_FULL_FEATURE_PHASE); 615fcf3ce44SJohn Forte 616fcf3ce44SJohn Forte rval = ISCSI_STATUS_SUCCESS; 617fcf3ce44SJohn Forte 618fcf3ce44SJohn Forte iscsi_login_done: 619fcf3ce44SJohn Forte if (auth_client) { 620fcf3ce44SJohn Forte if (iscsiAuthClientFinish(auth_client) != 621fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 622fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 623fcf3ce44SJohn Forte "failed - login failed to authenticate " 624fcf3ce44SJohn Forte "with target", icp->conn_oid); 625fcf3ce44SJohn Forte if (ISCSI_SUCCESS(rval)) 626fcf3ce44SJohn Forte rval = ISCSI_STATUS_INTERNAL_ERROR; 627fcf3ce44SJohn Forte } 628fcf3ce44SJohn Forte } 62930e7468fSPeter Dunlap 63030e7468fSPeter Dunlap if (ISCSI_SUCCESS(rval) && 63130e7468fSPeter Dunlap (*status_class == ISCSI_STATUS_CLASS_SUCCESS)) { 63230e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 63330e7468fSPeter Dunlap while (!icp->conn_state_ffp) 63430e7468fSPeter Dunlap cv_wait(&icp->conn_state_change, 63530e7468fSPeter Dunlap &icp->conn_state_mutex); 63630e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 63730e7468fSPeter Dunlap } else { 63830e7468fSPeter Dunlap iscsi_login_disconnect(icp); 63930e7468fSPeter Dunlap } 64030e7468fSPeter Dunlap 64130e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_DONE); 64230e7468fSPeter Dunlap 643fcf3ce44SJohn Forte return (rval); 644fcf3ce44SJohn Forte } 645fcf3ce44SJohn Forte 646fcf3ce44SJohn Forte 647fcf3ce44SJohn Forte /* 648fcf3ce44SJohn Forte * iscsi_make_login_pdu - 649fcf3ce44SJohn Forte * 650fcf3ce44SJohn Forte */ 651fcf3ce44SJohn Forte static iscsi_status_t 65230e7468fSPeter Dunlap iscsi_make_login_pdu(iscsi_conn_t *icp, idm_pdu_t *text_pdu, 653fcf3ce44SJohn Forte char *data, int max_data_length) 654fcf3ce44SJohn Forte { 655fcf3ce44SJohn Forte struct iscsi_sess *isp = NULL; 656fcf3ce44SJohn Forte int transit = 0; 65730e7468fSPeter Dunlap iscsi_hdr_t *ihp = text_pdu->isp_hdr; 65830e7468fSPeter Dunlap iscsi_login_hdr_t *ilhp = 65930e7468fSPeter Dunlap (iscsi_login_hdr_t *)text_pdu->isp_hdr; 660fcf3ce44SJohn Forte IscsiAuthClient *auth_client = NULL; 661fcf3ce44SJohn Forte int keytype = 0; 662fcf3ce44SJohn Forte int rc = 0; 663fcf3ce44SJohn Forte char value[iscsiAuthStringMaxLength]; 664fcf3ce44SJohn Forte 665fcf3ce44SJohn Forte ASSERT(icp != NULL); 66630e7468fSPeter Dunlap ASSERT(text_pdu != NULL); 667fcf3ce44SJohn Forte isp = icp->conn_sess; 668fcf3ce44SJohn Forte ASSERT(isp != NULL); 669fcf3ce44SJohn Forte 670fcf3ce44SJohn Forte auth_client = 671fcf3ce44SJohn Forte (isp->sess_auth.auth_buffers && isp->sess_auth.num_auth_buffers) ? 672fcf3ce44SJohn Forte (IscsiAuthClient *)isp->sess_auth.auth_buffers[0].address : NULL; 673fcf3ce44SJohn Forte 674fcf3ce44SJohn Forte /* 675fcf3ce44SJohn Forte * initialize the PDU header 676fcf3ce44SJohn Forte */ 677fcf3ce44SJohn Forte bzero(ilhp, sizeof (*ilhp)); 678fcf3ce44SJohn Forte ilhp->opcode = ISCSI_OP_LOGIN_CMD | ISCSI_OP_IMMEDIATE; 679fcf3ce44SJohn Forte ilhp->cid = icp->conn_cid; 680fcf3ce44SJohn Forte bcopy(&isp->sess_isid[0], &ilhp->isid[0], sizeof (isp->sess_isid)); 681fcf3ce44SJohn Forte ilhp->tsid = 0; 682fcf3ce44SJohn Forte 68330e7468fSPeter Dunlap /* 68430e7468fSPeter Dunlap * Set data buffer pointer. The calls to iscsi_add_text will update the 68530e7468fSPeter Dunlap * data length. 68630e7468fSPeter Dunlap */ 68730e7468fSPeter Dunlap text_pdu->isp_data = (uint8_t *)data; 68830e7468fSPeter Dunlap 689fcf3ce44SJohn Forte /* don't increment on immediate */ 690fcf3ce44SJohn Forte ilhp->cmdsn = htonl(isp->sess_cmdsn); 691fcf3ce44SJohn Forte 692fcf3ce44SJohn Forte ilhp->min_version = ISCSI_DRAFT20_VERSION; 693fcf3ce44SJohn Forte ilhp->max_version = ISCSI_DRAFT20_VERSION; 694fcf3ce44SJohn Forte 695fcf3ce44SJohn Forte /* 696fcf3ce44SJohn Forte * we have to send 0 until full-feature stage 697fcf3ce44SJohn Forte */ 698fcf3ce44SJohn Forte ilhp->expstatsn = htonl(icp->conn_expstatsn); 699fcf3ce44SJohn Forte 700fcf3ce44SJohn Forte /* 701fcf3ce44SJohn Forte * the very first Login PDU has some additional requirements, 702fcf3ce44SJohn Forte * * and we need to decide what stage to start in. 703fcf3ce44SJohn Forte */ 704fcf3ce44SJohn Forte if (icp->conn_current_stage == ISCSI_INITIAL_LOGIN_STAGE) { 705fcf3ce44SJohn Forte if ((isp->sess_hba->hba_name) && 706fcf3ce44SJohn Forte (isp->sess_hba->hba_name[0])) { 70730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 708fcf3ce44SJohn Forte "InitiatorName", 709fcf3ce44SJohn Forte (char *)isp->sess_hba->hba_name)) { 710fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 711fcf3ce44SJohn Forte } 712fcf3ce44SJohn Forte } else { 713fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 714fcf3ce44SJohn Forte "failed - initiator name is required", 715fcf3ce44SJohn Forte icp->conn_oid); 716fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 717fcf3ce44SJohn Forte } 718fcf3ce44SJohn Forte 719fcf3ce44SJohn Forte if ((isp->sess_hba->hba_alias) && 720fcf3ce44SJohn Forte (isp->sess_hba->hba_alias[0])) { 72130e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 722fcf3ce44SJohn Forte "InitiatorAlias", 723fcf3ce44SJohn Forte (char *)isp->sess_hba->hba_alias)) { 724fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 725fcf3ce44SJohn Forte } 726fcf3ce44SJohn Forte } 727fcf3ce44SJohn Forte 728fcf3ce44SJohn Forte if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 729fcf3ce44SJohn Forte if (isp->sess_name[0] != '\0') { 73030e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 731fcf3ce44SJohn Forte "TargetName", (char *)isp->sess_name)) { 732fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 733fcf3ce44SJohn Forte } 734fcf3ce44SJohn Forte } 735fcf3ce44SJohn Forte 73630e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 737fcf3ce44SJohn Forte "SessionType", "Normal")) { 738fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 739fcf3ce44SJohn Forte } 740fcf3ce44SJohn Forte } else if (isp->sess_type == ISCSI_SESS_TYPE_DISCOVERY) { 74130e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 742fcf3ce44SJohn Forte "SessionType", "Discovery")) { 743fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 744fcf3ce44SJohn Forte } 745fcf3ce44SJohn Forte } else { 746fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 747fcf3ce44SJohn Forte } 748fcf3ce44SJohn Forte 749fcf3ce44SJohn Forte if (auth_client) { 750fcf3ce44SJohn Forte /* we're prepared to do authentication */ 751fcf3ce44SJohn Forte icp->conn_current_stage = 752fcf3ce44SJohn Forte ISCSI_SECURITY_NEGOTIATION_STAGE; 753fcf3ce44SJohn Forte } else { 754fcf3ce44SJohn Forte /* can't do any authentication, skip that stage */ 755fcf3ce44SJohn Forte icp->conn_current_stage = 756fcf3ce44SJohn Forte ISCSI_OP_PARMS_NEGOTIATION_STAGE; 757fcf3ce44SJohn Forte } 758fcf3ce44SJohn Forte } 759fcf3ce44SJohn Forte 760fcf3ce44SJohn Forte /* 761fcf3ce44SJohn Forte * fill in text based on the stage 762fcf3ce44SJohn Forte */ 763fcf3ce44SJohn Forte switch (icp->conn_current_stage) { 764fcf3ce44SJohn Forte case ISCSI_OP_PARMS_NEGOTIATION_STAGE: 765fcf3ce44SJohn Forte /* 766fcf3ce44SJohn Forte * we always try to go from op params to full 767fcf3ce44SJohn Forte * feature stage 768fcf3ce44SJohn Forte */ 769fcf3ce44SJohn Forte icp->conn_next_stage = ISCSI_FULL_FEATURE_PHASE; 770fcf3ce44SJohn Forte transit = 1; 771fcf3ce44SJohn Forte 772fcf3ce44SJohn Forte /* 773fcf3ce44SJohn Forte * The terminology here may have gotten dated. A partial 774fcf3ce44SJohn Forte * response is a login response that doesn't complete a 775fcf3ce44SJohn Forte * login. If we haven't gotten a partial response, then 776fcf3ce44SJohn Forte * either we shouldn't be here, or we just switched to 777fcf3ce44SJohn Forte * this stage, and need to start offering keys. 778fcf3ce44SJohn Forte */ 779fcf3ce44SJohn Forte if (!icp->conn_partial_response) { 780fcf3ce44SJohn Forte /* 781fcf3ce44SJohn Forte * request the desired settings the first time 782fcf3ce44SJohn Forte * we are in this stage 783fcf3ce44SJohn Forte */ 784fcf3ce44SJohn Forte switch (icp->conn_params.header_digest) { 785fcf3ce44SJohn Forte case ISCSI_DIGEST_NONE: 78630e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 787fcf3ce44SJohn Forte max_data_length, "HeaderDigest", "None")) { 788fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 789fcf3ce44SJohn Forte } 790fcf3ce44SJohn Forte break; 791fcf3ce44SJohn Forte case ISCSI_DIGEST_CRC32C: 79230e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 793fcf3ce44SJohn Forte max_data_length, 794fcf3ce44SJohn Forte "HeaderDigest", "CRC32C")) { 795fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 796fcf3ce44SJohn Forte } 797fcf3ce44SJohn Forte break; 798fcf3ce44SJohn Forte case ISCSI_DIGEST_CRC32C_NONE: 79930e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 800fcf3ce44SJohn Forte max_data_length, "HeaderDigest", 801fcf3ce44SJohn Forte "CRC32C,None")) { 802fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 803fcf3ce44SJohn Forte } 804fcf3ce44SJohn Forte break; 805fcf3ce44SJohn Forte default: 806fcf3ce44SJohn Forte case ISCSI_DIGEST_NONE_CRC32C: 80730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 808fcf3ce44SJohn Forte max_data_length, "HeaderDigest", 809fcf3ce44SJohn Forte "None,CRC32C")) { 810fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 811fcf3ce44SJohn Forte } 812fcf3ce44SJohn Forte break; 813fcf3ce44SJohn Forte } 814fcf3ce44SJohn Forte 815fcf3ce44SJohn Forte switch (icp->conn_params.data_digest) { 816fcf3ce44SJohn Forte case ISCSI_DIGEST_NONE: 81730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 818fcf3ce44SJohn Forte max_data_length, "DataDigest", "None")) { 819fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 820fcf3ce44SJohn Forte } 821fcf3ce44SJohn Forte break; 822fcf3ce44SJohn Forte case ISCSI_DIGEST_CRC32C: 82330e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 824fcf3ce44SJohn Forte max_data_length, "DataDigest", "CRC32C")) { 825fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 826fcf3ce44SJohn Forte } 827fcf3ce44SJohn Forte break; 828fcf3ce44SJohn Forte case ISCSI_DIGEST_CRC32C_NONE: 82930e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 830fcf3ce44SJohn Forte max_data_length, "DataDigest", 831fcf3ce44SJohn Forte "CRC32C,None")) { 832fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 833fcf3ce44SJohn Forte } 834fcf3ce44SJohn Forte break; 835fcf3ce44SJohn Forte default: 836fcf3ce44SJohn Forte case ISCSI_DIGEST_NONE_CRC32C: 83730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 838fcf3ce44SJohn Forte max_data_length, "DataDigest", 839fcf3ce44SJohn Forte "None,CRC32C")) { 840fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 841fcf3ce44SJohn Forte } 842fcf3ce44SJohn Forte break; 843fcf3ce44SJohn Forte } 844fcf3ce44SJohn Forte 845fcf3ce44SJohn Forte (void) sprintf(value, "%d", 846fcf3ce44SJohn Forte icp->conn_params.max_recv_data_seg_len); 84730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 848fcf3ce44SJohn Forte "MaxRecvDataSegmentLength", value)) { 849fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 850fcf3ce44SJohn Forte } 851fcf3ce44SJohn Forte 852fcf3ce44SJohn Forte (void) sprintf(value, "%d", 853fcf3ce44SJohn Forte icp->conn_params.default_time_to_wait); 85430e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 855fcf3ce44SJohn Forte max_data_length, "DefaultTime2Wait", value)) { 856fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 857fcf3ce44SJohn Forte } 858fcf3ce44SJohn Forte 859fcf3ce44SJohn Forte (void) sprintf(value, "%d", 860fcf3ce44SJohn Forte icp->conn_params.default_time_to_retain); 86130e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 862fcf3ce44SJohn Forte max_data_length, "DefaultTime2Retain", value)) { 863fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 864fcf3ce44SJohn Forte } 865fcf3ce44SJohn Forte 866fcf3ce44SJohn Forte (void) sprintf(value, "%d", 867fcf3ce44SJohn Forte icp->conn_params.error_recovery_level); 86830e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 869fcf3ce44SJohn Forte max_data_length, "ErrorRecoveryLevel", "0")) { 870fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 871fcf3ce44SJohn Forte } 872fcf3ce44SJohn Forte 87330e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 874fcf3ce44SJohn Forte max_data_length, "IFMarker", 875fcf3ce44SJohn Forte icp->conn_params.ifmarker ? "Yes" : "No")) { 876fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 877fcf3ce44SJohn Forte } 878fcf3ce44SJohn Forte 87930e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 880fcf3ce44SJohn Forte max_data_length, "OFMarker", 881fcf3ce44SJohn Forte icp->conn_params.ofmarker ? "Yes" : "No")) { 882fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 883fcf3ce44SJohn Forte } 884fcf3ce44SJohn Forte 885fcf3ce44SJohn Forte /* 886fcf3ce44SJohn Forte * The following login parameters are "Irrelevant" 887fcf3ce44SJohn Forte * for discovery sessions 888fcf3ce44SJohn Forte */ 889fcf3ce44SJohn Forte if (isp->sess_type != ISCSI_SESS_TYPE_DISCOVERY) { 890fcf3ce44SJohn Forte 89130e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 892fcf3ce44SJohn Forte max_data_length, "InitialR2T", 893fcf3ce44SJohn Forte icp->conn_params.initial_r2t ? 894fcf3ce44SJohn Forte "Yes" : "No")) { 895fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 896fcf3ce44SJohn Forte } 897fcf3ce44SJohn Forte 89830e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 899fcf3ce44SJohn Forte max_data_length, "ImmediateData", 900fcf3ce44SJohn Forte icp->conn_params.immediate_data ? 901fcf3ce44SJohn Forte "Yes" : "No")) { 902fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 903fcf3ce44SJohn Forte } 904fcf3ce44SJohn Forte 905fcf3ce44SJohn Forte (void) sprintf(value, "%d", 906fcf3ce44SJohn Forte icp->conn_params.max_burst_length); 90730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 908fcf3ce44SJohn Forte max_data_length, "MaxBurstLength", value)) { 909fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 910fcf3ce44SJohn Forte } 911fcf3ce44SJohn Forte 912fcf3ce44SJohn Forte (void) sprintf(value, "%d", 913fcf3ce44SJohn Forte icp->conn_params.first_burst_length); 91430e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 915fcf3ce44SJohn Forte "FirstBurstLength", value)) { 916fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 917fcf3ce44SJohn Forte } 918fcf3ce44SJohn Forte 919fcf3ce44SJohn Forte (void) sprintf(value, "%d", 920fcf3ce44SJohn Forte icp->conn_params.max_outstanding_r2t); 92130e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 922fcf3ce44SJohn Forte "MaxOutstandingR2T", value)) { 923fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 924fcf3ce44SJohn Forte } 925fcf3ce44SJohn Forte 926fcf3ce44SJohn Forte (void) sprintf(value, "%d", 927fcf3ce44SJohn Forte icp->conn_params.max_connections); 92830e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 929fcf3ce44SJohn Forte "MaxConnections", value)) { 930fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 931fcf3ce44SJohn Forte } 932fcf3ce44SJohn Forte 93330e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 934fcf3ce44SJohn Forte max_data_length, "DataPDUInOrder", 935fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order ? 936fcf3ce44SJohn Forte "Yes" : "No")) { 937fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 938fcf3ce44SJohn Forte } 939fcf3ce44SJohn Forte 94030e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 941fcf3ce44SJohn Forte max_data_length, "DataSequenceInOrder", 942fcf3ce44SJohn Forte icp->conn_params.data_sequence_in_order ? 943fcf3ce44SJohn Forte "Yes" : "No")) { 944fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 945fcf3ce44SJohn Forte } 946fcf3ce44SJohn Forte } 947fcf3ce44SJohn Forte } 948fcf3ce44SJohn Forte break; 949fcf3ce44SJohn Forte 950fcf3ce44SJohn Forte case ISCSI_SECURITY_NEGOTIATION_STAGE: 951fcf3ce44SJohn Forte keytype = iscsiAuthKeyTypeNone; 952fcf3ce44SJohn Forte rc = iscsiAuthClientSendTransitBit(auth_client, &transit); 953fcf3ce44SJohn Forte 954fcf3ce44SJohn Forte /* 955fcf3ce44SJohn Forte * see if we're ready for a stage change 956fcf3ce44SJohn Forte */ 957fcf3ce44SJohn Forte if (rc == iscsiAuthStatusNoError) { 958fcf3ce44SJohn Forte if (transit) { 959fcf3ce44SJohn Forte icp->conn_next_stage = 960fcf3ce44SJohn Forte ISCSI_OP_PARMS_NEGOTIATION_STAGE; 961fcf3ce44SJohn Forte } else { 962fcf3ce44SJohn Forte icp->conn_next_stage = 963fcf3ce44SJohn Forte ISCSI_SECURITY_NEGOTIATION_STAGE; 964fcf3ce44SJohn Forte } 965fcf3ce44SJohn Forte } else { 966fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 967fcf3ce44SJohn Forte } 968fcf3ce44SJohn Forte 969fcf3ce44SJohn Forte /* 970fcf3ce44SJohn Forte * enumerate all the keys the auth code might want to send 971fcf3ce44SJohn Forte */ 972fcf3ce44SJohn Forte while (iscsiAuthClientGetNextKeyType(&keytype) == 973fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 974fcf3ce44SJohn Forte int present = 0; 975fcf3ce44SJohn Forte char *key = (char *)iscsiAuthClientGetKeyName(keytype); 976fcf3ce44SJohn Forte int key_length = key ? strlen(key) : 0; 97730e7468fSPeter Dunlap int pdu_length = text_pdu->isp_datalen; 978fcf3ce44SJohn Forte char *auth_value = data + pdu_length + key_length + 1; 979fcf3ce44SJohn Forte unsigned int max_length = max_data_length - 980fcf3ce44SJohn Forte (pdu_length + key_length + 1); 981fcf3ce44SJohn Forte 982fcf3ce44SJohn Forte /* 983fcf3ce44SJohn Forte * add the key/value pairs the auth code wants to 984fcf3ce44SJohn Forte * send directly to the PDU, since they could in 985fcf3ce44SJohn Forte * theory be large. 986fcf3ce44SJohn Forte */ 987fcf3ce44SJohn Forte rc = iscsiAuthClientSendKeyValue(auth_client, keytype, 988fcf3ce44SJohn Forte &present, auth_value, max_length); 989fcf3ce44SJohn Forte if ((rc == iscsiAuthStatusNoError) && present) { 990fcf3ce44SJohn Forte /* 991fcf3ce44SJohn Forte * actually fill in the key 992fcf3ce44SJohn Forte */ 993fcf3ce44SJohn Forte (void) strncpy(&data[pdu_length], key, 994fcf3ce44SJohn Forte key_length); 995fcf3ce44SJohn Forte pdu_length += key_length; 996fcf3ce44SJohn Forte data[pdu_length] = '='; 997fcf3ce44SJohn Forte pdu_length++; 998fcf3ce44SJohn Forte /* 999fcf3ce44SJohn Forte * adjust the PDU's data segment length to 1000fcf3ce44SJohn Forte * include the value and trailing NULL 1001fcf3ce44SJohn Forte */ 1002fcf3ce44SJohn Forte pdu_length += strlen(auth_value) + 1; 100330e7468fSPeter Dunlap text_pdu->isp_datalen = pdu_length; 1004fcf3ce44SJohn Forte hton24(ihp->dlength, pdu_length); 1005fcf3ce44SJohn Forte } 1006fcf3ce44SJohn Forte } 1007fcf3ce44SJohn Forte 1008fcf3ce44SJohn Forte break; 1009fcf3ce44SJohn Forte case ISCSI_FULL_FEATURE_PHASE: 1010fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1011fcf3ce44SJohn Forte "failed - can't send login in full feature stage", 1012fcf3ce44SJohn Forte icp->conn_oid); 1013fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1014fcf3ce44SJohn Forte default: 1015fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1016fcf3ce44SJohn Forte "failed - can't send login in unknown stage (%d)", 1017fcf3ce44SJohn Forte icp->conn_oid, icp->conn_current_stage); 1018fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1019fcf3ce44SJohn Forte } 1020fcf3ce44SJohn Forte 1021fcf3ce44SJohn Forte /* fill in the flags */ 1022fcf3ce44SJohn Forte ilhp->flags = icp->conn_current_stage << 2; 1023fcf3ce44SJohn Forte if (transit) { 1024fcf3ce44SJohn Forte /* transit to the next stage */ 1025fcf3ce44SJohn Forte ilhp->flags |= icp->conn_next_stage; 1026fcf3ce44SJohn Forte ilhp->flags |= ISCSI_FLAG_LOGIN_TRANSIT; 1027fcf3ce44SJohn Forte } else { 1028fcf3ce44SJohn Forte /* next == current */ 1029fcf3ce44SJohn Forte ilhp->flags |= icp->conn_current_stage; 1030fcf3ce44SJohn Forte } 1031fcf3ce44SJohn Forte 1032fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 1033fcf3ce44SJohn Forte } 1034fcf3ce44SJohn Forte 1035fcf3ce44SJohn Forte 1036fcf3ce44SJohn Forte /* 1037fcf3ce44SJohn Forte * iscsi_process_login_response - This assumes the text data is 1038fcf3ce44SJohn Forte * always NUL terminated. The caller can always arrange for that by 1039fcf3ce44SJohn Forte * using a slightly larger buffer than the max PDU size, and then 1040fcf3ce44SJohn Forte * appending a NUL to the PDU. 1041fcf3ce44SJohn Forte */ 1042fcf3ce44SJohn Forte static iscsi_status_t 1043fcf3ce44SJohn Forte iscsi_process_login_response(iscsi_conn_t *icp, 1044fcf3ce44SJohn Forte iscsi_login_rsp_hdr_t *ilrhp, char *data, int max_data_length) 1045fcf3ce44SJohn Forte { 1046fcf3ce44SJohn Forte iscsi_sess_t *isp = NULL; 1047fcf3ce44SJohn Forte IscsiAuthClient *auth_client = NULL; 1048fcf3ce44SJohn Forte int transit = 0; 1049fcf3ce44SJohn Forte char *text = data; 1050fcf3ce44SJohn Forte char *end = NULL; 1051fcf3ce44SJohn Forte int pdu_current_stage = 0; 1052fcf3ce44SJohn Forte int pdu_next_stage = 0; 1053fcf3ce44SJohn Forte int debug_status = 0; 1054fcf3ce44SJohn Forte unsigned long tmp; 1055fcf3ce44SJohn Forte char *tmpe; 1056fcf3ce44SJohn Forte boolean_t fbl_irrelevant = B_FALSE; 1057fcf3ce44SJohn Forte 1058fcf3ce44SJohn Forte ASSERT(icp != NULL); 1059fcf3ce44SJohn Forte ASSERT(ilrhp != NULL); 1060fcf3ce44SJohn Forte ASSERT(data != NULL); 1061fcf3ce44SJohn Forte isp = icp->conn_sess; 1062fcf3ce44SJohn Forte ASSERT(isp != NULL); 1063fcf3ce44SJohn Forte 1064fcf3ce44SJohn Forte auth_client = 1065fcf3ce44SJohn Forte (isp->sess_auth.auth_buffers && isp->sess_auth.num_auth_buffers) ? 1066fcf3ce44SJohn Forte (IscsiAuthClient *) isp->sess_auth.auth_buffers[0].address : NULL; 1067fcf3ce44SJohn Forte transit = ilrhp->flags & ISCSI_FLAG_LOGIN_TRANSIT; 1068fcf3ce44SJohn Forte 1069fcf3ce44SJohn Forte /* verify the initial buffer was big enough to hold everything */ 1070fcf3ce44SJohn Forte end = text + ntoh24(ilrhp->dlength) + 1; 1071fcf3ce44SJohn Forte if (end >= (data + max_data_length)) { 1072fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1073fcf3ce44SJohn Forte "buffer too small", icp->conn_oid); 1074fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1075fcf3ce44SJohn Forte } 1076fcf3ce44SJohn Forte *end = '\0'; 1077fcf3ce44SJohn Forte 1078fcf3ce44SJohn Forte /* if the response status was success, sanity check the response */ 1079fcf3ce44SJohn Forte if (ilrhp->status_class == ISCSI_STATUS_CLASS_SUCCESS) { 1080fcf3ce44SJohn Forte /* check the active version */ 1081fcf3ce44SJohn Forte if (ilrhp->active_version != ISCSI_DRAFT20_VERSION) { 1082fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1083fcf3ce44SJohn Forte "failed - target version incompatible " 1084fcf3ce44SJohn Forte "received:0x%0x2x expected:0x%02x", 1085fcf3ce44SJohn Forte icp->conn_oid, ilrhp->active_version, 1086fcf3ce44SJohn Forte ISCSI_DRAFT20_VERSION); 1087fcf3ce44SJohn Forte return (ISCSI_STATUS_VERSION_MISMATCH); 1088fcf3ce44SJohn Forte } 1089fcf3ce44SJohn Forte 1090fcf3ce44SJohn Forte /* make sure the current stage matches */ 1091fcf3ce44SJohn Forte pdu_current_stage = (ilrhp->flags & 1092fcf3ce44SJohn Forte ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2; 1093fcf3ce44SJohn Forte if (pdu_current_stage != icp->conn_current_stage) { 1094fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1095fcf3ce44SJohn Forte "failed - login response contained invalid " 1096fcf3ce44SJohn Forte "stage %d", icp->conn_oid, pdu_current_stage); 1097fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1098fcf3ce44SJohn Forte } 1099fcf3ce44SJohn Forte 1100fcf3ce44SJohn Forte /* 1101fcf3ce44SJohn Forte * Make sure that we're actually advancing 1102fcf3ce44SJohn Forte * if the T-bit is set 1103fcf3ce44SJohn Forte */ 1104fcf3ce44SJohn Forte pdu_next_stage = ilrhp->flags & 1105fcf3ce44SJohn Forte ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; 1106fcf3ce44SJohn Forte if (transit && (pdu_next_stage <= icp->conn_current_stage)) { 1107fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1108fcf3ce44SJohn Forte "failed - login response wants to go to stage " 1109fcf3ce44SJohn Forte "%d, but we want stage %d", icp->conn_oid, 1110fcf3ce44SJohn Forte pdu_next_stage, icp->conn_next_stage); 1111fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1112fcf3ce44SJohn Forte } 1113fcf3ce44SJohn Forte } 1114fcf3ce44SJohn Forte 1115fcf3ce44SJohn Forte if (icp->conn_current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE) { 1116fcf3ce44SJohn Forte if (iscsiAuthClientRecvBegin(auth_client) != 1117fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 1118fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1119fcf3ce44SJohn Forte "authentication receive failed", icp->conn_oid); 1120fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1121fcf3ce44SJohn Forte } 1122fcf3ce44SJohn Forte 1123fcf3ce44SJohn Forte if (iscsiAuthClientRecvTransitBit(auth_client, 1124fcf3ce44SJohn Forte transit) != iscsiAuthStatusNoError) { 1125fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1126fcf3ce44SJohn Forte "authentication transmit failed", icp->conn_oid); 1127fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1128fcf3ce44SJohn Forte } 1129fcf3ce44SJohn Forte } 1130fcf3ce44SJohn Forte 1131fcf3ce44SJohn Forte /* 1132fcf3ce44SJohn Forte * scan the text data 1133fcf3ce44SJohn Forte */ 1134fcf3ce44SJohn Forte more_text: 1135fcf3ce44SJohn Forte while (text && (text < end)) { 1136fcf3ce44SJohn Forte char *value = NULL; 1137fcf3ce44SJohn Forte char *value_end = NULL; 1138fcf3ce44SJohn Forte 1139fcf3ce44SJohn Forte /* 1140fcf3ce44SJohn Forte * skip any NULs separating each text key=value pair 1141fcf3ce44SJohn Forte */ 1142fcf3ce44SJohn Forte while ((text < end) && (*text == '\0')) { 1143fcf3ce44SJohn Forte text++; 1144fcf3ce44SJohn Forte } 1145fcf3ce44SJohn Forte if (text >= end) { 1146fcf3ce44SJohn Forte break; 1147fcf3ce44SJohn Forte } 1148fcf3ce44SJohn Forte 1149fcf3ce44SJohn Forte /* 1150fcf3ce44SJohn Forte * handle keys appropriate for each stage 1151fcf3ce44SJohn Forte */ 1152fcf3ce44SJohn Forte switch (icp->conn_current_stage) { 1153fcf3ce44SJohn Forte case ISCSI_SECURITY_NEGOTIATION_STAGE: 1154fcf3ce44SJohn Forte /* 1155fcf3ce44SJohn Forte * a few keys are possible in Security stage 1156fcf3ce44SJohn Forte * * which the auth code doesn't care about, 1157fcf3ce44SJohn Forte * * but which we might want to see, or at 1158fcf3ce44SJohn Forte * * least not choke on. 1159fcf3ce44SJohn Forte */ 1160fcf3ce44SJohn Forte if (iscsi_find_key_value("TargetAlias", 1161fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1162fcf3ce44SJohn Forte isp->sess_alias_length = 1163fcf3ce44SJohn Forte sizeof (isp->sess_alias) - 1; 1164fcf3ce44SJohn Forte 1165fcf3ce44SJohn Forte if ((value_end - value) < 1166fcf3ce44SJohn Forte isp->sess_alias_length) { 1167fcf3ce44SJohn Forte isp->sess_alias_length = 1168fcf3ce44SJohn Forte value_end - value; 1169fcf3ce44SJohn Forte } 1170fcf3ce44SJohn Forte 1171fcf3ce44SJohn Forte bcopy(value, isp->sess_alias, 1172fcf3ce44SJohn Forte isp->sess_alias_length); 1173fcf3ce44SJohn Forte isp->sess_alias[isp->sess_alias_length + 1] = 1174fcf3ce44SJohn Forte '\0'; 1175fcf3ce44SJohn Forte text = value_end; 1176fcf3ce44SJohn Forte 1177fcf3ce44SJohn Forte } else if (iscsi_find_key_value("TargetAddress", 1178fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1179fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(iscsi_update_address( 1180fcf3ce44SJohn Forte icp, value))) { 1181fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1182fcf3ce44SJohn Forte "login failed - login redirection " 1183fcf3ce44SJohn Forte "invalid", icp->conn_oid); 1184fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1185fcf3ce44SJohn Forte } 1186fcf3ce44SJohn Forte text = value_end; 1187fcf3ce44SJohn Forte } else if (iscsi_find_key_value("TargetPortalGroupTag", 1188fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1189fcf3ce44SJohn Forte /* 1190fcf3ce44SJohn Forte * We should have already obtained this via 1191fcf3ce44SJohn Forte * discovery. We've already picked an isid, 1192fcf3ce44SJohn Forte * so the most we can do is confirm we reached 1193fcf3ce44SJohn Forte * the portal group we were expecting to. 1194fcf3ce44SJohn Forte */ 1195fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1196fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1197fcf3ce44SJohn Forte } 1198fcf3ce44SJohn Forte if (isp->sess_tpgt_conf != ISCSI_DEFAULT_TPGT) { 1199fcf3ce44SJohn Forte if (tmp != isp->sess_tpgt_conf) { 1200fcf3ce44SJohn Forte 1201fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - target " 1202fcf3ce44SJohn Forte "protocol group tag mismatch, expected %d, received %lu", 1203fcf3ce44SJohn Forte icp->conn_oid, isp->sess_tpgt_conf, tmp); 1204fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1205fcf3ce44SJohn Forte 1206fcf3ce44SJohn Forte } 1207fcf3ce44SJohn Forte } 1208fcf3ce44SJohn Forte isp->sess_tpgt_nego = (int)tmp; 1209fcf3ce44SJohn Forte text = value_end; 1210fcf3ce44SJohn Forte } else { 1211fcf3ce44SJohn Forte /* 1212fcf3ce44SJohn Forte * any key we don't recognize either goes 1213fcf3ce44SJohn Forte * to the auth code, or we choke on it 1214fcf3ce44SJohn Forte */ 1215fcf3ce44SJohn Forte int keytype = iscsiAuthKeyTypeNone; 1216fcf3ce44SJohn Forte 1217fcf3ce44SJohn Forte while (iscsiAuthClientGetNextKeyType( 1218fcf3ce44SJohn Forte &keytype) == iscsiAuthStatusNoError) { 1219fcf3ce44SJohn Forte 1220fcf3ce44SJohn Forte char *key = 1221fcf3ce44SJohn Forte (char *)iscsiAuthClientGetKeyName( 1222fcf3ce44SJohn Forte keytype); 1223fcf3ce44SJohn Forte 1224fcf3ce44SJohn Forte if ((key) && 1225fcf3ce44SJohn Forte (iscsi_find_key_value(key, 1226fcf3ce44SJohn Forte text, end, &value, &value_end))) { 1227fcf3ce44SJohn Forte 1228fcf3ce44SJohn Forte if (iscsiAuthClientRecvKeyValue 1229fcf3ce44SJohn Forte (auth_client, keytype, 1230fcf3ce44SJohn Forte value) != 1231fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 1232fcf3ce44SJohn Forte 1233fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - can't accept " 1234fcf3ce44SJohn Forte "%s in security stage", icp->conn_oid, text); 1235fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1236fcf3ce44SJohn Forte 1237fcf3ce44SJohn Forte } 1238fcf3ce44SJohn Forte text = value_end; 1239fcf3ce44SJohn Forte goto more_text; 1240fcf3ce44SJohn Forte } 1241fcf3ce44SJohn Forte } 1242fcf3ce44SJohn Forte 1243fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - can't except " 1244fcf3ce44SJohn Forte "%s in security stage", icp->conn_oid, text); 1245fcf3ce44SJohn Forte 1246fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1247fcf3ce44SJohn Forte } 1248fcf3ce44SJohn Forte break; 1249fcf3ce44SJohn Forte case ISCSI_OP_PARMS_NEGOTIATION_STAGE: 1250fcf3ce44SJohn Forte if (iscsi_find_key_value("TargetAlias", text, 1251fcf3ce44SJohn Forte end, &value, &value_end)) { 1252fcf3ce44SJohn Forte isp->sess_alias_length = 1253fcf3ce44SJohn Forte sizeof (isp->sess_alias) - 1; 1254fcf3ce44SJohn Forte 1255fcf3ce44SJohn Forte if ((value_end - value) < 1256fcf3ce44SJohn Forte isp->sess_alias_length) { 1257fcf3ce44SJohn Forte isp->sess_alias_length = 1258fcf3ce44SJohn Forte value_end - value; 1259fcf3ce44SJohn Forte } 1260fcf3ce44SJohn Forte 1261fcf3ce44SJohn Forte bcopy(value, isp->sess_alias, 1262fcf3ce44SJohn Forte isp->sess_alias_length); 1263fcf3ce44SJohn Forte isp->sess_alias[isp->sess_alias_length + 1] = 1264fcf3ce44SJohn Forte '\0'; 1265fcf3ce44SJohn Forte text = value_end; 1266fcf3ce44SJohn Forte 1267fcf3ce44SJohn Forte } else if (iscsi_find_key_value("TargetAddress", 1268fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1269fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(iscsi_update_address( 1270fcf3ce44SJohn Forte icp, value))) { 1271fcf3ce44SJohn Forte 1272fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - login " 1273fcf3ce44SJohn Forte "redirection invalid", icp->conn_oid); 1274fcf3ce44SJohn Forte 1275fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1276fcf3ce44SJohn Forte } 1277fcf3ce44SJohn Forte text = value_end; 1278fcf3ce44SJohn Forte } else if (iscsi_find_key_value("TargetPortalGroupTag", 1279fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1280fcf3ce44SJohn Forte /* 1281fcf3ce44SJohn Forte * We should have already obtained this via 1282fcf3ce44SJohn Forte * discovery. We've already picked an isid, 1283fcf3ce44SJohn Forte * so the most we can do is confirm we reached 1284fcf3ce44SJohn Forte * the portal group we were expecting to. 1285fcf3ce44SJohn Forte */ 1286fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1287fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1288fcf3ce44SJohn Forte } 1289fcf3ce44SJohn Forte if (isp->sess_tpgt_conf != ISCSI_DEFAULT_TPGT) { 1290fcf3ce44SJohn Forte if (tmp != isp->sess_tpgt_conf) { 1291fcf3ce44SJohn Forte 1292fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - target portal " 1293fcf3ce44SJohn Forte "tag mismatch, expected:%d received:%lu", icp->conn_oid, 1294fcf3ce44SJohn Forte isp->sess_tpgt_conf, tmp); 1295fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1296fcf3ce44SJohn Forte 1297fcf3ce44SJohn Forte } 1298fcf3ce44SJohn Forte } 1299fcf3ce44SJohn Forte isp->sess_tpgt_nego = (int)tmp; 1300fcf3ce44SJohn Forte text = value_end; 1301fcf3ce44SJohn Forte 1302fcf3ce44SJohn Forte } else if (iscsi_find_key_value("InitialR2T", 1303fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1304fcf3ce44SJohn Forte 1305fcf3ce44SJohn Forte /* 1306fcf3ce44SJohn Forte * iSCSI RFC section 12.10 states that 1307fcf3ce44SJohn Forte * InitialR2T is Irrelevant for a 1308fcf3ce44SJohn Forte * discovery session. 1309fcf3ce44SJohn Forte */ 1310fcf3ce44SJohn Forte if (isp->sess_type == 1311fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1312fcf3ce44SJohn Forte /* EMPTY */ 1313fcf3ce44SJohn Forte } else if (value == NULL) { 1314fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1315fcf3ce44SJohn Forte "login failed - InitialR2T is " 1316fcf3ce44SJohn Forte "invalid - protocol error", 1317fcf3ce44SJohn Forte icp->conn_oid); 1318fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1319fcf3ce44SJohn Forte } else if (strcmp(value, "Yes") == 0) { 1320fcf3ce44SJohn Forte icp->conn_params.initial_r2t = B_TRUE; 1321fcf3ce44SJohn Forte } else if (strcmp(value, "No") == 0) { 1322fcf3ce44SJohn Forte icp->conn_params.initial_r2t = B_FALSE; 1323fcf3ce44SJohn Forte } else { 1324fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1325fcf3ce44SJohn Forte "login failed - InitialR2T is " 1326fcf3ce44SJohn Forte "invalid - protocol error", 1327fcf3ce44SJohn Forte icp->conn_oid); 1328fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1329fcf3ce44SJohn Forte } 1330fcf3ce44SJohn Forte text = value_end; 1331fcf3ce44SJohn Forte 1332fcf3ce44SJohn Forte } else if (iscsi_find_key_value("ImmediateData", 1333fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1334fcf3ce44SJohn Forte 1335fcf3ce44SJohn Forte /* 1336fcf3ce44SJohn Forte * iSCSI RFC section 12.11 states that 1337fcf3ce44SJohn Forte * ImmediateData is Irrelevant for a 1338fcf3ce44SJohn Forte * discovery session. 1339fcf3ce44SJohn Forte */ 1340fcf3ce44SJohn Forte if (isp->sess_type == 1341fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1342fcf3ce44SJohn Forte /* EMPTY */ 1343fcf3ce44SJohn Forte } else if (value == NULL) { 1344fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1345fcf3ce44SJohn Forte "login failed - ImmediateData is " 1346fcf3ce44SJohn Forte "invalid - protocol error", 1347fcf3ce44SJohn Forte icp->conn_oid); 1348fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1349fcf3ce44SJohn Forte } else if (strcmp(value, "Yes") == 0) { 1350fcf3ce44SJohn Forte icp->conn_params.immediate_data = 1; 1351fcf3ce44SJohn Forte } else if (strcmp(value, "No") == 0) { 1352fcf3ce44SJohn Forte icp->conn_params.immediate_data = 0; 1353fcf3ce44SJohn Forte } else { 1354fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1355fcf3ce44SJohn Forte "login failed - ImmediateData is " 1356fcf3ce44SJohn Forte "invalid - protocol error", 1357fcf3ce44SJohn Forte icp->conn_oid); 1358fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1359fcf3ce44SJohn Forte } 1360fcf3ce44SJohn Forte text = value_end; 1361fcf3ce44SJohn Forte 1362fcf3ce44SJohn Forte } else if (iscsi_find_key_value( 1363fcf3ce44SJohn Forte "MaxRecvDataSegmentLength", text, end, 1364fcf3ce44SJohn Forte &value, &value_end)) { 1365fcf3ce44SJohn Forte 1366fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1367fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1368fcf3ce44SJohn Forte "login failed - MaxRecvDataSegment" 1369fcf3ce44SJohn Forte "Length is invalid - protocol " 1370fcf3ce44SJohn Forte "error", icp->conn_oid); 1371fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1372fcf3ce44SJohn Forte } 1373fcf3ce44SJohn Forte icp->conn_params.max_recv_data_seg_len = 1374fcf3ce44SJohn Forte icp->conn_params.max_xmit_data_seg_len = 1375fcf3ce44SJohn Forte (int)tmp; 1376fcf3ce44SJohn Forte 1377fcf3ce44SJohn Forte text = value_end; 1378fcf3ce44SJohn Forte } else if (iscsi_find_key_value("FirstBurstLength", 1379fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1380fcf3ce44SJohn Forte 1381fcf3ce44SJohn Forte /* 1382fcf3ce44SJohn Forte * iSCSI RFC section 12.14 states that 1383fcf3ce44SJohn Forte * FirstBurstLength is Irrelevant if 1384fcf3ce44SJohn Forte * InitialR2T=Yes and ImmediateData=No 1385fcf3ce44SJohn Forte * or is this is a discovery session. 1386fcf3ce44SJohn Forte */ 1387fcf3ce44SJohn Forte if ((isp->sess_type == 1388fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY)) { 1389fcf3ce44SJohn Forte /* EMPTY */ 1390fcf3ce44SJohn Forte } else if (value && 1391fcf3ce44SJohn Forte (strcmp(value, "Irrelevant") == 0)) { 1392fcf3ce44SJohn Forte /* irrelevant */ 1393fcf3ce44SJohn Forte fbl_irrelevant = B_TRUE; 1394fcf3ce44SJohn Forte } else if (ddi_strtoul( 1395fcf3ce44SJohn Forte value, &tmpe, 0, &tmp) != 0) { 1396fcf3ce44SJohn Forte /* bad value */ 1397fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1398fcf3ce44SJohn Forte "login failed - FirstBurstLength" 1399fcf3ce44SJohn Forte "is invalid - protocol error", 1400fcf3ce44SJohn Forte icp->conn_oid); 1401fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1402fcf3ce44SJohn Forte } else { 1403fcf3ce44SJohn Forte /* good value */ 1404fcf3ce44SJohn Forte icp->conn_params.first_burst_length = 1405fcf3ce44SJohn Forte (int)tmp; 1406fcf3ce44SJohn Forte } 1407fcf3ce44SJohn Forte text = value_end; 1408fcf3ce44SJohn Forte } else if (iscsi_find_key_value("MaxBurstLength", 1409fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1410fcf3ce44SJohn Forte /* 1411fcf3ce44SJohn Forte * iSCSI RFC section 12.13 states that 1412fcf3ce44SJohn Forte * MaxBurstLength is Irrelevant for a 1413fcf3ce44SJohn Forte * discovery session. 1414fcf3ce44SJohn Forte */ 1415fcf3ce44SJohn Forte if (isp->sess_type == 1416fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1417fcf3ce44SJohn Forte /* EMPTY */ 1418fcf3ce44SJohn Forte } else if (ddi_strtoul( 1419fcf3ce44SJohn Forte value, &tmpe, 0, &tmp) != 0) { 1420fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1421fcf3ce44SJohn Forte "login failed - MaxBurstLength" 1422fcf3ce44SJohn Forte "is invalid - protocol error", 1423fcf3ce44SJohn Forte icp->conn_oid); 1424fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1425fcf3ce44SJohn Forte } else { 1426fcf3ce44SJohn Forte icp->conn_params.max_burst_length = 1427fcf3ce44SJohn Forte (int)tmp; 1428fcf3ce44SJohn Forte } 1429fcf3ce44SJohn Forte 1430fcf3ce44SJohn Forte text = value_end; 1431fcf3ce44SJohn Forte 1432fcf3ce44SJohn Forte } else if (iscsi_find_key_value("HeaderDigest", 1433fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1434fcf3ce44SJohn Forte 1435fcf3ce44SJohn Forte if (strcmp(value, "None") == 0) { 1436fcf3ce44SJohn Forte if (icp->conn_params.header_digest != 1437fcf3ce44SJohn Forte ISCSI_DIGEST_CRC32C) { 1438fcf3ce44SJohn Forte icp->conn_params.header_digest = 1439fcf3ce44SJohn Forte ISCSI_DIGEST_NONE; 1440fcf3ce44SJohn Forte } else { 1441fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi " 1442fcf3ce44SJohn Forte "connection(%u) login " 1443fcf3ce44SJohn Forte "failed - HeaderDigest=" 1444fcf3ce44SJohn Forte "CRC32 is required, can't " 1445fcf3ce44SJohn Forte "accept %s", 1446fcf3ce44SJohn Forte icp->conn_oid, text); 1447fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1448fcf3ce44SJohn Forte } 1449fcf3ce44SJohn Forte } else if (strcmp(value, "CRC32C") == 0) { 1450fcf3ce44SJohn Forte if (icp->conn_params.header_digest != 1451fcf3ce44SJohn Forte ISCSI_DIGEST_NONE) { 1452fcf3ce44SJohn Forte icp->conn_params.header_digest = 1453fcf3ce44SJohn Forte ISCSI_DIGEST_CRC32C; 1454fcf3ce44SJohn Forte } else { 1455fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi " 1456fcf3ce44SJohn Forte "connection(%u) login " 1457fcf3ce44SJohn Forte "failed - HeaderDigest=" 1458fcf3ce44SJohn Forte "None is required, can't " 1459fcf3ce44SJohn Forte "accept %s", 1460fcf3ce44SJohn Forte icp->conn_oid, text); 1461fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1462fcf3ce44SJohn Forte } 1463fcf3ce44SJohn Forte } else { 1464fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1465fcf3ce44SJohn Forte "login failed - HeaderDigest " 1466fcf3ce44SJohn Forte "can't accept %s", icp->conn_oid, 1467fcf3ce44SJohn Forte text); 1468fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1469fcf3ce44SJohn Forte } 1470fcf3ce44SJohn Forte text = value_end; 1471fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DataDigest", text, 1472fcf3ce44SJohn Forte end, &value, &value_end)) { 1473fcf3ce44SJohn Forte 1474fcf3ce44SJohn Forte if (strcmp(value, "None") == 0) { 1475fcf3ce44SJohn Forte if (icp->conn_params.data_digest != 1476fcf3ce44SJohn Forte ISCSI_DIGEST_CRC32C) { 1477fcf3ce44SJohn Forte icp->conn_params.data_digest = 1478fcf3ce44SJohn Forte ISCSI_DIGEST_NONE; 1479fcf3ce44SJohn Forte } else { 1480fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi " 1481fcf3ce44SJohn Forte "connection(%u) login " 1482fcf3ce44SJohn Forte "failed - DataDigest=" 1483fcf3ce44SJohn Forte "CRC32C is required, " 1484fcf3ce44SJohn Forte "can't accept %s", 1485fcf3ce44SJohn Forte icp->conn_oid, text); 1486fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1487fcf3ce44SJohn Forte } 1488fcf3ce44SJohn Forte } else if (strcmp(value, "CRC32C") == 0) { 1489fcf3ce44SJohn Forte if (icp->conn_params.data_digest != 1490fcf3ce44SJohn Forte ISCSI_DIGEST_NONE) { 1491fcf3ce44SJohn Forte icp->conn_params.data_digest = 1492fcf3ce44SJohn Forte ISCSI_DIGEST_CRC32C; 1493fcf3ce44SJohn Forte } else { 1494fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi " 1495fcf3ce44SJohn Forte "connection(%u) login " 1496fcf3ce44SJohn Forte "failed - DataDigest=None " 1497fcf3ce44SJohn Forte "is required, can't " 1498fcf3ce44SJohn Forte "accept %s", 1499fcf3ce44SJohn Forte icp->conn_oid, text); 1500fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1501fcf3ce44SJohn Forte } 1502fcf3ce44SJohn Forte } else { 1503fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1504fcf3ce44SJohn Forte "login failed - can't accept %s", 1505fcf3ce44SJohn Forte icp->conn_oid, text); 1506fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1507fcf3ce44SJohn Forte } 1508fcf3ce44SJohn Forte text = value_end; 1509fcf3ce44SJohn Forte 1510fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DefaultTime2Wait", 1511fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1512fcf3ce44SJohn Forte 1513fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1514fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1515fcf3ce44SJohn Forte "login failed - DefaultTime2Wait " 1516fcf3ce44SJohn Forte "is invalid - protocol error", 1517fcf3ce44SJohn Forte icp->conn_oid); 1518fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1519fcf3ce44SJohn Forte } 1520fcf3ce44SJohn Forte icp->conn_params.default_time_to_wait = 1521fcf3ce44SJohn Forte (int)tmp; 1522fcf3ce44SJohn Forte 1523fcf3ce44SJohn Forte text = value_end; 1524fcf3ce44SJohn Forte 1525fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DefaultTime2Retain", 1526fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1527fcf3ce44SJohn Forte 1528fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1529fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1530fcf3ce44SJohn Forte "login failed - DefaultTime2Retain " 1531fcf3ce44SJohn Forte "is invalid - protocol error", 1532fcf3ce44SJohn Forte icp->conn_oid); 1533fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1534fcf3ce44SJohn Forte } 1535fcf3ce44SJohn Forte icp->conn_params.default_time_to_retain = 1536fcf3ce44SJohn Forte (int)tmp; 1537fcf3ce44SJohn Forte 1538fcf3ce44SJohn Forte text = value_end; 1539fcf3ce44SJohn Forte 1540fcf3ce44SJohn Forte } else if (iscsi_find_key_value("OFMarker", text, 1541fcf3ce44SJohn Forte end, &value, &value_end)) { 1542fcf3ce44SJohn Forte 1543fcf3ce44SJohn Forte /* 1544fcf3ce44SJohn Forte * result function is AND, target must 1545fcf3ce44SJohn Forte * honor our No 1546fcf3ce44SJohn Forte */ 1547fcf3ce44SJohn Forte text = value_end; 1548fcf3ce44SJohn Forte 1549fcf3ce44SJohn Forte } else if (iscsi_find_key_value("OFMarkInt", text, 1550fcf3ce44SJohn Forte end, &value, &value_end)) { 1551fcf3ce44SJohn Forte 1552fcf3ce44SJohn Forte /* 1553fcf3ce44SJohn Forte * we don't do markers, so we don't care 1554fcf3ce44SJohn Forte */ 1555fcf3ce44SJohn Forte text = value_end; 1556fcf3ce44SJohn Forte 1557fcf3ce44SJohn Forte } else if (iscsi_find_key_value("IFMarker", text, 1558fcf3ce44SJohn Forte end, &value, &value_end)) { 1559fcf3ce44SJohn Forte 1560fcf3ce44SJohn Forte /* 1561fcf3ce44SJohn Forte * result function is AND, target must 1562fcf3ce44SJohn Forte * honor our No 1563fcf3ce44SJohn Forte */ 1564fcf3ce44SJohn Forte text = value_end; 1565fcf3ce44SJohn Forte 1566fcf3ce44SJohn Forte } else if (iscsi_find_key_value("IFMarkInt", text, 1567fcf3ce44SJohn Forte end, &value, &value_end)) { 1568fcf3ce44SJohn Forte 1569fcf3ce44SJohn Forte /* 1570fcf3ce44SJohn Forte * we don't do markers, so we don't care 1571fcf3ce44SJohn Forte */ 1572fcf3ce44SJohn Forte text = value_end; 1573fcf3ce44SJohn Forte 1574fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DataPDUInOrder", 1575fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1576fcf3ce44SJohn Forte 1577fcf3ce44SJohn Forte /* 1578fcf3ce44SJohn Forte * iSCSI RFC section 12.18 states that 1579fcf3ce44SJohn Forte * DataPDUInOrder is Irrelevant for a 1580fcf3ce44SJohn Forte * discovery session. 1581fcf3ce44SJohn Forte */ 1582fcf3ce44SJohn Forte if (isp->sess_type == 1583fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1584fcf3ce44SJohn Forte /* EMPTY */ 1585fcf3ce44SJohn Forte } else if (value == NULL) { 1586fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1587fcf3ce44SJohn Forte "login failed - InitialR2T is " 1588fcf3ce44SJohn Forte "invalid - protocol error", 1589fcf3ce44SJohn Forte icp->conn_oid); 1590fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1591fcf3ce44SJohn Forte } else if (strcmp(value, "Yes") == 0) { 1592fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order = 1593fcf3ce44SJohn Forte B_TRUE; 1594fcf3ce44SJohn Forte } else if (strcmp(value, "No") == 0) { 1595fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order = 1596fcf3ce44SJohn Forte B_FALSE; 1597fcf3ce44SJohn Forte } else { 1598fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1599fcf3ce44SJohn Forte "login failed - InitialR2T is " 1600fcf3ce44SJohn Forte "invalid - protocol error", 1601fcf3ce44SJohn Forte icp->conn_oid); 1602fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1603fcf3ce44SJohn Forte } 1604fcf3ce44SJohn Forte text = value_end; 1605fcf3ce44SJohn Forte 1606fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DataSequenceInOrder", 1607fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1608fcf3ce44SJohn Forte 1609fcf3ce44SJohn Forte /* 1610fcf3ce44SJohn Forte * iSCSI RFC section 12.19 states that 1611fcf3ce44SJohn Forte * DataSequenceInOrder is Irrelevant for a 1612fcf3ce44SJohn Forte * discovery session. 1613fcf3ce44SJohn Forte */ 1614fcf3ce44SJohn Forte if (isp->sess_type == 1615fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1616fcf3ce44SJohn Forte /* EMPTY */ 1617fcf3ce44SJohn Forte } else if (value == NULL) { 1618fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1619fcf3ce44SJohn Forte "login failed - InitialR2T is " 1620fcf3ce44SJohn Forte "invalid - protocol error", 1621fcf3ce44SJohn Forte icp->conn_oid); 1622fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1623fcf3ce44SJohn Forte } else if (strcmp(value, "Yes") == 0) { 1624fcf3ce44SJohn Forte icp->conn_params. 1625fcf3ce44SJohn Forte data_sequence_in_order = B_TRUE; 1626fcf3ce44SJohn Forte } else if (strcmp(value, "No") == 0) { 1627fcf3ce44SJohn Forte icp->conn_params. 1628fcf3ce44SJohn Forte data_sequence_in_order = B_FALSE; 1629fcf3ce44SJohn Forte } else { 1630fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1631fcf3ce44SJohn Forte "login failed - InitialR2T is " 1632fcf3ce44SJohn Forte "invalid - protocol error", 1633fcf3ce44SJohn Forte icp->conn_oid); 1634fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1635fcf3ce44SJohn Forte } 1636fcf3ce44SJohn Forte text = value_end; 1637fcf3ce44SJohn Forte 1638fcf3ce44SJohn Forte } else if (iscsi_find_key_value("MaxOutstandingR2T", 1639fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1640fcf3ce44SJohn Forte 1641fcf3ce44SJohn Forte /* 1642fcf3ce44SJohn Forte * iSCSI RFC section 12.17 states that 1643fcf3ce44SJohn Forte * MaxOutstandingR2T is Irrelevant for a 1644fcf3ce44SJohn Forte * discovery session. 1645fcf3ce44SJohn Forte */ 1646fcf3ce44SJohn Forte if (isp->sess_type == 1647fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1648fcf3ce44SJohn Forte /* EMPTY */ 1649fcf3ce44SJohn Forte } else if (strcmp(value, "1")) { 1650fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1651fcf3ce44SJohn Forte "login failed - can't accept " 1652fcf3ce44SJohn Forte "MaxOutstandingR2T %s", 1653fcf3ce44SJohn Forte icp->conn_oid, value); 1654fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1655fcf3ce44SJohn Forte } 1656fcf3ce44SJohn Forte text = value_end; 1657fcf3ce44SJohn Forte 1658fcf3ce44SJohn Forte } else if (iscsi_find_key_value("MaxConnections", 1659fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1660fcf3ce44SJohn Forte 1661fcf3ce44SJohn Forte /* 1662fcf3ce44SJohn Forte * iSCSI RFC section 12.2 states that 1663fcf3ce44SJohn Forte * MaxConnections is Irrelevant for a 1664fcf3ce44SJohn Forte * discovery session. 1665fcf3ce44SJohn Forte */ 1666fcf3ce44SJohn Forte if (isp->sess_type == 1667fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1668fcf3ce44SJohn Forte /* EMPTY */ 1669fcf3ce44SJohn Forte } else if (strcmp(value, "1")) { 1670fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1671fcf3ce44SJohn Forte "login failed - can't accept " 1672fcf3ce44SJohn Forte "MaxConnections %s", 1673fcf3ce44SJohn Forte icp->conn_oid, value); 1674fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1675fcf3ce44SJohn Forte } 1676fcf3ce44SJohn Forte text = value_end; 1677fcf3ce44SJohn Forte 1678fcf3ce44SJohn Forte } else if (iscsi_find_key_value("ErrorRecoveryLevel", 1679fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1680fcf3ce44SJohn Forte 1681fcf3ce44SJohn Forte if (strcmp(value, "0")) { 1682fcf3ce44SJohn Forte 1683fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1684fcf3ce44SJohn Forte "login failed - can't accept " 1685fcf3ce44SJohn Forte "ErrorRecoveryLevel %s", 1686fcf3ce44SJohn Forte icp->conn_oid, value); 1687fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1688fcf3ce44SJohn Forte } 1689fcf3ce44SJohn Forte text = value_end; 1690fcf3ce44SJohn Forte 1691fcf3ce44SJohn Forte } else { 1692fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1693fcf3ce44SJohn Forte "login failed - ignoring login " 1694fcf3ce44SJohn Forte "parameter %s", icp->conn_oid, value); 1695fcf3ce44SJohn Forte text = value_end; 1696fcf3ce44SJohn Forte } 1697fcf3ce44SJohn Forte break; 1698fcf3ce44SJohn Forte default: 1699fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1700fcf3ce44SJohn Forte } 1701fcf3ce44SJohn Forte } 1702fcf3ce44SJohn Forte 1703fcf3ce44SJohn Forte /* 1704fcf3ce44SJohn Forte * iSCSI RFC section 12.14 states that 1705fcf3ce44SJohn Forte * FirstBurstLength is Irrelevant if 1706fcf3ce44SJohn Forte * InitialR2T=Yes and ImmediateData=No. 1707fcf3ce44SJohn Forte * This is a final check to make sure 1708fcf3ce44SJohn Forte * the array didn't make a protocol 1709fcf3ce44SJohn Forte * violation. 1710fcf3ce44SJohn Forte */ 1711fcf3ce44SJohn Forte if ((fbl_irrelevant == B_TRUE) && 1712fcf3ce44SJohn Forte ((icp->conn_params.initial_r2t != B_TRUE) || 1713fcf3ce44SJohn Forte (icp->conn_params.immediate_data != B_FALSE))) { 1714fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1715fcf3ce44SJohn Forte "FirstBurstLength=Irrelevant and (InitialR2T!=Yes or " 1716fcf3ce44SJohn Forte "ImmediateData!=No) - protocol error", icp->conn_oid); 1717fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1718fcf3ce44SJohn Forte } 1719fcf3ce44SJohn Forte 1720fcf3ce44SJohn Forte if (icp->conn_current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE) { 1721fcf3ce44SJohn Forte switch (iscsiAuthClientRecvEnd(auth_client, iscsi_null_callback, 1722fcf3ce44SJohn Forte (void *)isp, NULL)) { 1723fcf3ce44SJohn Forte case iscsiAuthStatusContinue: 1724fcf3ce44SJohn Forte /* 1725fcf3ce44SJohn Forte * continue sending PDUs 1726fcf3ce44SJohn Forte */ 1727fcf3ce44SJohn Forte break; 1728fcf3ce44SJohn Forte 1729fcf3ce44SJohn Forte case iscsiAuthStatusPass: 1730fcf3ce44SJohn Forte break; 1731fcf3ce44SJohn Forte 1732fcf3ce44SJohn Forte case iscsiAuthStatusInProgress: 1733fcf3ce44SJohn Forte /* 1734fcf3ce44SJohn Forte * this should only occur if we were authenticating the 1735fcf3ce44SJohn Forte * target, which we don't do yet, so treat this as an 1736fcf3ce44SJohn Forte * error. 1737fcf3ce44SJohn Forte */ 1738fcf3ce44SJohn Forte case iscsiAuthStatusNoError: 1739fcf3ce44SJohn Forte /* 1740fcf3ce44SJohn Forte * treat this as an error, since we should get a 1741fcf3ce44SJohn Forte * different code 1742fcf3ce44SJohn Forte */ 1743fcf3ce44SJohn Forte case iscsiAuthStatusError: 1744fcf3ce44SJohn Forte case iscsiAuthStatusFail: 1745fcf3ce44SJohn Forte default: 1746fcf3ce44SJohn Forte debug_status = 0; 1747fcf3ce44SJohn Forte 1748fcf3ce44SJohn Forte if (iscsiAuthClientGetDebugStatus(auth_client, 1749fcf3ce44SJohn Forte &debug_status) != iscsiAuthStatusNoError) { 1750fcf3ce44SJohn Forte 1751fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1752fcf3ce44SJohn Forte "failed - authentication failed with " 1753fcf3ce44SJohn Forte "target (%s)", icp->conn_oid, 1754fcf3ce44SJohn Forte iscsiAuthClientDebugStatusToText( 1755fcf3ce44SJohn Forte debug_status)); 1756fcf3ce44SJohn Forte 1757fcf3ce44SJohn Forte } else { 1758fcf3ce44SJohn Forte 1759fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1760fcf3ce44SJohn Forte "failed - authentication failed with " 1761fcf3ce44SJohn Forte "target", icp->conn_oid); 1762fcf3ce44SJohn Forte 1763fcf3ce44SJohn Forte } 1764fcf3ce44SJohn Forte return (ISCSI_STATUS_AUTHENTICATION_FAILED); 1765fcf3ce44SJohn Forte } 1766fcf3ce44SJohn Forte } 1767fcf3ce44SJohn Forte 1768fcf3ce44SJohn Forte /* 1769fcf3ce44SJohn Forte * record some of the PDU fields for later use 1770fcf3ce44SJohn Forte */ 1771fcf3ce44SJohn Forte isp->sess_tsid = ntohs(ilrhp->tsid); 1772fcf3ce44SJohn Forte isp->sess_expcmdsn = ntohl(ilrhp->expcmdsn); 1773fcf3ce44SJohn Forte isp->sess_maxcmdsn = ntohl(ilrhp->maxcmdsn); 1774fcf3ce44SJohn Forte if (ilrhp->status_class == ISCSI_STATUS_CLASS_SUCCESS) { 1775fcf3ce44SJohn Forte icp->conn_expstatsn = ntohl(ilrhp->statsn) + 1; 1776fcf3ce44SJohn Forte } 1777fcf3ce44SJohn Forte 1778fcf3ce44SJohn Forte if (transit) { 1779fcf3ce44SJohn Forte /* 1780fcf3ce44SJohn Forte * advance to the next stage 1781fcf3ce44SJohn Forte */ 1782fcf3ce44SJohn Forte icp->conn_partial_response = 0; 1783fcf3ce44SJohn Forte icp->conn_current_stage = 1784fcf3ce44SJohn Forte ilrhp->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; 1785fcf3ce44SJohn Forte } else { 1786fcf3ce44SJohn Forte /* 1787fcf3ce44SJohn Forte * we got a partial response, don't advance, more 1788fcf3ce44SJohn Forte * negotiation to do 1789fcf3ce44SJohn Forte */ 1790fcf3ce44SJohn Forte icp->conn_partial_response = 1; 1791fcf3ce44SJohn Forte } 1792fcf3ce44SJohn Forte 1793fcf3ce44SJohn Forte /* 1794fcf3ce44SJohn Forte * this PDU is ok, though the login process 1795fcf3ce44SJohn Forte * may not be done yet 1796fcf3ce44SJohn Forte */ 1797fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 1798fcf3ce44SJohn Forte } 1799fcf3ce44SJohn Forte 1800fcf3ce44SJohn Forte /* 1801fcf3ce44SJohn Forte * iscsi_add_text - caller is assumed to be well-behaved and passing NUL 1802fcf3ce44SJohn Forte * terminated strings 1803fcf3ce44SJohn Forte */ 1804fcf3ce44SJohn Forte int 180530e7468fSPeter Dunlap iscsi_add_text(idm_pdu_t *text_pdu, int max_data_length, 1806fcf3ce44SJohn Forte char *param, char *value) 1807fcf3ce44SJohn Forte { 1808fcf3ce44SJohn Forte int param_len = 0; 1809fcf3ce44SJohn Forte int value_len = 0; 1810fcf3ce44SJohn Forte int length = 0; 1811fcf3ce44SJohn Forte int pdu_length = 0; 1812fcf3ce44SJohn Forte char *text = NULL; 1813fcf3ce44SJohn Forte char *end = NULL; 1814fcf3ce44SJohn Forte 181530e7468fSPeter Dunlap ASSERT(text_pdu != NULL); 1816fcf3ce44SJohn Forte ASSERT(param != NULL); 1817fcf3ce44SJohn Forte ASSERT(value != NULL); 1818fcf3ce44SJohn Forte 1819fcf3ce44SJohn Forte param_len = strlen(param); 1820fcf3ce44SJohn Forte value_len = strlen(value); 1821fcf3ce44SJohn Forte /* param, separator, value, and trailing NULL */ 1822fcf3ce44SJohn Forte length = param_len + 1 + value_len + 1; 182330e7468fSPeter Dunlap pdu_length = text_pdu->isp_datalen; 182430e7468fSPeter Dunlap text = (char *)text_pdu->isp_data + pdu_length; 182530e7468fSPeter Dunlap end = (char *)text_pdu->isp_data + max_data_length; 1826fcf3ce44SJohn Forte pdu_length += length; 1827fcf3ce44SJohn Forte 1828fcf3ce44SJohn Forte if (text + length >= end) { 1829fcf3ce44SJohn Forte return (0); 1830fcf3ce44SJohn Forte } 1831fcf3ce44SJohn Forte 1832fcf3ce44SJohn Forte /* param */ 1833fcf3ce44SJohn Forte (void) strncpy(text, param, param_len); 1834fcf3ce44SJohn Forte text += param_len; 1835fcf3ce44SJohn Forte 1836fcf3ce44SJohn Forte /* separator */ 1837fcf3ce44SJohn Forte *text++ = ISCSI_TEXT_SEPARATOR; 1838fcf3ce44SJohn Forte 1839fcf3ce44SJohn Forte /* value */ 1840fcf3ce44SJohn Forte (void) strncpy(text, value, value_len); 1841fcf3ce44SJohn Forte text += value_len; 1842fcf3ce44SJohn Forte 1843fcf3ce44SJohn Forte /* NULL */ 1844fcf3ce44SJohn Forte *text++ = '\0'; 1845fcf3ce44SJohn Forte 1846fcf3ce44SJohn Forte /* update the length in the PDU header */ 184730e7468fSPeter Dunlap text_pdu->isp_datalen = pdu_length; 184830e7468fSPeter Dunlap hton24(text_pdu->isp_hdr->dlength, pdu_length); 1849fcf3ce44SJohn Forte 1850fcf3ce44SJohn Forte return (1); 1851fcf3ce44SJohn Forte } 1852fcf3ce44SJohn Forte 1853fcf3ce44SJohn Forte /* 1854fcf3ce44SJohn Forte * iscsi_get_next_text - get the next line of text from the given data 1855fcf3ce44SJohn Forte * buffer. This function searches from the address given for the 1856fcf3ce44SJohn Forte * curr_text parameter. If curr_text_parameter is NULL return first 1857fcf3ce44SJohn Forte * line in buffer. The return value is the address of the next line 1858fcf3ce44SJohn Forte * based upon where curr_text is located. 1859fcf3ce44SJohn Forte * 1860fcf3ce44SJohn Forte */ 1861fcf3ce44SJohn Forte char * 1862fcf3ce44SJohn Forte iscsi_get_next_text(char *data, int max_data_length, char *curr_text) 1863fcf3ce44SJohn Forte { 1864fcf3ce44SJohn Forte char *curr_data; 1865fcf3ce44SJohn Forte 1866fcf3ce44SJohn Forte ASSERT(data != NULL); 1867fcf3ce44SJohn Forte 1868fcf3ce44SJohn Forte /* check if any data exists, if not return */ 1869fcf3ce44SJohn Forte if (max_data_length == 0) { 1870fcf3ce44SJohn Forte return (NULL); 1871fcf3ce44SJohn Forte } 1872fcf3ce44SJohn Forte 1873fcf3ce44SJohn Forte /* handle first call to this function */ 1874fcf3ce44SJohn Forte if (curr_text == NULL) { 1875fcf3ce44SJohn Forte return (data); 1876fcf3ce44SJohn Forte } 1877fcf3ce44SJohn Forte 1878fcf3ce44SJohn Forte /* move to next text string */ 1879fcf3ce44SJohn Forte curr_data = curr_text; 1880fcf3ce44SJohn Forte while ((curr_data < (data + max_data_length)) && *curr_data) { 1881fcf3ce44SJohn Forte curr_data++; 1882fcf3ce44SJohn Forte } 1883fcf3ce44SJohn Forte curr_data++; /* go past the NULL to the next entry */ 1884fcf3ce44SJohn Forte 1885fcf3ce44SJohn Forte /* check whether data end reached */ 1886fcf3ce44SJohn Forte if (curr_data >= (data + max_data_length)) { 1887fcf3ce44SJohn Forte return (NULL); 1888fcf3ce44SJohn Forte } 1889fcf3ce44SJohn Forte 1890fcf3ce44SJohn Forte return (curr_data); 1891fcf3ce44SJohn Forte } 1892fcf3ce44SJohn Forte 1893fcf3ce44SJohn Forte 1894fcf3ce44SJohn Forte /* 1895fcf3ce44SJohn Forte * iscsi_find_key_value - 1896fcf3ce44SJohn Forte * 1897fcf3ce44SJohn Forte */ 1898fcf3ce44SJohn Forte static int 1899fcf3ce44SJohn Forte iscsi_find_key_value(char *param, char *ihp, char *pdu_end, 1900fcf3ce44SJohn Forte char **value_start, char **value_end) 1901fcf3ce44SJohn Forte { 1902fcf3ce44SJohn Forte char *str = param; 1903fcf3ce44SJohn Forte char *text = ihp; 1904fcf3ce44SJohn Forte char *value = NULL; 1905fcf3ce44SJohn Forte 1906fcf3ce44SJohn Forte if (value_start) 1907fcf3ce44SJohn Forte *value_start = NULL; 1908fcf3ce44SJohn Forte if (value_end) 1909fcf3ce44SJohn Forte *value_end = NULL; 1910fcf3ce44SJohn Forte 1911fcf3ce44SJohn Forte /* 1912fcf3ce44SJohn Forte * make sure they contain the same bytes 1913fcf3ce44SJohn Forte */ 1914fcf3ce44SJohn Forte while (*str) { 1915fcf3ce44SJohn Forte if (text >= pdu_end) { 1916fcf3ce44SJohn Forte return (0); 1917fcf3ce44SJohn Forte } 1918fcf3ce44SJohn Forte if (*text == '\0') { 1919fcf3ce44SJohn Forte return (0); 1920fcf3ce44SJohn Forte } 1921fcf3ce44SJohn Forte if (*str != *text) { 1922fcf3ce44SJohn Forte return (0); 1923fcf3ce44SJohn Forte } 1924fcf3ce44SJohn Forte str++; 1925fcf3ce44SJohn Forte text++; 1926fcf3ce44SJohn Forte } 1927fcf3ce44SJohn Forte 1928fcf3ce44SJohn Forte if ((text >= pdu_end) || 1929fcf3ce44SJohn Forte (*text == '\0') || 1930fcf3ce44SJohn Forte (*text != ISCSI_TEXT_SEPARATOR)) { 1931fcf3ce44SJohn Forte return (0); 1932fcf3ce44SJohn Forte } 1933fcf3ce44SJohn Forte 1934fcf3ce44SJohn Forte /* 1935fcf3ce44SJohn Forte * find the value 1936fcf3ce44SJohn Forte */ 1937fcf3ce44SJohn Forte value = text + 1; 1938fcf3ce44SJohn Forte 1939fcf3ce44SJohn Forte /* 1940fcf3ce44SJohn Forte * find the end of the value 1941fcf3ce44SJohn Forte */ 1942fcf3ce44SJohn Forte while ((text < pdu_end) && (*text)) 1943fcf3ce44SJohn Forte text++; 1944fcf3ce44SJohn Forte 1945fcf3ce44SJohn Forte if (value_start) 1946fcf3ce44SJohn Forte *value_start = value; 1947fcf3ce44SJohn Forte if (value_end) 1948fcf3ce44SJohn Forte *value_end = text; 1949fcf3ce44SJohn Forte 1950fcf3ce44SJohn Forte return (1); 1951fcf3ce44SJohn Forte } 1952fcf3ce44SJohn Forte 1953fcf3ce44SJohn Forte 1954fcf3ce44SJohn Forte /* 1955fcf3ce44SJohn Forte * iscsi_update_address - This function is used on a login redirection. 1956fcf3ce44SJohn Forte * During the login redirection we are asked to switch to an IP address 1957fcf3ce44SJohn Forte * port different than the one we were logging into. 1958fcf3ce44SJohn Forte */ 1959fcf3ce44SJohn Forte static iscsi_status_t 1960fcf3ce44SJohn Forte iscsi_update_address(iscsi_conn_t *icp, char *in) 1961fcf3ce44SJohn Forte { 1962fcf3ce44SJohn Forte char *addr_str, *port_str, *tpgt_str; 1963fcf3ce44SJohn Forte int type; 1964fcf3ce44SJohn Forte struct hostent *hptr; 1965fcf3ce44SJohn Forte unsigned long tmp; 1966fcf3ce44SJohn Forte int error_num; 1967fcf3ce44SJohn Forte int port; 1968fcf3ce44SJohn Forte 1969fcf3ce44SJohn Forte ASSERT(icp != NULL); 1970fcf3ce44SJohn Forte ASSERT(in != NULL); 1971fcf3ce44SJohn Forte 1972fcf3ce44SJohn Forte /* parse login redirection response */ 1973fcf3ce44SJohn Forte if (parse_addr_port_tpgt(in, &addr_str, &type, 1974fcf3ce44SJohn Forte &port_str, &tpgt_str) == B_FALSE) { 1975fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1976fcf3ce44SJohn Forte } 1977fcf3ce44SJohn Forte 1978fcf3ce44SJohn Forte /* convert addr_str */ 1979fcf3ce44SJohn Forte hptr = kgetipnodebyname(addr_str, type, AI_ALL, &error_num); 1980fcf3ce44SJohn Forte if (!hptr) { 1981fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1982fcf3ce44SJohn Forte } 1983fcf3ce44SJohn Forte 1984fcf3ce44SJohn Forte /* convert port_str */ 1985fcf3ce44SJohn Forte if (port_str != NULL) { 1986fcf3ce44SJohn Forte (void) ddi_strtoul(port_str, NULL, 0, &tmp); 1987fcf3ce44SJohn Forte port = (int)tmp; 1988fcf3ce44SJohn Forte } else { 1989fcf3ce44SJohn Forte port = ISCSI_LISTEN_PORT; 1990fcf3ce44SJohn Forte } 1991fcf3ce44SJohn Forte 1992fcf3ce44SJohn Forte iscsid_addr_to_sockaddr(hptr->h_length, *hptr->h_addr_list, 1993fcf3ce44SJohn Forte port, &icp->conn_curr_addr.sin); 1994fcf3ce44SJohn Forte 1995fcf3ce44SJohn Forte kfreehostent(hptr); 1996fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 1997fcf3ce44SJohn Forte } 1998fcf3ce44SJohn Forte 199930e7468fSPeter Dunlap void 200030e7468fSPeter Dunlap iscsi_login_update_state(iscsi_conn_t *icp, iscsi_login_state_t next_state) 200130e7468fSPeter Dunlap { 200230e7468fSPeter Dunlap mutex_enter(&icp->conn_login_mutex); 200330e7468fSPeter Dunlap (void) iscsi_login_update_state_locked(icp, next_state); 200430e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex); 200530e7468fSPeter Dunlap } 200630e7468fSPeter Dunlap 200730e7468fSPeter Dunlap void 200830e7468fSPeter Dunlap iscsi_login_update_state_locked(iscsi_conn_t *icp, 200930e7468fSPeter Dunlap iscsi_login_state_t next_state) 201030e7468fSPeter Dunlap { 201130e7468fSPeter Dunlap ASSERT(mutex_owned(&icp->conn_login_mutex)); 201230e7468fSPeter Dunlap next_state = (next_state > LOGIN_MAX) ? LOGIN_MAX : next_state; 201330e7468fSPeter Dunlap idm_sm_audit_state_change(&icp->conn_state_audit, 201430e7468fSPeter Dunlap SAS_ISCSI_LOGIN, icp->conn_login_state, next_state); 201530e7468fSPeter Dunlap 201630e7468fSPeter Dunlap ISCSI_LOGIN_LOG(CE_NOTE, "iscsi_login_update_state conn %p %d -> %d", 201730e7468fSPeter Dunlap (void *)icp, icp->conn_login_state, next_state); 201830e7468fSPeter Dunlap 201930e7468fSPeter Dunlap icp->conn_login_state = next_state; 202030e7468fSPeter Dunlap cv_broadcast(&icp->conn_login_cv); 202130e7468fSPeter Dunlap } 202230e7468fSPeter Dunlap 202330e7468fSPeter Dunlap 2024fcf3ce44SJohn Forte 2025fcf3ce44SJohn Forte /* 2026fcf3ce44SJohn Forte * iscsi_null_callback - This callback may be used under certain 2027fcf3ce44SJohn Forte * conditions when authenticating a target, but I'm not sure what 2028fcf3ce44SJohn Forte * we need to do here. 2029fcf3ce44SJohn Forte */ 2030fcf3ce44SJohn Forte /* ARGSUSED */ 2031fcf3ce44SJohn Forte static void 2032fcf3ce44SJohn Forte iscsi_null_callback(void *user_handle, void *message_handle, int auth_status) 2033fcf3ce44SJohn Forte { 2034fcf3ce44SJohn Forte } 2035fcf3ce44SJohn Forte 2036fcf3ce44SJohn Forte 2037fcf3ce44SJohn Forte /* 2038fcf3ce44SJohn Forte * iscsi_login_failure_str - 2039fcf3ce44SJohn Forte * 2040fcf3ce44SJohn Forte */ 2041fcf3ce44SJohn Forte static char * 2042fcf3ce44SJohn Forte iscsi_login_failure_str(uchar_t status_class, uchar_t status_detail) 2043fcf3ce44SJohn Forte { 2044fcf3ce44SJohn Forte switch (status_class) { 2045fcf3ce44SJohn Forte case 0x00: 2046fcf3ce44SJohn Forte switch (status_detail) { 2047fcf3ce44SJohn Forte case 0x00: 2048fcf3ce44SJohn Forte return ("Login is proceeding okay."); 2049fcf3ce44SJohn Forte default: 2050fcf3ce44SJohn Forte break; 2051fcf3ce44SJohn Forte } 2052fcf3ce44SJohn Forte case 0x01: 2053fcf3ce44SJohn Forte switch (status_detail) { 2054fcf3ce44SJohn Forte case 0x01: 2055fcf3ce44SJohn Forte return ("Requested ITN has moved temporarily to " 2056fcf3ce44SJohn Forte "the address provided."); 2057fcf3ce44SJohn Forte case 0x02: 2058fcf3ce44SJohn Forte return ("Requested ITN has moved permanently to " 2059fcf3ce44SJohn Forte "the address provided."); 2060fcf3ce44SJohn Forte default: 2061fcf3ce44SJohn Forte break; 2062fcf3ce44SJohn Forte } 2063fcf3ce44SJohn Forte case 0x02: 2064fcf3ce44SJohn Forte switch (status_detail) { 2065fcf3ce44SJohn Forte case 0x00: 2066fcf3ce44SJohn Forte return ("Miscellaneous iSCSI initiator errors."); 2067fcf3ce44SJohn Forte case 0x01: 2068fcf3ce44SJohn Forte return ("Initiator could not be successfully " 2069fcf3ce44SJohn Forte "authenticated."); 2070fcf3ce44SJohn Forte case 0x02: 2071fcf3ce44SJohn Forte return ("Initiator is not allowed access to the " 2072fcf3ce44SJohn Forte "given target."); 2073fcf3ce44SJohn Forte case 0x03: 2074fcf3ce44SJohn Forte return ("Requested ITN does not exist at this " 2075fcf3ce44SJohn Forte "address."); 2076fcf3ce44SJohn Forte case 0x04: 2077fcf3ce44SJohn Forte return ("Requested ITN has been removed and no " 2078fcf3ce44SJohn Forte "forwarding address is provided."); 2079fcf3ce44SJohn Forte case 0x05: 2080fcf3ce44SJohn Forte return ("Requested iSCSI version range is not " 2081fcf3ce44SJohn Forte "supported by the target."); 2082fcf3ce44SJohn Forte case 0x06: 2083fcf3ce44SJohn Forte return ("No more connections can be accepted on " 2084fcf3ce44SJohn Forte "this Session ID (SSID)."); 2085fcf3ce44SJohn Forte case 0x07: 2086fcf3ce44SJohn Forte return ("Missing parameters (e.g., iSCSI initiator " 2087fcf3ce44SJohn Forte "and/or target name)."); 2088fcf3ce44SJohn Forte case 0x08: 2089fcf3ce44SJohn Forte return ("Target does not support session spanning " 2090fcf3ce44SJohn Forte "to this connection (address)."); 2091fcf3ce44SJohn Forte case 0x09: 2092fcf3ce44SJohn Forte return ("Target does not support this type of " 2093fcf3ce44SJohn Forte "session or not from this initiator."); 2094fcf3ce44SJohn Forte case 0x0A: 2095fcf3ce44SJohn Forte return ("Attempt to add a connection to a " 2096fcf3ce44SJohn Forte "nonexistent session."); 2097fcf3ce44SJohn Forte case 0x0B: 2098fcf3ce44SJohn Forte return ("Invalid request type during login."); 2099fcf3ce44SJohn Forte default: 2100fcf3ce44SJohn Forte break; 2101fcf3ce44SJohn Forte } 2102fcf3ce44SJohn Forte case 0x03: 2103fcf3ce44SJohn Forte switch (status_detail) { 2104fcf3ce44SJohn Forte case 0x00: 2105fcf3ce44SJohn Forte return ("Target hardware or software error."); 2106fcf3ce44SJohn Forte case 0x01: 2107fcf3ce44SJohn Forte return ("iSCSI service or target is not currently " 2108fcf3ce44SJohn Forte "operational."); 2109fcf3ce44SJohn Forte case 0x02: 2110fcf3ce44SJohn Forte return ("Target has insufficient session, connection " 2111fcf3ce44SJohn Forte "or other resources."); 2112fcf3ce44SJohn Forte default: 2113fcf3ce44SJohn Forte break; 2114fcf3ce44SJohn Forte } 2115fcf3ce44SJohn Forte } 2116fcf3ce44SJohn Forte return ("Unknown login response received."); 2117fcf3ce44SJohn Forte } 2118fcf3ce44SJohn Forte 2119fcf3ce44SJohn Forte 2120fcf3ce44SJohn Forte /* 2121fcf3ce44SJohn Forte * iscsi_login_connect - 2122fcf3ce44SJohn Forte */ 2123fcf3ce44SJohn Forte static iscsi_status_t 2124fcf3ce44SJohn Forte iscsi_login_connect(iscsi_conn_t *icp) 2125fcf3ce44SJohn Forte { 21260f1702c5SYu Xiangning iscsi_hba_t *ihp; 21270f1702c5SYu Xiangning iscsi_sess_t *isp; 21280f1702c5SYu Xiangning struct sockaddr *addr; 212930e7468fSPeter Dunlap idm_conn_req_t cr; 213030e7468fSPeter Dunlap idm_status_t rval; 2131d3d50737SRafael Vanoni clock_t lbolt; 2132fcf3ce44SJohn Forte 2133fcf3ce44SJohn Forte ASSERT(icp != NULL); 2134fcf3ce44SJohn Forte isp = icp->conn_sess; 2135fcf3ce44SJohn Forte ASSERT(isp != NULL); 2136fcf3ce44SJohn Forte ihp = isp->sess_hba; 2137fcf3ce44SJohn Forte ASSERT(ihp != NULL); 2138fcf3ce44SJohn Forte addr = &icp->conn_curr_addr.sin; 2139fcf3ce44SJohn Forte 214030e7468fSPeter Dunlap /* Make sure that scope_id is zero if it is an IPv6 address */ 214130e7468fSPeter Dunlap if (addr->sa_family == AF_INET6) { 214230e7468fSPeter Dunlap ((struct sockaddr_in6 *)addr)->sin6_scope_id = 0; 2143fcf3ce44SJohn Forte } 2144fcf3ce44SJohn Forte 214530e7468fSPeter Dunlap /* delay the connect process if required */ 214630e7468fSPeter Dunlap lbolt = ddi_get_lbolt(); 214730e7468fSPeter Dunlap if (lbolt < icp->conn_login_min) { 2148aff4bce5Syi zhang - Sun Microsystems - Beijing China if (icp->conn_login_max < icp->conn_login_min) { 2149aff4bce5Syi zhang - Sun Microsystems - Beijing China delay(icp->conn_login_max - lbolt); 2150aff4bce5Syi zhang - Sun Microsystems - Beijing China } else { 2151aff4bce5Syi zhang - Sun Microsystems - Beijing China delay(icp->conn_login_min - lbolt); 2152aff4bce5Syi zhang - Sun Microsystems - Beijing China } 2153fcf3ce44SJohn Forte } 2154fcf3ce44SJohn Forte 215530e7468fSPeter Dunlap /* Create IDM connection context */ 215630e7468fSPeter Dunlap cr.cr_domain = addr->sa_family; 215730e7468fSPeter Dunlap cr.cr_type = SOCK_STREAM; 215830e7468fSPeter Dunlap cr.cr_protocol = 0; 215930e7468fSPeter Dunlap cr.cr_bound = icp->conn_bound; 216030e7468fSPeter Dunlap cr.cr_li = icp->conn_sess->sess_hba->hba_li; 216130e7468fSPeter Dunlap cr.icr_conn_ops.icb_rx_misc = &iscsi_rx_misc_pdu; 216230e7468fSPeter Dunlap cr.icr_conn_ops.icb_rx_error = &iscsi_rx_error_pdu; 216330e7468fSPeter Dunlap cr.icr_conn_ops.icb_rx_scsi_rsp = &iscsi_rx_scsi_rsp; 216430e7468fSPeter Dunlap cr.icr_conn_ops.icb_client_notify = &iscsi_client_notify; 216530e7468fSPeter Dunlap cr.icr_conn_ops.icb_build_hdr = &iscsi_build_hdr; 216630e7468fSPeter Dunlap cr.icr_conn_ops.icb_task_aborted = &iscsi_task_aborted; 216730e7468fSPeter Dunlap bcopy(addr, &cr.cr_ini_dst_addr, 216830e7468fSPeter Dunlap sizeof (cr.cr_ini_dst_addr)); 216930e7468fSPeter Dunlap bcopy(&icp->conn_bound_addr, &cr.cr_bound_addr, 217030e7468fSPeter Dunlap sizeof (cr.cr_bound_addr)); 2171dedec472SJack Meng if (isp->sess_boot == B_TRUE) { 2172dedec472SJack Meng cr.cr_boot_conn = B_TRUE; 2173dedec472SJack Meng } else { 2174dedec472SJack Meng cr.cr_boot_conn = B_FALSE; 2175dedec472SJack Meng } 217630e7468fSPeter Dunlap 217730e7468fSPeter Dunlap /* 217830e7468fSPeter Dunlap * Allocate IDM connection context 217930e7468fSPeter Dunlap */ 218030e7468fSPeter Dunlap rval = idm_ini_conn_create(&cr, &icp->conn_ic); 218130e7468fSPeter Dunlap if (rval != IDM_STATUS_SUCCESS) { 218230e7468fSPeter Dunlap return (ISCSI_STATUS_LOGIN_FAILED); 2183fcf3ce44SJohn Forte } 2184fcf3ce44SJohn Forte 218530e7468fSPeter Dunlap icp->conn_ic->ic_handle = icp; 218630e7468fSPeter Dunlap 218730e7468fSPeter Dunlap /* 218830e7468fSPeter Dunlap * About to initiate connect, reset login state. 218930e7468fSPeter Dunlap */ 219030e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_START); 219130e7468fSPeter Dunlap 219230e7468fSPeter Dunlap /* 219330e7468fSPeter Dunlap * Make sure the connection doesn't go away until we are done with it. 219430e7468fSPeter Dunlap * This hold will prevent us from receiving a CN_CONNECT_DESTROY 219530e7468fSPeter Dunlap * notification on this connection until we are ready. 219630e7468fSPeter Dunlap */ 219730e7468fSPeter Dunlap idm_conn_hold(icp->conn_ic); 219830e7468fSPeter Dunlap 2199aff4bce5Syi zhang - Sun Microsystems - Beijing China /* 2200aff4bce5Syi zhang - Sun Microsystems - Beijing China * When iSCSI initiator to target IO timeout or connection failure 2201aff4bce5Syi zhang - Sun Microsystems - Beijing China * Connection retry is needed for normal operational session. 2202aff4bce5Syi zhang - Sun Microsystems - Beijing China */ 2203aff4bce5Syi zhang - Sun Microsystems - Beijing China if ((icp->conn_sess->sess_type == ISCSI_SESS_TYPE_NORMAL) && 2204aff4bce5Syi zhang - Sun Microsystems - Beijing China ((icp->conn_state == ISCSI_CONN_STATE_FAILED) || 2205aff4bce5Syi zhang - Sun Microsystems - Beijing China (icp->conn_state == ISCSI_CONN_STATE_POLLING))) { 2206aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.nonblock_socket = B_TRUE; 2207aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_max = 2208aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_login_max; 2209aff4bce5Syi zhang - Sun Microsystems - Beijing China if (icp->conn_state == ISCSI_CONN_STATE_POLLING) { 2210aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_interval = 2211aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_tunable_params.polling_login_delay; 2212aff4bce5Syi zhang - Sun Microsystems - Beijing China } else { 2213aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_interval = 2214aff4bce5Syi zhang - Sun Microsystems - Beijing China ISCSI_LOGIN_RETRY_DELAY; 2215aff4bce5Syi zhang - Sun Microsystems - Beijing China } 2216aff4bce5Syi zhang - Sun Microsystems - Beijing China 2217aff4bce5Syi zhang - Sun Microsystems - Beijing China } else { 2218aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.nonblock_socket = B_FALSE; 2219aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_max = 0; 2220aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_interval = 0; 2221aff4bce5Syi zhang - Sun Microsystems - Beijing China } 222230e7468fSPeter Dunlap /* 222330e7468fSPeter Dunlap * Attempt connection. Upon return we will either be ready to 222430e7468fSPeter Dunlap * login or disconnected. If idm_ini_conn_connect fails we 222530e7468fSPeter Dunlap * will eventually receive a CN_CONNECT_DESTROY at which point 222630e7468fSPeter Dunlap * we will destroy the connection allocated above (so there 222730e7468fSPeter Dunlap * is no need to explicitly free it here). 222830e7468fSPeter Dunlap */ 222930e7468fSPeter Dunlap rval = idm_ini_conn_connect(icp->conn_ic); 2230fcf3ce44SJohn Forte 223130e7468fSPeter Dunlap if (rval != IDM_STATUS_SUCCESS) { 2232fcf3ce44SJohn Forte cmn_err(CE_NOTE, "iscsi connection(%u) unable to " 2233fcf3ce44SJohn Forte "connect to target %s", icp->conn_oid, 2234fcf3ce44SJohn Forte icp->conn_sess->sess_name); 223530e7468fSPeter Dunlap idm_conn_rele(icp->conn_ic); 223630e7468fSPeter Dunlap } 2237fcf3ce44SJohn Forte 223830e7468fSPeter Dunlap return (rval == IDM_STATUS_SUCCESS ? 223930e7468fSPeter Dunlap ISCSI_STATUS_SUCCESS : ISCSI_STATUS_INTERNAL_ERROR); 224030e7468fSPeter Dunlap } 224130e7468fSPeter Dunlap 224230e7468fSPeter Dunlap /* 224330e7468fSPeter Dunlap * iscsi_login_disconnect 224430e7468fSPeter Dunlap */ 224530e7468fSPeter Dunlap static void 224630e7468fSPeter Dunlap iscsi_login_disconnect(iscsi_conn_t *icp) 224730e7468fSPeter Dunlap { 224830e7468fSPeter Dunlap /* Tell IDM to disconnect is if we are not already disconnect */ 224930e7468fSPeter Dunlap idm_ini_conn_disconnect_sync(icp->conn_ic); 225030e7468fSPeter Dunlap 225130e7468fSPeter Dunlap /* 225230e7468fSPeter Dunlap * The function above may return before the CN_CONNECT_LOST 225330e7468fSPeter Dunlap * notification. Wait for it. 225430e7468fSPeter Dunlap */ 225530e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 225630e7468fSPeter Dunlap while (icp->conn_state_idm_connected) 225730e7468fSPeter Dunlap cv_wait(&icp->conn_state_change, 225830e7468fSPeter Dunlap &icp->conn_state_mutex); 225930e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 226030e7468fSPeter Dunlap } 226130e7468fSPeter Dunlap 226230e7468fSPeter Dunlap /* 226330e7468fSPeter Dunlap * iscsi_notice_key_values - Create an nvlist containing the values 226430e7468fSPeter Dunlap * that have been negotiated for this connection and pass them down to 226530e7468fSPeter Dunlap * IDM so it can pick up any values that are important. 226630e7468fSPeter Dunlap */ 226730e7468fSPeter Dunlap static void 226830e7468fSPeter Dunlap iscsi_notice_key_values(iscsi_conn_t *icp) 226930e7468fSPeter Dunlap { 227030e7468fSPeter Dunlap nvlist_t *neg_nvl; 227130e7468fSPeter Dunlap int rc; 227230e7468fSPeter Dunlap 227330e7468fSPeter Dunlap rc = nvlist_alloc(&neg_nvl, NV_UNIQUE_NAME, KM_SLEEP); 227430e7468fSPeter Dunlap ASSERT(rc == 0); 227530e7468fSPeter Dunlap 227630e7468fSPeter Dunlap /* Only crc32c is supported so the digest logic is simple */ 227730e7468fSPeter Dunlap if (icp->conn_params.header_digest) { 227830e7468fSPeter Dunlap rc = nvlist_add_string(neg_nvl, "HeaderDigest", "crc32c"); 227930e7468fSPeter Dunlap } else { 228030e7468fSPeter Dunlap rc = nvlist_add_string(neg_nvl, "HeaderDigest", "none"); 2281fcf3ce44SJohn Forte } 228230e7468fSPeter Dunlap ASSERT(rc == 0); 2283fcf3ce44SJohn Forte 228430e7468fSPeter Dunlap if (icp->conn_params.data_digest) { 228530e7468fSPeter Dunlap rc = nvlist_add_string(neg_nvl, "DataDigest", "crc32c"); 228630e7468fSPeter Dunlap } else { 228730e7468fSPeter Dunlap rc = nvlist_add_string(neg_nvl, "DataDigest", "none"); 2288fcf3ce44SJohn Forte } 228930e7468fSPeter Dunlap ASSERT(rc == 0); 2290fcf3ce44SJohn Forte 229130e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "MaxRecvDataSegmentLength", 229230e7468fSPeter Dunlap (uint64_t)icp->conn_params.max_recv_data_seg_len); 229330e7468fSPeter Dunlap ASSERT(rc == 0); 229430e7468fSPeter Dunlap 229530e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "MaxBurstLength", 229630e7468fSPeter Dunlap (uint64_t)icp->conn_params.max_burst_length); 229730e7468fSPeter Dunlap ASSERT(rc == 0); 229830e7468fSPeter Dunlap 229930e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "MaxOutstandingR2T", 230030e7468fSPeter Dunlap (uint64_t)icp->conn_params.max_outstanding_r2t); 230130e7468fSPeter Dunlap ASSERT(rc == 0); 230230e7468fSPeter Dunlap 230330e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "ErrorRecoveryLevel", 230430e7468fSPeter Dunlap (uint64_t)icp->conn_params.error_recovery_level); 230530e7468fSPeter Dunlap ASSERT(rc == 0); 230630e7468fSPeter Dunlap 230730e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "DefaultTime2Wait", 230830e7468fSPeter Dunlap (uint64_t)icp->conn_params.default_time_to_wait); 230930e7468fSPeter Dunlap ASSERT(rc == 0); 231030e7468fSPeter Dunlap 231130e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "DefaultTime2Retain", 231230e7468fSPeter Dunlap (uint64_t)icp->conn_params.default_time_to_retain); 231330e7468fSPeter Dunlap ASSERT(rc == 0); 231430e7468fSPeter Dunlap 231530e7468fSPeter Dunlap /* Pass the list to IDM to examine, then free it */ 231630e7468fSPeter Dunlap idm_notice_key_values(icp->conn_ic, neg_nvl); 231730e7468fSPeter Dunlap nvlist_free(neg_nvl); 2318fcf3ce44SJohn Forte } 2319