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*904e51f6SJack Meng * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24fcf3ce44SJohn Forte * 25fcf3ce44SJohn Forte * iSCSI protocol login and enumeration 26fcf3ce44SJohn Forte */ 27fcf3ce44SJohn Forte 28fcf3ce44SJohn Forte #include "iscsi.h" 291a1a84a3SPeter Dunlap #include <sys/iscsi_protocol.h> 30fcf3ce44SJohn Forte #include <sys/scsi/adapters/iscsi_door.h> 31fcf3ce44SJohn Forte 3230e7468fSPeter Dunlap boolean_t iscsi_login_logging = B_FALSE; 3330e7468fSPeter Dunlap 34fcf3ce44SJohn Forte /* internal login protocol interfaces */ 35fcf3ce44SJohn Forte static iscsi_status_t iscsi_login(iscsi_conn_t *icp, 3630e7468fSPeter Dunlap uint8_t *status_class, uint8_t *status_detail); 3730e7468fSPeter Dunlap static int iscsi_add_text(idm_pdu_t *text_pdu, 38fcf3ce44SJohn Forte int max_data_length, char *param, char *value); 39fcf3ce44SJohn Forte static int iscsi_find_key_value(char *param, char *ihp, char *pdu_end, 40fcf3ce44SJohn Forte char **value_start, char **value_end); 41fcf3ce44SJohn Forte static void iscsi_null_callback(void *user_handle, void *message_handle, 42fcf3ce44SJohn Forte int auth_status); 43fcf3ce44SJohn Forte static iscsi_status_t iscsi_process_login_response(iscsi_conn_t *icp, 44fcf3ce44SJohn Forte iscsi_login_rsp_hdr_t *ilrhp, char *data, int max_data_length); 45fcf3ce44SJohn Forte static iscsi_status_t iscsi_make_login_pdu(iscsi_conn_t *icp, 4630e7468fSPeter Dunlap idm_pdu_t *text_pdu, char *data, int max_data_length); 47fcf3ce44SJohn Forte static iscsi_status_t iscsi_update_address(iscsi_conn_t *icp, 48fcf3ce44SJohn Forte char *address); 49fcf3ce44SJohn Forte static char *iscsi_login_failure_str(uchar_t status_class, 50fcf3ce44SJohn Forte uchar_t status_detail); 51fcf3ce44SJohn Forte static void iscsi_login_end(iscsi_conn_t *icp, 5230e7468fSPeter Dunlap iscsi_status_t status, iscsi_task_t *itp); 53fcf3ce44SJohn Forte static iscsi_status_t iscsi_login_connect(iscsi_conn_t *icp); 5430e7468fSPeter Dunlap static void iscsi_login_disconnect(iscsi_conn_t *icp); 5530e7468fSPeter Dunlap static void iscsi_notice_key_values(iscsi_conn_t *icp); 56fcf3ce44SJohn Forte 57fcf3ce44SJohn Forte #define ISCSI_LOGIN_RETRY_DELAY 5 /* seconds */ 58fcf3ce44SJohn Forte 5919944f88Syi zhang - Sun Microsystems - Beijing China #define ISCSI_LOGIN_TRANSIT_FFP(flags) \ 6019944f88Syi zhang - Sun Microsystems - Beijing China (!(flags & ISCSI_FLAG_LOGIN_CONTINUE) && \ 6119944f88Syi zhang - Sun Microsystems - Beijing China (flags & ISCSI_FLAG_LOGIN_TRANSIT) && \ 6219944f88Syi zhang - Sun Microsystems - Beijing China (ISCSI_LOGIN_CURRENT_STAGE(flags) == \ 6319944f88Syi zhang - Sun Microsystems - Beijing China ISCSI_OP_PARMS_NEGOTIATION_STAGE) && \ 6419944f88Syi zhang - Sun Microsystems - Beijing China (ISCSI_LOGIN_NEXT_STAGE(flags) == \ 6519944f88Syi zhang - Sun Microsystems - Beijing China ISCSI_FULL_FEATURE_PHASE)) 6619944f88Syi zhang - Sun Microsystems - Beijing China 67fcf3ce44SJohn Forte /* 68fcf3ce44SJohn Forte * +--------------------------------------------------------------------+ 69fcf3ce44SJohn Forte * | External Login Interface | 70fcf3ce44SJohn Forte * +--------------------------------------------------------------------+ 71fcf3ce44SJohn Forte */ 72fcf3ce44SJohn Forte 73fcf3ce44SJohn Forte /* 74fcf3ce44SJohn Forte * iscsi_login_start - connect and perform iscsi protocol login 75fcf3ce44SJohn Forte */ 76fcf3ce44SJohn Forte iscsi_status_t 77fcf3ce44SJohn Forte iscsi_login_start(void *arg) 78fcf3ce44SJohn Forte { 79fcf3ce44SJohn Forte iscsi_task_t *itp = (iscsi_task_t *)arg; 80fcf3ce44SJohn Forte iscsi_status_t rval = ISCSI_STATUS_LOGIN_FAILED; 81fcf3ce44SJohn Forte iscsi_conn_t *icp; 82fcf3ce44SJohn Forte iscsi_sess_t *isp; 83fcf3ce44SJohn Forte iscsi_hba_t *ihp; 84fcf3ce44SJohn Forte unsigned char status_class; 85fcf3ce44SJohn Forte unsigned char status_detail; 86fcf3ce44SJohn Forte 87fcf3ce44SJohn Forte ASSERT(itp != NULL); 88fcf3ce44SJohn Forte icp = (iscsi_conn_t *)itp->t_arg; 89fcf3ce44SJohn Forte ASSERT(icp != NULL); 90fcf3ce44SJohn Forte isp = icp->conn_sess; 91fcf3ce44SJohn Forte ASSERT(isp != NULL); 92fcf3ce44SJohn Forte ihp = isp->sess_hba; 93fcf3ce44SJohn Forte ASSERT(ihp != NULL); 94fcf3ce44SJohn Forte 95fcf3ce44SJohn Forte login_start: 9630e7468fSPeter Dunlap ASSERT((icp->conn_state == ISCSI_CONN_STATE_IN_LOGIN) || 9730e7468fSPeter Dunlap (icp->conn_state == ISCSI_CONN_STATE_FAILED) || 9830e7468fSPeter Dunlap (icp->conn_state == ISCSI_CONN_STATE_POLLING)); 9930e7468fSPeter Dunlap 10030e7468fSPeter Dunlap icp->conn_state_ffp = B_FALSE; 101cc7ef495Syi zhang - Sun Microsystems - Beijing China icp->conn_login_status = ISCSI_INITIAL_LOGIN_STAGE; 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))) { 123bbe72583SJack Meng if ((isp->sess_boot == B_TRUE) && 124bbe72583SJack Meng (ihp->hba_service_status_overwrite == B_TRUE) && 125bbe72583SJack Meng (isp->sess_boot_nic_reset == B_FALSE)) { 126bbe72583SJack Meng /* 127bbe72583SJack Meng * The connection to boot target failed 128bbe72583SJack Meng * before the system fully started. 129bbe72583SJack Meng * Reset the boot nic to the settings from 130bbe72583SJack Meng * firmware before retrying the connect to 131bbe72583SJack Meng * save the the system. 132bbe72583SJack Meng */ 133bbe72583SJack Meng if (iscsi_net_interface(B_TRUE) == 134bbe72583SJack Meng ISCSI_STATUS_SUCCESS) { 135bbe72583SJack Meng isp->sess_boot_nic_reset = B_TRUE; 136bbe72583SJack Meng } 137bbe72583SJack 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: 178cc7ef495Syi zhang - Sun Microsystems - Beijing China case ISCSI_STATUS_LOGIN_TPGT_NEGO_FAIL: 179fcf3ce44SJohn Forte /* we don't want to retry this failure */ 18030e7468fSPeter Dunlap iscsi_login_end(icp, ISCSI_STATUS_LOGIN_FAILED, itp); 181fcf3ce44SJohn Forte return (ISCSI_STATUS_LOGIN_FAILED); 182fcf3ce44SJohn Forte default: 183fcf3ce44SJohn Forte /* retry this failure */ 184fcf3ce44SJohn Forte goto login_retry; 185fcf3ce44SJohn Forte } 186fcf3ce44SJohn Forte } 187fcf3ce44SJohn Forte 188fcf3ce44SJohn Forte /* soft failure with reason */ 189fcf3ce44SJohn Forte switch (status_class) { 190fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_SUCCESS: 191fcf3ce44SJohn Forte /* login was successful */ 19230e7468fSPeter Dunlap iscsi_login_end(icp, ISCSI_STATUS_SUCCESS, itp); 193fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 194fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_REDIRECT: 195fcf3ce44SJohn Forte /* Retry at the redirected address */ 196fcf3ce44SJohn Forte goto login_start; 197fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_TARGET_ERR: 198fcf3ce44SJohn Forte /* retry this failure */ 199fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 200fcf3ce44SJohn Forte "%s (0x%02x/0x%02x)", icp->conn_oid, 201fcf3ce44SJohn Forte iscsi_login_failure_str(status_class, status_detail), 202fcf3ce44SJohn Forte status_class, status_detail); 203fcf3ce44SJohn Forte goto login_retry; 204fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_INITIATOR_ERR: 205fcf3ce44SJohn Forte default: 206fcf3ce44SJohn Forte /* All other errors are hard failures */ 207fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 2087f848965Sbing zhao - Sun Microsystems - Beijing China "%s (0x%02x/0x%02x) Target: %s, TPGT: %d", 2097f848965Sbing zhao - Sun Microsystems - Beijing China icp->conn_oid, 210fcf3ce44SJohn Forte iscsi_login_failure_str(status_class, status_detail), 2117f848965Sbing zhao - Sun Microsystems - Beijing China status_class, status_detail, isp->sess_name, 2127f848965Sbing zhao - Sun Microsystems - Beijing China isp->sess_tpgt_conf); 213fcf3ce44SJohn Forte 214fcf3ce44SJohn Forte /* we don't want to retry this failure */ 21530e7468fSPeter Dunlap iscsi_login_end(icp, ISCSI_STATUS_LOGIN_FAILED, itp); 216fcf3ce44SJohn Forte break; 217fcf3ce44SJohn Forte } 21830e7468fSPeter Dunlap 219fcf3ce44SJohn Forte return (ISCSI_STATUS_LOGIN_FAILED); 220fcf3ce44SJohn Forte 221fcf3ce44SJohn Forte login_retry: 222fcf3ce44SJohn Forte /* retry this failure if we haven't run out of time */ 223fcf3ce44SJohn Forte if (icp->conn_login_max > ddi_get_lbolt()) { 224fcf3ce44SJohn Forte 225fcf3ce44SJohn Forte if (icp->conn_state == ISCSI_CONN_STATE_POLLING) { 226fcf3ce44SJohn Forte icp->conn_login_min = ddi_get_lbolt() + 227aff4bce5Syi zhang - Sun Microsystems - Beijing China SEC_TO_TICK(icp->conn_tunable_params. 228aff4bce5Syi zhang - Sun Microsystems - Beijing China polling_login_delay); 229fcf3ce44SJohn Forte } else { 230fcf3ce44SJohn Forte icp->conn_login_min = ddi_get_lbolt() + 231fcf3ce44SJohn Forte SEC_TO_TICK(ISCSI_LOGIN_RETRY_DELAY); 232fcf3ce44SJohn Forte } 233fcf3ce44SJohn Forte 234fcf3ce44SJohn Forte if (itp->t_blocking == B_TRUE) { 235fcf3ce44SJohn Forte goto login_start; 236fcf3ce44SJohn Forte } else { 237*904e51f6SJack Meng if (ddi_taskq_dispatch(isp->sess_login_taskq, 238fcf3ce44SJohn Forte (void(*)())iscsi_login_start, itp, DDI_SLEEP) != 239fcf3ce44SJohn Forte DDI_SUCCESS) { 240fcf3ce44SJohn Forte iscsi_login_end(icp, 24130e7468fSPeter Dunlap ISCSI_STATUS_LOGIN_TIMED_OUT, itp); 242fcf3ce44SJohn Forte } 243fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 244fcf3ce44SJohn Forte } 245fcf3ce44SJohn Forte } else { 246fcf3ce44SJohn Forte /* Retries exceeded */ 24730e7468fSPeter Dunlap iscsi_login_end(icp, ISCSI_STATUS_LOGIN_TIMED_OUT, itp); 248fcf3ce44SJohn Forte } 24930e7468fSPeter Dunlap 250fcf3ce44SJohn Forte return (ISCSI_STATUS_LOGIN_FAILED); 251fcf3ce44SJohn Forte } 252fcf3ce44SJohn Forte 253fcf3ce44SJohn Forte static void 25430e7468fSPeter Dunlap iscsi_login_end(iscsi_conn_t *icp, iscsi_status_t status, iscsi_task_t *itp) 255fcf3ce44SJohn Forte { 256fcf3ce44SJohn Forte iscsi_sess_t *isp; 257*904e51f6SJack Meng uint32_t event_count; 258fcf3ce44SJohn Forte 259fcf3ce44SJohn Forte ASSERT(icp != NULL); 260fcf3ce44SJohn Forte isp = icp->conn_sess; 261fcf3ce44SJohn Forte ASSERT(isp != NULL); 262fcf3ce44SJohn Forte 26330e7468fSPeter Dunlap if (status == ISCSI_STATUS_SUCCESS) { 26430e7468fSPeter Dunlap /* Inform IDM of the relevant negotiated values */ 26530e7468fSPeter Dunlap iscsi_notice_key_values(icp); 26630e7468fSPeter Dunlap 26730e7468fSPeter Dunlap /* We are now logged in */ 26830e7468fSPeter Dunlap iscsi_conn_update_state(icp, ISCSI_CONN_STATE_LOGGED_IN); 26930e7468fSPeter Dunlap 27030e7468fSPeter Dunlap /* startup TX thread */ 27130e7468fSPeter Dunlap (void) iscsi_thread_start(icp->conn_tx_thread); 27230e7468fSPeter Dunlap 27330e7468fSPeter Dunlap /* 27430e7468fSPeter Dunlap * Move login state machine to LOGIN_FFP. This will 27530e7468fSPeter Dunlap * release the taskq thread handling the CN_FFP_ENABLED 27630e7468fSPeter Dunlap * allowing the IDM connection state machine to resume 27730e7468fSPeter Dunlap * processing events 27830e7468fSPeter Dunlap */ 27930e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_FFP); 280fcf3ce44SJohn Forte 28130e7468fSPeter Dunlap /* Notify the session that a connection is logged in */ 282*904e51f6SJack Meng event_count = atomic_inc_32_nv(&isp->sess_state_event_count); 283*904e51f6SJack Meng iscsi_sess_enter_state_zone(isp); 284*904e51f6SJack Meng iscsi_sess_state_machine(isp, ISCSI_SESS_EVENT_N1, event_count); 285*904e51f6SJack Meng iscsi_sess_exit_state_zone(isp); 28630e7468fSPeter Dunlap } else { 28730e7468fSPeter Dunlap /* If login failed reset nego tpgt */ 288fcf3ce44SJohn Forte isp->sess_tpgt_nego = ISCSI_DEFAULT_TPGT; 28930e7468fSPeter Dunlap 29030e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 29130e7468fSPeter Dunlap switch (icp->conn_state) { 29230e7468fSPeter Dunlap case ISCSI_CONN_STATE_IN_LOGIN: 29330e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 29430e7468fSPeter Dunlap ISCSI_CONN_STATE_FREE); 29530e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 29630e7468fSPeter Dunlap break; 29730e7468fSPeter Dunlap case ISCSI_CONN_STATE_FAILED: 29830e7468fSPeter Dunlap if (status == ISCSI_STATUS_LOGIN_FAILED) { 29930e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 30030e7468fSPeter Dunlap ISCSI_CONN_STATE_FREE); 30130e7468fSPeter Dunlap } else { 30230e7468fSPeter Dunlap /* ISCSI_STATUS_LOGIN_TIMED_OUT */ 30330e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 30430e7468fSPeter Dunlap ISCSI_CONN_STATE_POLLING); 30530e7468fSPeter Dunlap } 30630e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 307*904e51f6SJack Meng event_count = atomic_inc_32_nv( 308*904e51f6SJack Meng &isp->sess_state_event_count); 309*904e51f6SJack Meng iscsi_sess_enter_state_zone(isp); 310*904e51f6SJack Meng iscsi_sess_state_machine(isp, ISCSI_SESS_EVENT_N6, 311*904e51f6SJack Meng event_count); 312*904e51f6SJack Meng iscsi_sess_exit_state_zone(isp); 31330e7468fSPeter Dunlap 31430e7468fSPeter Dunlap if (status == ISCSI_STATUS_LOGIN_TIMED_OUT) { 31530e7468fSPeter Dunlap iscsi_conn_retry(isp, icp); 31630e7468fSPeter Dunlap } 31730e7468fSPeter Dunlap break; 31830e7468fSPeter Dunlap case ISCSI_CONN_STATE_POLLING: 31930e7468fSPeter Dunlap if (status == ISCSI_STATUS_LOGIN_FAILED) { 32030e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 32130e7468fSPeter Dunlap ISCSI_CONN_STATE_FREE); 32230e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 323*904e51f6SJack Meng event_count = atomic_inc_32_nv( 324*904e51f6SJack Meng &isp->sess_state_event_count); 325*904e51f6SJack Meng iscsi_sess_enter_state_zone(isp); 32630e7468fSPeter Dunlap 32730e7468fSPeter Dunlap iscsi_sess_state_machine(isp, 328*904e51f6SJack Meng ISCSI_SESS_EVENT_N6, event_count); 329*904e51f6SJack Meng 330*904e51f6SJack Meng iscsi_sess_exit_state_zone(isp); 33130e7468fSPeter Dunlap } else { 33230e7468fSPeter Dunlap /* ISCSI_STATUS_LOGIN_TIMED_OUT */ 33330e7468fSPeter Dunlap if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 33430e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 33530e7468fSPeter Dunlap 33630e7468fSPeter Dunlap iscsi_conn_retry(isp, icp); 33730e7468fSPeter Dunlap } else { 33830e7468fSPeter Dunlap iscsi_conn_update_state_locked(icp, 33930e7468fSPeter Dunlap ISCSI_CONN_STATE_FREE); 34030e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 34130e7468fSPeter Dunlap } 34230e7468fSPeter Dunlap } 34330e7468fSPeter Dunlap break; 34419944f88Syi zhang - Sun Microsystems - Beijing China case ISCSI_CONN_STATE_FREE: 34519944f88Syi zhang - Sun Microsystems - Beijing China mutex_exit(&icp->conn_state_mutex); 34619944f88Syi zhang - Sun Microsystems - Beijing China break; 34730e7468fSPeter Dunlap default: 34819944f88Syi zhang - Sun Microsystems - Beijing China mutex_exit(&icp->conn_state_mutex); 34930e7468fSPeter Dunlap ASSERT(0); 35030e7468fSPeter Dunlap break; 35130e7468fSPeter Dunlap } 352fcf3ce44SJohn Forte } 353fcf3ce44SJohn Forte 354fcf3ce44SJohn Forte if (itp->t_blocking == B_FALSE) { 355fcf3ce44SJohn Forte kmem_free(itp, sizeof (iscsi_task_t)); 356fcf3ce44SJohn Forte } 357bbe72583SJack Meng 358bbe72583SJack Meng isp->sess_boot_nic_reset = B_FALSE; 359fcf3ce44SJohn Forte } 360fcf3ce44SJohn Forte 361fcf3ce44SJohn Forte /* 362fcf3ce44SJohn Forte * +--------------------------------------------------------------------+ 363fcf3ce44SJohn Forte * | Begin of protocol login routines | 364fcf3ce44SJohn Forte * +--------------------------------------------------------------------+ 365fcf3ce44SJohn Forte */ 366fcf3ce44SJohn Forte 367fcf3ce44SJohn Forte /* 368fcf3ce44SJohn Forte * iscsi_login - Attempt to login to the target. The caller 369fcf3ce44SJohn Forte * must check the status class to determine if the login succeeded. 370fcf3ce44SJohn Forte * A return of 1 does not mean the login succeeded, it just means 371fcf3ce44SJohn Forte * this function worked, and the status class is valid info. This 372fcf3ce44SJohn Forte * allows the caller to decide whether or not to retry logins, so 373fcf3ce44SJohn Forte * that we don't have any policy logic here. 374fcf3ce44SJohn Forte */ 37530e7468fSPeter Dunlap iscsi_status_t 37630e7468fSPeter Dunlap iscsi_login(iscsi_conn_t *icp, uint8_t *status_class, uint8_t *status_detail) 377fcf3ce44SJohn Forte { 378fcf3ce44SJohn Forte iscsi_status_t rval = ISCSI_STATUS_INTERNAL_ERROR; 379fcf3ce44SJohn Forte struct iscsi_sess *isp = NULL; 380fcf3ce44SJohn Forte IscsiAuthClient *auth_client = NULL; 381fcf3ce44SJohn Forte int max_data_length = 0; 382fcf3ce44SJohn Forte char *data = NULL; 38330e7468fSPeter Dunlap idm_pdu_t *text_pdu; 38430e7468fSPeter Dunlap char *buffer; 38530e7468fSPeter Dunlap size_t bufsize; 38630e7468fSPeter Dunlap iscsi_login_rsp_hdr_t *ilrhp; 38730e7468fSPeter Dunlap clock_t response_timeout, timeout_result; 38830e7468fSPeter Dunlap 38930e7468fSPeter Dunlap buffer = icp->conn_login_data; 39030e7468fSPeter Dunlap bufsize = icp->conn_login_max_data_length; 391fcf3ce44SJohn Forte 392fcf3ce44SJohn Forte ASSERT(icp != NULL); 393fcf3ce44SJohn Forte ASSERT(buffer != NULL); 394fcf3ce44SJohn Forte ASSERT(status_class != NULL); 395fcf3ce44SJohn Forte ASSERT(status_detail != NULL); 396fcf3ce44SJohn Forte isp = icp->conn_sess; 397fcf3ce44SJohn Forte ASSERT(isp != NULL); 398fcf3ce44SJohn Forte 399fcf3ce44SJohn Forte /* 40030e7468fSPeter Dunlap * prepare the connection, hold IDM connection until login completes 401fcf3ce44SJohn Forte */ 402fcf3ce44SJohn Forte icp->conn_current_stage = ISCSI_INITIAL_LOGIN_STAGE; 403fcf3ce44SJohn Forte icp->conn_partial_response = 0; 404fcf3ce44SJohn Forte 405fcf3ce44SJohn Forte if (isp->sess_auth.auth_buffers && 406fcf3ce44SJohn Forte isp->sess_auth.num_auth_buffers) { 407fcf3ce44SJohn Forte 408fcf3ce44SJohn Forte auth_client = (IscsiAuthClient *)isp-> 409fcf3ce44SJohn Forte sess_auth.auth_buffers[0].address; 410fcf3ce44SJohn Forte 411fcf3ce44SJohn Forte /* 412fcf3ce44SJohn Forte * prepare for authentication 413fcf3ce44SJohn Forte */ 414fcf3ce44SJohn Forte if (iscsiAuthClientInit(iscsiAuthNodeTypeInitiator, 415fcf3ce44SJohn Forte isp->sess_auth.num_auth_buffers, 416fcf3ce44SJohn Forte isp->sess_auth.auth_buffers) != 417fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 418fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 419fcf3ce44SJohn Forte "unable to initialize authentication", 420fcf3ce44SJohn Forte icp->conn_oid); 421cc7ef495Syi zhang - Sun Microsystems - Beijing China icp->conn_login_status = ISCSI_STATUS_INTERNAL_ERROR; 42230e7468fSPeter Dunlap iscsi_login_disconnect(icp); 42330e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_DONE); 424fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 425fcf3ce44SJohn Forte } 426fcf3ce44SJohn Forte 427fcf3ce44SJohn Forte if (iscsiAuthClientSetVersion(auth_client, 428fcf3ce44SJohn Forte iscsiAuthVersionRfc) != iscsiAuthStatusNoError) { 429fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 430fcf3ce44SJohn Forte "unable to set authentication", icp->conn_oid); 431fcf3ce44SJohn Forte goto iscsi_login_done; 432fcf3ce44SJohn Forte } 433fcf3ce44SJohn Forte 434fcf3ce44SJohn Forte if (isp->sess_auth.username && 435fcf3ce44SJohn Forte (iscsiAuthClientSetUsername(auth_client, 436fcf3ce44SJohn Forte isp->sess_auth.username) != 437fcf3ce44SJohn Forte iscsiAuthStatusNoError)) { 438fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 439fcf3ce44SJohn Forte "unable to set username", icp->conn_oid); 440fcf3ce44SJohn Forte goto iscsi_login_done; 441fcf3ce44SJohn Forte } 442fcf3ce44SJohn Forte 443fcf3ce44SJohn Forte if (isp->sess_auth.password && 444fcf3ce44SJohn Forte (iscsiAuthClientSetPassword(auth_client, 445fcf3ce44SJohn Forte isp->sess_auth.password, isp->sess_auth.password_length) != 446fcf3ce44SJohn Forte iscsiAuthStatusNoError)) { 447fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 448fcf3ce44SJohn Forte "unable to set password", icp->conn_oid); 449fcf3ce44SJohn Forte goto iscsi_login_done; 450fcf3ce44SJohn Forte } 451fcf3ce44SJohn Forte 452fcf3ce44SJohn Forte if (iscsiAuthClientSetIpSec(auth_client, 1) != 453fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 454fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 455fcf3ce44SJohn Forte "unable to set ipsec", icp->conn_oid); 456fcf3ce44SJohn Forte goto iscsi_login_done; 457fcf3ce44SJohn Forte } 458fcf3ce44SJohn Forte 459fcf3ce44SJohn Forte if (iscsiAuthClientSetAuthRemote(auth_client, 460fcf3ce44SJohn Forte isp->sess_auth.bidirectional_auth) != 461fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 462fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 463fcf3ce44SJohn Forte "unable to set remote authentication", 464fcf3ce44SJohn Forte icp->conn_oid); 465fcf3ce44SJohn Forte goto iscsi_login_done; 466fcf3ce44SJohn Forte } 467fcf3ce44SJohn Forte } 468fcf3ce44SJohn Forte 469fcf3ce44SJohn Forte /* 470fcf3ce44SJohn Forte * exchange PDUs until the login stage is complete, or an error occurs 471fcf3ce44SJohn Forte */ 472fcf3ce44SJohn Forte do { 473fcf3ce44SJohn Forte /* setup */ 474fcf3ce44SJohn Forte bzero(buffer, bufsize); 475fcf3ce44SJohn Forte data = buffer; 476fcf3ce44SJohn Forte max_data_length = bufsize; 477fcf3ce44SJohn Forte rval = ISCSI_STATUS_INTERNAL_ERROR; 478fcf3ce44SJohn Forte 47930e7468fSPeter Dunlap text_pdu = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0); 48030e7468fSPeter Dunlap idm_pdu_init(text_pdu, icp->conn_ic, NULL, NULL); 48130e7468fSPeter Dunlap 482fcf3ce44SJohn Forte /* 483fcf3ce44SJohn Forte * fill in the PDU header and text data based on the 484fcf3ce44SJohn Forte * login stage that we're in 485fcf3ce44SJohn Forte */ 48630e7468fSPeter Dunlap rval = iscsi_make_login_pdu(icp, text_pdu, data, 48730e7468fSPeter Dunlap max_data_length); 488fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(rval)) { 489fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 490fcf3ce44SJohn Forte "unable to make login pdu", icp->conn_oid); 491fcf3ce44SJohn Forte goto iscsi_login_done; 492fcf3ce44SJohn Forte } 493fcf3ce44SJohn Forte 49430e7468fSPeter Dunlap mutex_enter(&icp->conn_login_mutex); 49530e7468fSPeter Dunlap /* 49630e7468fSPeter Dunlap * Make sure we are still in LOGIN_START or LOGIN_RX 49730e7468fSPeter Dunlap * state before switching to LOGIN_TX. It's possible 49830e7468fSPeter Dunlap * for a connection failure to move us to LOGIN_ERROR 49930e7468fSPeter Dunlap * before we get to this point. 50030e7468fSPeter Dunlap */ 50130e7468fSPeter Dunlap if (((icp->conn_login_state != LOGIN_READY) && 50230e7468fSPeter Dunlap (icp->conn_login_state != LOGIN_RX)) || 50330e7468fSPeter Dunlap !icp->conn_state_idm_connected) { 50430e7468fSPeter Dunlap /* Error occurred */ 50530e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex); 50630e7468fSPeter Dunlap rval = (ISCSI_STATUS_INTERNAL_ERROR); 507fcf3ce44SJohn Forte goto iscsi_login_done; 508fcf3ce44SJohn Forte } 509fcf3ce44SJohn Forte 51030e7468fSPeter Dunlap iscsi_login_update_state_locked(icp, LOGIN_TX); 51130e7468fSPeter Dunlap icp->conn_login_data = data; 51230e7468fSPeter Dunlap icp->conn_login_max_data_length = max_data_length; 51330e7468fSPeter Dunlap 51430e7468fSPeter Dunlap /* 51530e7468fSPeter Dunlap * send a PDU to the target. This is asynchronous but 51630e7468fSPeter Dunlap * we don't have any particular need for a TX completion 51730e7468fSPeter Dunlap * notification since we are going to block waiting for the 51830e7468fSPeter Dunlap * receive. 51930e7468fSPeter Dunlap */ 52030e7468fSPeter Dunlap response_timeout = ddi_get_lbolt() + 521aff4bce5Syi zhang - Sun Microsystems - Beijing China SEC_TO_TICK(icp->conn_tunable_params. 522aff4bce5Syi zhang - Sun Microsystems - Beijing China recv_login_rsp_timeout); 52330e7468fSPeter Dunlap idm_pdu_tx(text_pdu); 52430e7468fSPeter Dunlap 52530e7468fSPeter Dunlap /* 52630e7468fSPeter Dunlap * Wait for login failure indication or login RX. 52730e7468fSPeter Dunlap * Handler for login response PDU will copy any data into 52830e7468fSPeter Dunlap * the buffer pointed to by icp->conn_login_data 52930e7468fSPeter Dunlap */ 53030e7468fSPeter Dunlap while (icp->conn_login_state == LOGIN_TX) { 53130e7468fSPeter Dunlap timeout_result = cv_timedwait(&icp->conn_login_cv, 53230e7468fSPeter Dunlap &icp->conn_login_mutex, response_timeout); 53330e7468fSPeter Dunlap if (timeout_result == -1) 53430e7468fSPeter Dunlap break; 535fcf3ce44SJohn Forte } 536fcf3ce44SJohn Forte 53730e7468fSPeter Dunlap if (icp->conn_login_state != LOGIN_RX) { 53830e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex); 53930e7468fSPeter Dunlap rval = (ISCSI_STATUS_INTERNAL_ERROR); 540fcf3ce44SJohn Forte goto iscsi_login_done; 541fcf3ce44SJohn Forte } 54230e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex); 543fcf3ce44SJohn Forte 544fcf3ce44SJohn Forte /* check the PDU response type */ 54530e7468fSPeter Dunlap ilrhp = (iscsi_login_rsp_hdr_t *)&icp->conn_login_resp_hdr; 54630e7468fSPeter Dunlap if (ilrhp->opcode != ISCSI_OP_LOGIN_RSP) { 547fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 548fcf3ce44SJohn Forte "received invalid login response (0x%02x)", 54930e7468fSPeter Dunlap icp->conn_oid, ilrhp->opcode); 550fcf3ce44SJohn Forte rval = (ISCSI_STATUS_PROTOCOL_ERROR); 551fcf3ce44SJohn Forte goto iscsi_login_done; 552fcf3ce44SJohn Forte } 553fcf3ce44SJohn Forte 554fcf3ce44SJohn Forte /* 555fcf3ce44SJohn Forte * give the caller the status class and detail from the 556fcf3ce44SJohn Forte * last login response PDU received 557fcf3ce44SJohn Forte */ 558fcf3ce44SJohn Forte if (status_class) { 559fcf3ce44SJohn Forte *status_class = ilrhp->status_class; 560fcf3ce44SJohn Forte } 561fcf3ce44SJohn Forte if (status_detail) { 562fcf3ce44SJohn Forte *status_detail = ilrhp->status_detail; 563fcf3ce44SJohn Forte } 564fcf3ce44SJohn Forte 565fcf3ce44SJohn Forte switch (ilrhp->status_class) { 566fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_SUCCESS: 567fcf3ce44SJohn Forte /* 568fcf3ce44SJohn Forte * process this response and possibly continue 569fcf3ce44SJohn Forte * sending PDUs 570fcf3ce44SJohn Forte */ 571fcf3ce44SJohn Forte rval = iscsi_process_login_response(icp, 57230e7468fSPeter Dunlap ilrhp, (char *)icp->conn_login_data, 57330e7468fSPeter Dunlap icp->conn_login_max_data_length); 574fcf3ce44SJohn Forte /* pass back whatever error we discovered */ 575fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(rval)) { 57619944f88Syi zhang - Sun Microsystems - Beijing China if (ISCSI_LOGIN_TRANSIT_FFP(ilrhp->flags)) { 57719944f88Syi zhang - Sun Microsystems - Beijing China /* 57819944f88Syi zhang - Sun Microsystems - Beijing China * iSCSI connection transit to next 57919944f88Syi zhang - Sun Microsystems - Beijing China * FFP stage while iscsi params 58019944f88Syi zhang - Sun Microsystems - Beijing China * ngeotiate error, LOGIN_ERROR 58119944f88Syi zhang - Sun Microsystems - Beijing China * marked so CN_FFP_ENABLED can 58219944f88Syi zhang - Sun Microsystems - Beijing China * be fully handled before 58319944f88Syi zhang - Sun Microsystems - Beijing China * CN_FFP_DISABLED can be processed. 58419944f88Syi zhang - Sun Microsystems - Beijing China */ 58519944f88Syi zhang - Sun Microsystems - Beijing China iscsi_login_update_state(icp, 58619944f88Syi zhang - Sun Microsystems - Beijing China LOGIN_ERROR); 58719944f88Syi zhang - Sun Microsystems - Beijing China } 588fcf3ce44SJohn Forte goto iscsi_login_done; 589fcf3ce44SJohn Forte } 590fcf3ce44SJohn Forte 591fcf3ce44SJohn Forte break; 592fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_REDIRECT: 593fcf3ce44SJohn Forte /* 594fcf3ce44SJohn Forte * we need to process this response to get the 595fcf3ce44SJohn Forte * TargetAddress of the redirect, but we don't 596fcf3ce44SJohn Forte * care about the return code. 597fcf3ce44SJohn Forte */ 59830e7468fSPeter Dunlap (void) iscsi_process_login_response(icp, 59930e7468fSPeter Dunlap ilrhp, (char *)icp->conn_login_data, 60030e7468fSPeter Dunlap icp->conn_login_max_data_length); 601fcf3ce44SJohn Forte rval = ISCSI_STATUS_SUCCESS; 602fcf3ce44SJohn Forte goto iscsi_login_done; 603fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_INITIATOR_ERR: 604fcf3ce44SJohn Forte if (ilrhp->status_detail == 605fcf3ce44SJohn Forte ISCSI_LOGIN_STATUS_AUTH_FAILED) { 606fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 607fcf3ce44SJohn Forte "failed - login failed to authenticate " 608fcf3ce44SJohn Forte "with target", icp->conn_oid); 609fcf3ce44SJohn Forte } 610fcf3ce44SJohn Forte rval = ISCSI_STATUS_SUCCESS; 611fcf3ce44SJohn Forte goto iscsi_login_done; 612fcf3ce44SJohn Forte default: 613fcf3ce44SJohn Forte /* 614fcf3ce44SJohn Forte * some sort of error, login terminated unsuccessfully, 615fcf3ce44SJohn Forte * though this function did it's job. the caller must 616fcf3ce44SJohn Forte * check the status_class and status_detail and decide 617fcf3ce44SJohn Forte * what to do next. 618fcf3ce44SJohn Forte */ 619fcf3ce44SJohn Forte rval = ISCSI_STATUS_SUCCESS; 620fcf3ce44SJohn Forte goto iscsi_login_done; 621fcf3ce44SJohn Forte } 622fcf3ce44SJohn Forte 623fcf3ce44SJohn Forte } while (icp->conn_current_stage != ISCSI_FULL_FEATURE_PHASE); 624fcf3ce44SJohn Forte 625fcf3ce44SJohn Forte rval = ISCSI_STATUS_SUCCESS; 626fcf3ce44SJohn Forte 627fcf3ce44SJohn Forte iscsi_login_done: 628fcf3ce44SJohn Forte if (auth_client) { 629fcf3ce44SJohn Forte if (iscsiAuthClientFinish(auth_client) != 630fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 631fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 632fcf3ce44SJohn Forte "failed - login failed to authenticate " 633fcf3ce44SJohn Forte "with target", icp->conn_oid); 634fcf3ce44SJohn Forte if (ISCSI_SUCCESS(rval)) 635fcf3ce44SJohn Forte rval = ISCSI_STATUS_INTERNAL_ERROR; 636fcf3ce44SJohn Forte } 637fcf3ce44SJohn Forte } 63830e7468fSPeter Dunlap 639cc7ef495Syi zhang - Sun Microsystems - Beijing China icp->conn_login_status = rval; 64030e7468fSPeter Dunlap if (ISCSI_SUCCESS(rval) && 64130e7468fSPeter Dunlap (*status_class == ISCSI_STATUS_CLASS_SUCCESS)) { 64230e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 64330e7468fSPeter Dunlap while (!icp->conn_state_ffp) 64430e7468fSPeter Dunlap cv_wait(&icp->conn_state_change, 64530e7468fSPeter Dunlap &icp->conn_state_mutex); 64630e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 64730e7468fSPeter Dunlap } else { 64830e7468fSPeter Dunlap iscsi_login_disconnect(icp); 64930e7468fSPeter Dunlap } 65030e7468fSPeter Dunlap 65130e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_DONE); 65230e7468fSPeter Dunlap 653fcf3ce44SJohn Forte return (rval); 654fcf3ce44SJohn Forte } 655fcf3ce44SJohn Forte 656fcf3ce44SJohn Forte 657fcf3ce44SJohn Forte /* 658fcf3ce44SJohn Forte * iscsi_make_login_pdu - 659fcf3ce44SJohn Forte * 660fcf3ce44SJohn Forte */ 661fcf3ce44SJohn Forte static iscsi_status_t 66230e7468fSPeter Dunlap iscsi_make_login_pdu(iscsi_conn_t *icp, idm_pdu_t *text_pdu, 663fcf3ce44SJohn Forte char *data, int max_data_length) 664fcf3ce44SJohn Forte { 665fcf3ce44SJohn Forte struct iscsi_sess *isp = NULL; 666fcf3ce44SJohn Forte int transit = 0; 66730e7468fSPeter Dunlap iscsi_hdr_t *ihp = text_pdu->isp_hdr; 66830e7468fSPeter Dunlap iscsi_login_hdr_t *ilhp = 66930e7468fSPeter Dunlap (iscsi_login_hdr_t *)text_pdu->isp_hdr; 670fcf3ce44SJohn Forte IscsiAuthClient *auth_client = NULL; 671fcf3ce44SJohn Forte int keytype = 0; 672fcf3ce44SJohn Forte int rc = 0; 673fcf3ce44SJohn Forte char value[iscsiAuthStringMaxLength]; 674fcf3ce44SJohn Forte 675fcf3ce44SJohn Forte ASSERT(icp != NULL); 67630e7468fSPeter Dunlap ASSERT(text_pdu != NULL); 677fcf3ce44SJohn Forte isp = icp->conn_sess; 678fcf3ce44SJohn Forte ASSERT(isp != NULL); 679fcf3ce44SJohn Forte 680fcf3ce44SJohn Forte auth_client = 681fcf3ce44SJohn Forte (isp->sess_auth.auth_buffers && isp->sess_auth.num_auth_buffers) ? 682fcf3ce44SJohn Forte (IscsiAuthClient *)isp->sess_auth.auth_buffers[0].address : NULL; 683fcf3ce44SJohn Forte 684fcf3ce44SJohn Forte /* 685fcf3ce44SJohn Forte * initialize the PDU header 686fcf3ce44SJohn Forte */ 687fcf3ce44SJohn Forte bzero(ilhp, sizeof (*ilhp)); 688fcf3ce44SJohn Forte ilhp->opcode = ISCSI_OP_LOGIN_CMD | ISCSI_OP_IMMEDIATE; 689fcf3ce44SJohn Forte ilhp->cid = icp->conn_cid; 690fcf3ce44SJohn Forte bcopy(&isp->sess_isid[0], &ilhp->isid[0], sizeof (isp->sess_isid)); 691fcf3ce44SJohn Forte ilhp->tsid = 0; 692fcf3ce44SJohn Forte 69330e7468fSPeter Dunlap /* 69430e7468fSPeter Dunlap * Set data buffer pointer. The calls to iscsi_add_text will update the 69530e7468fSPeter Dunlap * data length. 69630e7468fSPeter Dunlap */ 69730e7468fSPeter Dunlap text_pdu->isp_data = (uint8_t *)data; 69830e7468fSPeter Dunlap 699fcf3ce44SJohn Forte /* don't increment on immediate */ 700fcf3ce44SJohn Forte ilhp->cmdsn = htonl(isp->sess_cmdsn); 701fcf3ce44SJohn Forte 702fcf3ce44SJohn Forte ilhp->min_version = ISCSI_DRAFT20_VERSION; 703fcf3ce44SJohn Forte ilhp->max_version = ISCSI_DRAFT20_VERSION; 704fcf3ce44SJohn Forte 705fcf3ce44SJohn Forte /* 706fcf3ce44SJohn Forte * we have to send 0 until full-feature stage 707fcf3ce44SJohn Forte */ 708fcf3ce44SJohn Forte ilhp->expstatsn = htonl(icp->conn_expstatsn); 709fcf3ce44SJohn Forte 710fcf3ce44SJohn Forte /* 711fcf3ce44SJohn Forte * the very first Login PDU has some additional requirements, 712fcf3ce44SJohn Forte * * and we need to decide what stage to start in. 713fcf3ce44SJohn Forte */ 714fcf3ce44SJohn Forte if (icp->conn_current_stage == ISCSI_INITIAL_LOGIN_STAGE) { 715fcf3ce44SJohn Forte if ((isp->sess_hba->hba_name) && 716fcf3ce44SJohn Forte (isp->sess_hba->hba_name[0])) { 71730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 718fcf3ce44SJohn Forte "InitiatorName", 719fcf3ce44SJohn Forte (char *)isp->sess_hba->hba_name)) { 720fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 721fcf3ce44SJohn Forte } 722fcf3ce44SJohn Forte } else { 723fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 724fcf3ce44SJohn Forte "failed - initiator name is required", 725fcf3ce44SJohn Forte icp->conn_oid); 726fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 727fcf3ce44SJohn Forte } 728fcf3ce44SJohn Forte 729fcf3ce44SJohn Forte if ((isp->sess_hba->hba_alias) && 730fcf3ce44SJohn Forte (isp->sess_hba->hba_alias[0])) { 73130e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 732fcf3ce44SJohn Forte "InitiatorAlias", 733fcf3ce44SJohn Forte (char *)isp->sess_hba->hba_alias)) { 734fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 735fcf3ce44SJohn Forte } 736fcf3ce44SJohn Forte } 737fcf3ce44SJohn Forte 738fcf3ce44SJohn Forte if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 739fcf3ce44SJohn Forte if (isp->sess_name[0] != '\0') { 74030e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 741fcf3ce44SJohn Forte "TargetName", (char *)isp->sess_name)) { 742fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 743fcf3ce44SJohn Forte } 744fcf3ce44SJohn Forte } 745fcf3ce44SJohn Forte 74630e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 747fcf3ce44SJohn Forte "SessionType", "Normal")) { 748fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 749fcf3ce44SJohn Forte } 750fcf3ce44SJohn Forte } else if (isp->sess_type == ISCSI_SESS_TYPE_DISCOVERY) { 75130e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 752fcf3ce44SJohn Forte "SessionType", "Discovery")) { 753fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 754fcf3ce44SJohn Forte } 755fcf3ce44SJohn Forte } else { 756fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 757fcf3ce44SJohn Forte } 758fcf3ce44SJohn Forte 759fcf3ce44SJohn Forte if (auth_client) { 760fcf3ce44SJohn Forte /* we're prepared to do authentication */ 761fcf3ce44SJohn Forte icp->conn_current_stage = 762fcf3ce44SJohn Forte ISCSI_SECURITY_NEGOTIATION_STAGE; 763fcf3ce44SJohn Forte } else { 764fcf3ce44SJohn Forte /* can't do any authentication, skip that stage */ 765fcf3ce44SJohn Forte icp->conn_current_stage = 766fcf3ce44SJohn Forte ISCSI_OP_PARMS_NEGOTIATION_STAGE; 767fcf3ce44SJohn Forte } 768fcf3ce44SJohn Forte } 769fcf3ce44SJohn Forte 770fcf3ce44SJohn Forte /* 771fcf3ce44SJohn Forte * fill in text based on the stage 772fcf3ce44SJohn Forte */ 773fcf3ce44SJohn Forte switch (icp->conn_current_stage) { 774fcf3ce44SJohn Forte case ISCSI_OP_PARMS_NEGOTIATION_STAGE: 775fcf3ce44SJohn Forte /* 776fcf3ce44SJohn Forte * we always try to go from op params to full 777fcf3ce44SJohn Forte * feature stage 778fcf3ce44SJohn Forte */ 779fcf3ce44SJohn Forte icp->conn_next_stage = ISCSI_FULL_FEATURE_PHASE; 780fcf3ce44SJohn Forte transit = 1; 781fcf3ce44SJohn Forte 782fcf3ce44SJohn Forte /* 783fcf3ce44SJohn Forte * The terminology here may have gotten dated. A partial 784fcf3ce44SJohn Forte * response is a login response that doesn't complete a 785fcf3ce44SJohn Forte * login. If we haven't gotten a partial response, then 786fcf3ce44SJohn Forte * either we shouldn't be here, or we just switched to 787fcf3ce44SJohn Forte * this stage, and need to start offering keys. 788fcf3ce44SJohn Forte */ 789fcf3ce44SJohn Forte if (!icp->conn_partial_response) { 790fcf3ce44SJohn Forte /* 791fcf3ce44SJohn Forte * request the desired settings the first time 792fcf3ce44SJohn Forte * we are in this stage 793fcf3ce44SJohn Forte */ 794fcf3ce44SJohn Forte switch (icp->conn_params.header_digest) { 795fcf3ce44SJohn Forte case ISCSI_DIGEST_NONE: 79630e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 797fcf3ce44SJohn Forte max_data_length, "HeaderDigest", "None")) { 798fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 799fcf3ce44SJohn Forte } 800fcf3ce44SJohn Forte break; 801fcf3ce44SJohn Forte case ISCSI_DIGEST_CRC32C: 80230e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 803fcf3ce44SJohn Forte max_data_length, 804fcf3ce44SJohn Forte "HeaderDigest", "CRC32C")) { 805fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 806fcf3ce44SJohn Forte } 807fcf3ce44SJohn Forte break; 808fcf3ce44SJohn Forte case ISCSI_DIGEST_CRC32C_NONE: 80930e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 810fcf3ce44SJohn Forte max_data_length, "HeaderDigest", 811fcf3ce44SJohn Forte "CRC32C,None")) { 812fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 813fcf3ce44SJohn Forte } 814fcf3ce44SJohn Forte break; 815fcf3ce44SJohn Forte default: 816fcf3ce44SJohn Forte case ISCSI_DIGEST_NONE_CRC32C: 81730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 818fcf3ce44SJohn Forte max_data_length, "HeaderDigest", 819fcf3ce44SJohn Forte "None,CRC32C")) { 820fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 821fcf3ce44SJohn Forte } 822fcf3ce44SJohn Forte break; 823fcf3ce44SJohn Forte } 824fcf3ce44SJohn Forte 825fcf3ce44SJohn Forte switch (icp->conn_params.data_digest) { 826fcf3ce44SJohn Forte case ISCSI_DIGEST_NONE: 82730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 828fcf3ce44SJohn Forte max_data_length, "DataDigest", "None")) { 829fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 830fcf3ce44SJohn Forte } 831fcf3ce44SJohn Forte break; 832fcf3ce44SJohn Forte case ISCSI_DIGEST_CRC32C: 83330e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 834fcf3ce44SJohn Forte max_data_length, "DataDigest", "CRC32C")) { 835fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 836fcf3ce44SJohn Forte } 837fcf3ce44SJohn Forte break; 838fcf3ce44SJohn Forte case ISCSI_DIGEST_CRC32C_NONE: 83930e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 840fcf3ce44SJohn Forte max_data_length, "DataDigest", 841fcf3ce44SJohn Forte "CRC32C,None")) { 842fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 843fcf3ce44SJohn Forte } 844fcf3ce44SJohn Forte break; 845fcf3ce44SJohn Forte default: 846fcf3ce44SJohn Forte case ISCSI_DIGEST_NONE_CRC32C: 84730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 848fcf3ce44SJohn Forte max_data_length, "DataDigest", 849fcf3ce44SJohn Forte "None,CRC32C")) { 850fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 851fcf3ce44SJohn Forte } 852fcf3ce44SJohn Forte break; 853fcf3ce44SJohn Forte } 854fcf3ce44SJohn Forte 855fcf3ce44SJohn Forte (void) sprintf(value, "%d", 856fcf3ce44SJohn Forte icp->conn_params.max_recv_data_seg_len); 85730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 858fcf3ce44SJohn Forte "MaxRecvDataSegmentLength", value)) { 859fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 860fcf3ce44SJohn Forte } 861fcf3ce44SJohn Forte 862fcf3ce44SJohn Forte (void) sprintf(value, "%d", 863fcf3ce44SJohn Forte icp->conn_params.default_time_to_wait); 86430e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 865fcf3ce44SJohn Forte max_data_length, "DefaultTime2Wait", value)) { 866fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 867fcf3ce44SJohn Forte } 868fcf3ce44SJohn Forte 869fcf3ce44SJohn Forte (void) sprintf(value, "%d", 870fcf3ce44SJohn Forte icp->conn_params.default_time_to_retain); 87130e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 872fcf3ce44SJohn Forte max_data_length, "DefaultTime2Retain", value)) { 873fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 874fcf3ce44SJohn Forte } 875fcf3ce44SJohn Forte 876fcf3ce44SJohn Forte (void) sprintf(value, "%d", 877fcf3ce44SJohn Forte icp->conn_params.error_recovery_level); 87830e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 879fcf3ce44SJohn Forte max_data_length, "ErrorRecoveryLevel", "0")) { 880fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 881fcf3ce44SJohn Forte } 882fcf3ce44SJohn Forte 88330e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 884fcf3ce44SJohn Forte max_data_length, "IFMarker", 885fcf3ce44SJohn Forte icp->conn_params.ifmarker ? "Yes" : "No")) { 886fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 887fcf3ce44SJohn Forte } 888fcf3ce44SJohn Forte 88930e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 890fcf3ce44SJohn Forte max_data_length, "OFMarker", 891fcf3ce44SJohn Forte icp->conn_params.ofmarker ? "Yes" : "No")) { 892fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 893fcf3ce44SJohn Forte } 894fcf3ce44SJohn Forte 895fcf3ce44SJohn Forte /* 896fcf3ce44SJohn Forte * The following login parameters are "Irrelevant" 897fcf3ce44SJohn Forte * for discovery sessions 898fcf3ce44SJohn Forte */ 899fcf3ce44SJohn Forte if (isp->sess_type != ISCSI_SESS_TYPE_DISCOVERY) { 900fcf3ce44SJohn Forte 90130e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 902fcf3ce44SJohn Forte max_data_length, "InitialR2T", 903fcf3ce44SJohn Forte icp->conn_params.initial_r2t ? 904fcf3ce44SJohn Forte "Yes" : "No")) { 905fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 906fcf3ce44SJohn Forte } 907fcf3ce44SJohn Forte 90830e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 909fcf3ce44SJohn Forte max_data_length, "ImmediateData", 910fcf3ce44SJohn Forte icp->conn_params.immediate_data ? 911fcf3ce44SJohn Forte "Yes" : "No")) { 912fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 913fcf3ce44SJohn Forte } 914fcf3ce44SJohn Forte 915fcf3ce44SJohn Forte (void) sprintf(value, "%d", 916fcf3ce44SJohn Forte icp->conn_params.max_burst_length); 91730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 918fcf3ce44SJohn Forte max_data_length, "MaxBurstLength", value)) { 919fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 920fcf3ce44SJohn Forte } 921fcf3ce44SJohn Forte 922fcf3ce44SJohn Forte (void) sprintf(value, "%d", 923fcf3ce44SJohn Forte icp->conn_params.first_burst_length); 92430e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 925fcf3ce44SJohn Forte "FirstBurstLength", value)) { 926fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 927fcf3ce44SJohn Forte } 928fcf3ce44SJohn Forte 929fcf3ce44SJohn Forte (void) sprintf(value, "%d", 930fcf3ce44SJohn Forte icp->conn_params.max_outstanding_r2t); 93130e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 932fcf3ce44SJohn Forte "MaxOutstandingR2T", value)) { 933fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 934fcf3ce44SJohn Forte } 935fcf3ce44SJohn Forte 936fcf3ce44SJohn Forte (void) sprintf(value, "%d", 937fcf3ce44SJohn Forte icp->conn_params.max_connections); 93830e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 939fcf3ce44SJohn Forte "MaxConnections", value)) { 940fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 941fcf3ce44SJohn Forte } 942fcf3ce44SJohn Forte 94330e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 944fcf3ce44SJohn Forte max_data_length, "DataPDUInOrder", 945fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order ? 946fcf3ce44SJohn Forte "Yes" : "No")) { 947fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 948fcf3ce44SJohn Forte } 949fcf3ce44SJohn Forte 95030e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 951fcf3ce44SJohn Forte max_data_length, "DataSequenceInOrder", 952fcf3ce44SJohn Forte icp->conn_params.data_sequence_in_order ? 953fcf3ce44SJohn Forte "Yes" : "No")) { 954fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 955fcf3ce44SJohn Forte } 956fcf3ce44SJohn Forte } 957fcf3ce44SJohn Forte } 958fcf3ce44SJohn Forte break; 959fcf3ce44SJohn Forte 960fcf3ce44SJohn Forte case ISCSI_SECURITY_NEGOTIATION_STAGE: 961fcf3ce44SJohn Forte keytype = iscsiAuthKeyTypeNone; 962fcf3ce44SJohn Forte rc = iscsiAuthClientSendTransitBit(auth_client, &transit); 963fcf3ce44SJohn Forte 964fcf3ce44SJohn Forte /* 965fcf3ce44SJohn Forte * see if we're ready for a stage change 966fcf3ce44SJohn Forte */ 967fcf3ce44SJohn Forte if (rc == iscsiAuthStatusNoError) { 968fcf3ce44SJohn Forte if (transit) { 969fcf3ce44SJohn Forte icp->conn_next_stage = 970fcf3ce44SJohn Forte ISCSI_OP_PARMS_NEGOTIATION_STAGE; 971fcf3ce44SJohn Forte } else { 972fcf3ce44SJohn Forte icp->conn_next_stage = 973fcf3ce44SJohn Forte ISCSI_SECURITY_NEGOTIATION_STAGE; 974fcf3ce44SJohn Forte } 975fcf3ce44SJohn Forte } else { 976fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 977fcf3ce44SJohn Forte } 978fcf3ce44SJohn Forte 979fcf3ce44SJohn Forte /* 980fcf3ce44SJohn Forte * enumerate all the keys the auth code might want to send 981fcf3ce44SJohn Forte */ 982fcf3ce44SJohn Forte while (iscsiAuthClientGetNextKeyType(&keytype) == 983fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 984fcf3ce44SJohn Forte int present = 0; 985fcf3ce44SJohn Forte char *key = (char *)iscsiAuthClientGetKeyName(keytype); 986fcf3ce44SJohn Forte int key_length = key ? strlen(key) : 0; 98730e7468fSPeter Dunlap int pdu_length = text_pdu->isp_datalen; 988fcf3ce44SJohn Forte char *auth_value = data + pdu_length + key_length + 1; 989fcf3ce44SJohn Forte unsigned int max_length = max_data_length - 990fcf3ce44SJohn Forte (pdu_length + key_length + 1); 991fcf3ce44SJohn Forte 992fcf3ce44SJohn Forte /* 993fcf3ce44SJohn Forte * add the key/value pairs the auth code wants to 994fcf3ce44SJohn Forte * send directly to the PDU, since they could in 995fcf3ce44SJohn Forte * theory be large. 996fcf3ce44SJohn Forte */ 997fcf3ce44SJohn Forte rc = iscsiAuthClientSendKeyValue(auth_client, keytype, 998fcf3ce44SJohn Forte &present, auth_value, max_length); 999fcf3ce44SJohn Forte if ((rc == iscsiAuthStatusNoError) && present) { 1000fcf3ce44SJohn Forte /* 1001fcf3ce44SJohn Forte * actually fill in the key 1002fcf3ce44SJohn Forte */ 1003fcf3ce44SJohn Forte (void) strncpy(&data[pdu_length], key, 1004fcf3ce44SJohn Forte key_length); 1005fcf3ce44SJohn Forte pdu_length += key_length; 1006fcf3ce44SJohn Forte data[pdu_length] = '='; 1007fcf3ce44SJohn Forte pdu_length++; 1008fcf3ce44SJohn Forte /* 1009fcf3ce44SJohn Forte * adjust the PDU's data segment length to 1010fcf3ce44SJohn Forte * include the value and trailing NULL 1011fcf3ce44SJohn Forte */ 1012fcf3ce44SJohn Forte pdu_length += strlen(auth_value) + 1; 101330e7468fSPeter Dunlap text_pdu->isp_datalen = pdu_length; 1014fcf3ce44SJohn Forte hton24(ihp->dlength, pdu_length); 1015fcf3ce44SJohn Forte } 1016fcf3ce44SJohn Forte } 1017fcf3ce44SJohn Forte 1018fcf3ce44SJohn Forte break; 1019fcf3ce44SJohn Forte case ISCSI_FULL_FEATURE_PHASE: 1020fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1021fcf3ce44SJohn Forte "failed - can't send login in full feature stage", 1022fcf3ce44SJohn Forte icp->conn_oid); 1023fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1024fcf3ce44SJohn Forte default: 1025fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1026fcf3ce44SJohn Forte "failed - can't send login in unknown stage (%d)", 1027fcf3ce44SJohn Forte icp->conn_oid, icp->conn_current_stage); 1028fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1029fcf3ce44SJohn Forte } 1030fcf3ce44SJohn Forte 1031fcf3ce44SJohn Forte /* fill in the flags */ 1032fcf3ce44SJohn Forte ilhp->flags = icp->conn_current_stage << 2; 1033fcf3ce44SJohn Forte if (transit) { 1034fcf3ce44SJohn Forte /* transit to the next stage */ 1035fcf3ce44SJohn Forte ilhp->flags |= icp->conn_next_stage; 1036fcf3ce44SJohn Forte ilhp->flags |= ISCSI_FLAG_LOGIN_TRANSIT; 1037fcf3ce44SJohn Forte } else { 1038fcf3ce44SJohn Forte /* next == current */ 1039fcf3ce44SJohn Forte ilhp->flags |= icp->conn_current_stage; 1040fcf3ce44SJohn Forte } 1041fcf3ce44SJohn Forte 1042fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 1043fcf3ce44SJohn Forte } 1044fcf3ce44SJohn Forte 1045fcf3ce44SJohn Forte 1046fcf3ce44SJohn Forte /* 1047fcf3ce44SJohn Forte * iscsi_process_login_response - This assumes the text data is 1048fcf3ce44SJohn Forte * always NUL terminated. The caller can always arrange for that by 1049fcf3ce44SJohn Forte * using a slightly larger buffer than the max PDU size, and then 1050fcf3ce44SJohn Forte * appending a NUL to the PDU. 1051fcf3ce44SJohn Forte */ 1052fcf3ce44SJohn Forte static iscsi_status_t 1053fcf3ce44SJohn Forte iscsi_process_login_response(iscsi_conn_t *icp, 1054fcf3ce44SJohn Forte iscsi_login_rsp_hdr_t *ilrhp, char *data, int max_data_length) 1055fcf3ce44SJohn Forte { 1056fcf3ce44SJohn Forte iscsi_sess_t *isp = NULL; 1057fcf3ce44SJohn Forte IscsiAuthClient *auth_client = NULL; 1058fcf3ce44SJohn Forte int transit = 0; 1059fcf3ce44SJohn Forte char *text = data; 1060fcf3ce44SJohn Forte char *end = NULL; 1061fcf3ce44SJohn Forte int pdu_current_stage = 0; 1062fcf3ce44SJohn Forte int pdu_next_stage = 0; 1063fcf3ce44SJohn Forte int debug_status = 0; 1064fcf3ce44SJohn Forte unsigned long tmp; 1065fcf3ce44SJohn Forte char *tmpe; 1066fcf3ce44SJohn Forte boolean_t fbl_irrelevant = B_FALSE; 1067fcf3ce44SJohn Forte 1068fcf3ce44SJohn Forte ASSERT(icp != NULL); 1069fcf3ce44SJohn Forte ASSERT(ilrhp != NULL); 1070fcf3ce44SJohn Forte ASSERT(data != NULL); 1071fcf3ce44SJohn Forte isp = icp->conn_sess; 1072fcf3ce44SJohn Forte ASSERT(isp != NULL); 1073fcf3ce44SJohn Forte 1074fcf3ce44SJohn Forte auth_client = 1075fcf3ce44SJohn Forte (isp->sess_auth.auth_buffers && isp->sess_auth.num_auth_buffers) ? 1076fcf3ce44SJohn Forte (IscsiAuthClient *) isp->sess_auth.auth_buffers[0].address : NULL; 1077fcf3ce44SJohn Forte transit = ilrhp->flags & ISCSI_FLAG_LOGIN_TRANSIT; 1078fcf3ce44SJohn Forte 1079fcf3ce44SJohn Forte /* verify the initial buffer was big enough to hold everything */ 1080fcf3ce44SJohn Forte end = text + ntoh24(ilrhp->dlength) + 1; 1081fcf3ce44SJohn Forte if (end >= (data + max_data_length)) { 1082fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1083fcf3ce44SJohn Forte "buffer too small", icp->conn_oid); 1084fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1085fcf3ce44SJohn Forte } 1086fcf3ce44SJohn Forte *end = '\0'; 1087fcf3ce44SJohn Forte 1088fcf3ce44SJohn Forte /* if the response status was success, sanity check the response */ 1089fcf3ce44SJohn Forte if (ilrhp->status_class == ISCSI_STATUS_CLASS_SUCCESS) { 1090fcf3ce44SJohn Forte /* check the active version */ 1091fcf3ce44SJohn Forte if (ilrhp->active_version != ISCSI_DRAFT20_VERSION) { 1092fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1093fcf3ce44SJohn Forte "failed - target version incompatible " 1094fcf3ce44SJohn Forte "received:0x%0x2x expected:0x%02x", 1095fcf3ce44SJohn Forte icp->conn_oid, ilrhp->active_version, 1096fcf3ce44SJohn Forte ISCSI_DRAFT20_VERSION); 1097fcf3ce44SJohn Forte return (ISCSI_STATUS_VERSION_MISMATCH); 1098fcf3ce44SJohn Forte } 1099fcf3ce44SJohn Forte 1100fcf3ce44SJohn Forte /* make sure the current stage matches */ 1101fcf3ce44SJohn Forte pdu_current_stage = (ilrhp->flags & 1102fcf3ce44SJohn Forte ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2; 1103fcf3ce44SJohn Forte if (pdu_current_stage != icp->conn_current_stage) { 1104fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1105fcf3ce44SJohn Forte "failed - login response contained invalid " 1106fcf3ce44SJohn Forte "stage %d", icp->conn_oid, pdu_current_stage); 1107fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1108fcf3ce44SJohn Forte } 1109fcf3ce44SJohn Forte 1110fcf3ce44SJohn Forte /* 1111fcf3ce44SJohn Forte * Make sure that we're actually advancing 1112fcf3ce44SJohn Forte * if the T-bit is set 1113fcf3ce44SJohn Forte */ 1114fcf3ce44SJohn Forte pdu_next_stage = ilrhp->flags & 1115fcf3ce44SJohn Forte ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; 1116fcf3ce44SJohn Forte if (transit && (pdu_next_stage <= icp->conn_current_stage)) { 1117fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1118fcf3ce44SJohn Forte "failed - login response wants to go to stage " 1119fcf3ce44SJohn Forte "%d, but we want stage %d", icp->conn_oid, 1120fcf3ce44SJohn Forte pdu_next_stage, icp->conn_next_stage); 1121fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1122fcf3ce44SJohn Forte } 1123fcf3ce44SJohn Forte } 1124fcf3ce44SJohn Forte 1125fcf3ce44SJohn Forte if (icp->conn_current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE) { 1126fcf3ce44SJohn Forte if (iscsiAuthClientRecvBegin(auth_client) != 1127fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 1128fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1129fcf3ce44SJohn Forte "authentication receive failed", icp->conn_oid); 1130fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1131fcf3ce44SJohn Forte } 1132fcf3ce44SJohn Forte 1133fcf3ce44SJohn Forte if (iscsiAuthClientRecvTransitBit(auth_client, 1134fcf3ce44SJohn Forte transit) != iscsiAuthStatusNoError) { 1135fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1136fcf3ce44SJohn Forte "authentication transmit failed", icp->conn_oid); 1137fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1138fcf3ce44SJohn Forte } 1139fcf3ce44SJohn Forte } 1140fcf3ce44SJohn Forte 1141fcf3ce44SJohn Forte /* 1142fcf3ce44SJohn Forte * scan the text data 1143fcf3ce44SJohn Forte */ 1144fcf3ce44SJohn Forte more_text: 1145fcf3ce44SJohn Forte while (text && (text < end)) { 1146fcf3ce44SJohn Forte char *value = NULL; 1147fcf3ce44SJohn Forte char *value_end = NULL; 1148fcf3ce44SJohn Forte 1149fcf3ce44SJohn Forte /* 1150fcf3ce44SJohn Forte * skip any NULs separating each text key=value pair 1151fcf3ce44SJohn Forte */ 1152fcf3ce44SJohn Forte while ((text < end) && (*text == '\0')) { 1153fcf3ce44SJohn Forte text++; 1154fcf3ce44SJohn Forte } 1155fcf3ce44SJohn Forte if (text >= end) { 1156fcf3ce44SJohn Forte break; 1157fcf3ce44SJohn Forte } 1158fcf3ce44SJohn Forte 1159fcf3ce44SJohn Forte /* 1160fcf3ce44SJohn Forte * handle keys appropriate for each stage 1161fcf3ce44SJohn Forte */ 1162fcf3ce44SJohn Forte switch (icp->conn_current_stage) { 1163fcf3ce44SJohn Forte case ISCSI_SECURITY_NEGOTIATION_STAGE: 1164fcf3ce44SJohn Forte /* 1165fcf3ce44SJohn Forte * a few keys are possible in Security stage 1166fcf3ce44SJohn Forte * * which the auth code doesn't care about, 1167fcf3ce44SJohn Forte * * but which we might want to see, or at 1168fcf3ce44SJohn Forte * * least not choke on. 1169fcf3ce44SJohn Forte */ 1170fcf3ce44SJohn Forte if (iscsi_find_key_value("TargetAlias", 1171fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1172fcf3ce44SJohn Forte isp->sess_alias_length = 1173fcf3ce44SJohn Forte sizeof (isp->sess_alias) - 1; 1174fcf3ce44SJohn Forte 1175fcf3ce44SJohn Forte if ((value_end - value) < 1176fcf3ce44SJohn Forte isp->sess_alias_length) { 1177fcf3ce44SJohn Forte isp->sess_alias_length = 1178fcf3ce44SJohn Forte value_end - value; 1179fcf3ce44SJohn Forte } 1180fcf3ce44SJohn Forte 1181fcf3ce44SJohn Forte bcopy(value, isp->sess_alias, 1182fcf3ce44SJohn Forte isp->sess_alias_length); 1183fcf3ce44SJohn Forte isp->sess_alias[isp->sess_alias_length + 1] = 1184fcf3ce44SJohn Forte '\0'; 1185fcf3ce44SJohn Forte text = value_end; 1186fcf3ce44SJohn Forte 1187fcf3ce44SJohn Forte } else if (iscsi_find_key_value("TargetAddress", 1188fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1189fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(iscsi_update_address( 1190fcf3ce44SJohn Forte icp, value))) { 1191fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1192fcf3ce44SJohn Forte "login failed - login redirection " 1193fcf3ce44SJohn Forte "invalid", icp->conn_oid); 1194fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1195fcf3ce44SJohn Forte } 1196fcf3ce44SJohn Forte text = value_end; 1197fcf3ce44SJohn Forte } else if (iscsi_find_key_value("TargetPortalGroupTag", 1198fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1199fcf3ce44SJohn Forte /* 1200fcf3ce44SJohn Forte * We should have already obtained this via 1201fcf3ce44SJohn Forte * discovery. We've already picked an isid, 1202fcf3ce44SJohn Forte * so the most we can do is confirm we reached 1203fcf3ce44SJohn Forte * the portal group we were expecting to. 1204fcf3ce44SJohn Forte */ 1205fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1206fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1207fcf3ce44SJohn Forte } 1208fcf3ce44SJohn Forte if (isp->sess_tpgt_conf != ISCSI_DEFAULT_TPGT) { 1209fcf3ce44SJohn Forte if (tmp != isp->sess_tpgt_conf) { 1210fcf3ce44SJohn Forte 1211fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - target " 1212fcf3ce44SJohn Forte "protocol group tag mismatch, expected %d, received %lu", 1213fcf3ce44SJohn Forte icp->conn_oid, isp->sess_tpgt_conf, tmp); 1214cc7ef495Syi zhang - Sun Microsystems - Beijing China return (ISCSI_STATUS_LOGIN_TPGT_NEGO_FAIL); 1215fcf3ce44SJohn Forte 1216fcf3ce44SJohn Forte } 1217fcf3ce44SJohn Forte } 1218fcf3ce44SJohn Forte isp->sess_tpgt_nego = (int)tmp; 1219fcf3ce44SJohn Forte text = value_end; 1220fcf3ce44SJohn Forte } else { 1221fcf3ce44SJohn Forte /* 1222fcf3ce44SJohn Forte * any key we don't recognize either goes 1223fcf3ce44SJohn Forte * to the auth code, or we choke on it 1224fcf3ce44SJohn Forte */ 1225fcf3ce44SJohn Forte int keytype = iscsiAuthKeyTypeNone; 1226fcf3ce44SJohn Forte 1227fcf3ce44SJohn Forte while (iscsiAuthClientGetNextKeyType( 1228fcf3ce44SJohn Forte &keytype) == iscsiAuthStatusNoError) { 1229fcf3ce44SJohn Forte 1230fcf3ce44SJohn Forte char *key = 1231fcf3ce44SJohn Forte (char *)iscsiAuthClientGetKeyName( 1232fcf3ce44SJohn Forte keytype); 1233fcf3ce44SJohn Forte 1234fcf3ce44SJohn Forte if ((key) && 1235fcf3ce44SJohn Forte (iscsi_find_key_value(key, 1236fcf3ce44SJohn Forte text, end, &value, &value_end))) { 1237fcf3ce44SJohn Forte 1238fcf3ce44SJohn Forte if (iscsiAuthClientRecvKeyValue 1239fcf3ce44SJohn Forte (auth_client, keytype, 1240fcf3ce44SJohn Forte value) != 1241fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 1242fcf3ce44SJohn Forte 1243fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - can't accept " 1244fcf3ce44SJohn Forte "%s in security stage", icp->conn_oid, text); 1245fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1246fcf3ce44SJohn Forte 1247fcf3ce44SJohn Forte } 1248fcf3ce44SJohn Forte text = value_end; 1249fcf3ce44SJohn Forte goto more_text; 1250fcf3ce44SJohn Forte } 1251fcf3ce44SJohn Forte } 1252fcf3ce44SJohn Forte 1253fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - can't except " 1254fcf3ce44SJohn Forte "%s in security stage", icp->conn_oid, text); 1255fcf3ce44SJohn Forte 1256fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1257fcf3ce44SJohn Forte } 1258fcf3ce44SJohn Forte break; 1259fcf3ce44SJohn Forte case ISCSI_OP_PARMS_NEGOTIATION_STAGE: 1260fcf3ce44SJohn Forte if (iscsi_find_key_value("TargetAlias", text, 1261fcf3ce44SJohn Forte end, &value, &value_end)) { 1262fcf3ce44SJohn Forte isp->sess_alias_length = 1263fcf3ce44SJohn Forte sizeof (isp->sess_alias) - 1; 1264fcf3ce44SJohn Forte 1265fcf3ce44SJohn Forte if ((value_end - value) < 1266fcf3ce44SJohn Forte isp->sess_alias_length) { 1267fcf3ce44SJohn Forte isp->sess_alias_length = 1268fcf3ce44SJohn Forte value_end - value; 1269fcf3ce44SJohn Forte } 1270fcf3ce44SJohn Forte 1271fcf3ce44SJohn Forte bcopy(value, isp->sess_alias, 1272fcf3ce44SJohn Forte isp->sess_alias_length); 1273fcf3ce44SJohn Forte isp->sess_alias[isp->sess_alias_length + 1] = 1274fcf3ce44SJohn Forte '\0'; 1275fcf3ce44SJohn Forte text = value_end; 1276fcf3ce44SJohn Forte 1277fcf3ce44SJohn Forte } else if (iscsi_find_key_value("TargetAddress", 1278fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1279fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(iscsi_update_address( 1280fcf3ce44SJohn Forte icp, value))) { 1281fcf3ce44SJohn Forte 1282fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - login " 1283fcf3ce44SJohn Forte "redirection invalid", icp->conn_oid); 1284fcf3ce44SJohn Forte 1285fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1286fcf3ce44SJohn Forte } 1287fcf3ce44SJohn Forte text = value_end; 1288fcf3ce44SJohn Forte } else if (iscsi_find_key_value("TargetPortalGroupTag", 1289fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1290fcf3ce44SJohn Forte /* 1291fcf3ce44SJohn Forte * We should have already obtained this via 1292fcf3ce44SJohn Forte * discovery. We've already picked an isid, 1293fcf3ce44SJohn Forte * so the most we can do is confirm we reached 1294fcf3ce44SJohn Forte * the portal group we were expecting to. 1295fcf3ce44SJohn Forte */ 1296fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1297fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1298fcf3ce44SJohn Forte } 1299fcf3ce44SJohn Forte if (isp->sess_tpgt_conf != ISCSI_DEFAULT_TPGT) { 1300fcf3ce44SJohn Forte if (tmp != isp->sess_tpgt_conf) { 1301fcf3ce44SJohn Forte 1302fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - target portal " 1303fcf3ce44SJohn Forte "tag mismatch, expected:%d received:%lu", icp->conn_oid, 1304fcf3ce44SJohn Forte isp->sess_tpgt_conf, tmp); 1305cc7ef495Syi zhang - Sun Microsystems - Beijing China return (ISCSI_STATUS_LOGIN_TPGT_NEGO_FAIL); 1306fcf3ce44SJohn Forte 1307fcf3ce44SJohn Forte } 1308fcf3ce44SJohn Forte } 1309fcf3ce44SJohn Forte isp->sess_tpgt_nego = (int)tmp; 1310fcf3ce44SJohn Forte text = value_end; 1311fcf3ce44SJohn Forte 1312fcf3ce44SJohn Forte } else if (iscsi_find_key_value("InitialR2T", 1313fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1314fcf3ce44SJohn Forte 1315fcf3ce44SJohn Forte /* 1316fcf3ce44SJohn Forte * iSCSI RFC section 12.10 states that 1317fcf3ce44SJohn Forte * InitialR2T is Irrelevant for a 1318fcf3ce44SJohn Forte * discovery session. 1319fcf3ce44SJohn Forte */ 1320fcf3ce44SJohn Forte if (isp->sess_type == 1321fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1322fcf3ce44SJohn Forte /* EMPTY */ 1323fcf3ce44SJohn Forte } else if (value == NULL) { 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 } else if (strcmp(value, "Yes") == 0) { 1330fcf3ce44SJohn Forte icp->conn_params.initial_r2t = B_TRUE; 1331fcf3ce44SJohn Forte } else if (strcmp(value, "No") == 0) { 1332fcf3ce44SJohn Forte icp->conn_params.initial_r2t = B_FALSE; 1333fcf3ce44SJohn Forte } else { 1334fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1335fcf3ce44SJohn Forte "login failed - InitialR2T is " 1336fcf3ce44SJohn Forte "invalid - protocol error", 1337fcf3ce44SJohn Forte icp->conn_oid); 1338fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1339fcf3ce44SJohn Forte } 1340fcf3ce44SJohn Forte text = value_end; 1341fcf3ce44SJohn Forte 1342fcf3ce44SJohn Forte } else if (iscsi_find_key_value("ImmediateData", 1343fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1344fcf3ce44SJohn Forte 1345fcf3ce44SJohn Forte /* 1346fcf3ce44SJohn Forte * iSCSI RFC section 12.11 states that 1347fcf3ce44SJohn Forte * ImmediateData is Irrelevant for a 1348fcf3ce44SJohn Forte * discovery session. 1349fcf3ce44SJohn Forte */ 1350fcf3ce44SJohn Forte if (isp->sess_type == 1351fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1352fcf3ce44SJohn Forte /* EMPTY */ 1353fcf3ce44SJohn Forte } else if (value == NULL) { 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 } else if (strcmp(value, "Yes") == 0) { 1360fcf3ce44SJohn Forte icp->conn_params.immediate_data = 1; 1361fcf3ce44SJohn Forte } else if (strcmp(value, "No") == 0) { 1362fcf3ce44SJohn Forte icp->conn_params.immediate_data = 0; 1363fcf3ce44SJohn Forte } else { 1364fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1365fcf3ce44SJohn Forte "login failed - ImmediateData is " 1366fcf3ce44SJohn Forte "invalid - protocol error", 1367fcf3ce44SJohn Forte icp->conn_oid); 1368fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1369fcf3ce44SJohn Forte } 1370fcf3ce44SJohn Forte text = value_end; 1371fcf3ce44SJohn Forte 1372fcf3ce44SJohn Forte } else if (iscsi_find_key_value( 1373fcf3ce44SJohn Forte "MaxRecvDataSegmentLength", text, end, 1374fcf3ce44SJohn Forte &value, &value_end)) { 1375fcf3ce44SJohn Forte 1376fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1377fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1378fcf3ce44SJohn Forte "login failed - MaxRecvDataSegment" 1379fcf3ce44SJohn Forte "Length is invalid - protocol " 1380fcf3ce44SJohn Forte "error", icp->conn_oid); 1381fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1382fcf3ce44SJohn Forte } 1383fcf3ce44SJohn Forte icp->conn_params.max_recv_data_seg_len = 1384fcf3ce44SJohn Forte icp->conn_params.max_xmit_data_seg_len = 1385fcf3ce44SJohn Forte (int)tmp; 1386fcf3ce44SJohn Forte 1387fcf3ce44SJohn Forte text = value_end; 1388fcf3ce44SJohn Forte } else if (iscsi_find_key_value("FirstBurstLength", 1389fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1390fcf3ce44SJohn Forte 1391fcf3ce44SJohn Forte /* 1392fcf3ce44SJohn Forte * iSCSI RFC section 12.14 states that 1393fcf3ce44SJohn Forte * FirstBurstLength is Irrelevant if 1394fcf3ce44SJohn Forte * InitialR2T=Yes and ImmediateData=No 1395fcf3ce44SJohn Forte * or is this is a discovery session. 1396fcf3ce44SJohn Forte */ 1397fcf3ce44SJohn Forte if ((isp->sess_type == 1398fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY)) { 1399fcf3ce44SJohn Forte /* EMPTY */ 1400fcf3ce44SJohn Forte } else if (value && 1401fcf3ce44SJohn Forte (strcmp(value, "Irrelevant") == 0)) { 1402fcf3ce44SJohn Forte /* irrelevant */ 1403fcf3ce44SJohn Forte fbl_irrelevant = B_TRUE; 1404fcf3ce44SJohn Forte } else if (ddi_strtoul( 1405fcf3ce44SJohn Forte value, &tmpe, 0, &tmp) != 0) { 1406fcf3ce44SJohn Forte /* bad value */ 1407fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1408fcf3ce44SJohn Forte "login failed - FirstBurstLength" 1409fcf3ce44SJohn Forte "is invalid - protocol error", 1410fcf3ce44SJohn Forte icp->conn_oid); 1411fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1412fcf3ce44SJohn Forte } else { 1413fcf3ce44SJohn Forte /* good value */ 1414fcf3ce44SJohn Forte icp->conn_params.first_burst_length = 1415fcf3ce44SJohn Forte (int)tmp; 1416fcf3ce44SJohn Forte } 1417fcf3ce44SJohn Forte text = value_end; 1418fcf3ce44SJohn Forte } else if (iscsi_find_key_value("MaxBurstLength", 1419fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1420fcf3ce44SJohn Forte /* 1421fcf3ce44SJohn Forte * iSCSI RFC section 12.13 states that 1422fcf3ce44SJohn Forte * MaxBurstLength is Irrelevant for a 1423fcf3ce44SJohn Forte * discovery session. 1424fcf3ce44SJohn Forte */ 1425fcf3ce44SJohn Forte if (isp->sess_type == 1426fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1427fcf3ce44SJohn Forte /* EMPTY */ 1428fcf3ce44SJohn Forte } else if (ddi_strtoul( 1429fcf3ce44SJohn Forte value, &tmpe, 0, &tmp) != 0) { 1430fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1431fcf3ce44SJohn Forte "login failed - MaxBurstLength" 1432fcf3ce44SJohn Forte "is invalid - protocol error", 1433fcf3ce44SJohn Forte icp->conn_oid); 1434fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1435fcf3ce44SJohn Forte } else { 1436fcf3ce44SJohn Forte icp->conn_params.max_burst_length = 1437fcf3ce44SJohn Forte (int)tmp; 1438fcf3ce44SJohn Forte } 1439fcf3ce44SJohn Forte 1440fcf3ce44SJohn Forte text = value_end; 1441fcf3ce44SJohn Forte 1442fcf3ce44SJohn Forte } else if (iscsi_find_key_value("HeaderDigest", 1443fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1444fcf3ce44SJohn Forte 1445fcf3ce44SJohn Forte if (strcmp(value, "None") == 0) { 1446fcf3ce44SJohn Forte if (icp->conn_params.header_digest != 1447fcf3ce44SJohn Forte ISCSI_DIGEST_CRC32C) { 1448fcf3ce44SJohn Forte icp->conn_params.header_digest = 1449fcf3ce44SJohn Forte ISCSI_DIGEST_NONE; 1450fcf3ce44SJohn Forte } else { 1451fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi " 1452fcf3ce44SJohn Forte "connection(%u) login " 1453fcf3ce44SJohn Forte "failed - HeaderDigest=" 1454fcf3ce44SJohn Forte "CRC32 is required, can't " 1455fcf3ce44SJohn Forte "accept %s", 1456fcf3ce44SJohn Forte icp->conn_oid, text); 1457fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1458fcf3ce44SJohn Forte } 1459fcf3ce44SJohn Forte } else if (strcmp(value, "CRC32C") == 0) { 1460fcf3ce44SJohn Forte if (icp->conn_params.header_digest != 1461fcf3ce44SJohn Forte ISCSI_DIGEST_NONE) { 1462fcf3ce44SJohn Forte icp->conn_params.header_digest = 1463fcf3ce44SJohn Forte ISCSI_DIGEST_CRC32C; 1464fcf3ce44SJohn Forte } else { 1465fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi " 1466fcf3ce44SJohn Forte "connection(%u) login " 1467fcf3ce44SJohn Forte "failed - HeaderDigest=" 1468fcf3ce44SJohn Forte "None is required, can't " 1469fcf3ce44SJohn Forte "accept %s", 1470fcf3ce44SJohn Forte icp->conn_oid, text); 1471fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1472fcf3ce44SJohn Forte } 1473fcf3ce44SJohn Forte } else { 1474fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1475fcf3ce44SJohn Forte "login failed - HeaderDigest " 1476fcf3ce44SJohn Forte "can't accept %s", icp->conn_oid, 1477fcf3ce44SJohn Forte text); 1478fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1479fcf3ce44SJohn Forte } 1480fcf3ce44SJohn Forte text = value_end; 1481fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DataDigest", text, 1482fcf3ce44SJohn Forte end, &value, &value_end)) { 1483fcf3ce44SJohn Forte 1484fcf3ce44SJohn Forte if (strcmp(value, "None") == 0) { 1485fcf3ce44SJohn Forte if (icp->conn_params.data_digest != 1486fcf3ce44SJohn Forte ISCSI_DIGEST_CRC32C) { 1487fcf3ce44SJohn Forte icp->conn_params.data_digest = 1488fcf3ce44SJohn Forte ISCSI_DIGEST_NONE; 1489fcf3ce44SJohn Forte } else { 1490fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi " 1491fcf3ce44SJohn Forte "connection(%u) login " 1492fcf3ce44SJohn Forte "failed - DataDigest=" 1493fcf3ce44SJohn Forte "CRC32C is required, " 1494fcf3ce44SJohn Forte "can't accept %s", 1495fcf3ce44SJohn Forte icp->conn_oid, text); 1496fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1497fcf3ce44SJohn Forte } 1498fcf3ce44SJohn Forte } else if (strcmp(value, "CRC32C") == 0) { 1499fcf3ce44SJohn Forte if (icp->conn_params.data_digest != 1500fcf3ce44SJohn Forte ISCSI_DIGEST_NONE) { 1501fcf3ce44SJohn Forte icp->conn_params.data_digest = 1502fcf3ce44SJohn Forte ISCSI_DIGEST_CRC32C; 1503fcf3ce44SJohn Forte } else { 1504fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi " 1505fcf3ce44SJohn Forte "connection(%u) login " 1506fcf3ce44SJohn Forte "failed - DataDigest=None " 1507fcf3ce44SJohn Forte "is required, can't " 1508fcf3ce44SJohn Forte "accept %s", 1509fcf3ce44SJohn Forte icp->conn_oid, text); 1510fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1511fcf3ce44SJohn Forte } 1512fcf3ce44SJohn Forte } else { 1513fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1514fcf3ce44SJohn Forte "login failed - can't accept %s", 1515fcf3ce44SJohn Forte icp->conn_oid, text); 1516fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1517fcf3ce44SJohn Forte } 1518fcf3ce44SJohn Forte text = value_end; 1519fcf3ce44SJohn Forte 1520fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DefaultTime2Wait", 1521fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1522fcf3ce44SJohn Forte 1523fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1524fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1525fcf3ce44SJohn Forte "login failed - DefaultTime2Wait " 1526fcf3ce44SJohn Forte "is invalid - protocol error", 1527fcf3ce44SJohn Forte icp->conn_oid); 1528fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1529fcf3ce44SJohn Forte } 1530fcf3ce44SJohn Forte icp->conn_params.default_time_to_wait = 1531fcf3ce44SJohn Forte (int)tmp; 1532fcf3ce44SJohn Forte 1533fcf3ce44SJohn Forte text = value_end; 1534fcf3ce44SJohn Forte 1535fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DefaultTime2Retain", 1536fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1537fcf3ce44SJohn Forte 1538fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1539fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1540fcf3ce44SJohn Forte "login failed - DefaultTime2Retain " 1541fcf3ce44SJohn Forte "is invalid - protocol error", 1542fcf3ce44SJohn Forte icp->conn_oid); 1543fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1544fcf3ce44SJohn Forte } 1545fcf3ce44SJohn Forte icp->conn_params.default_time_to_retain = 1546fcf3ce44SJohn Forte (int)tmp; 1547fcf3ce44SJohn Forte 1548fcf3ce44SJohn Forte text = value_end; 1549fcf3ce44SJohn Forte 1550fcf3ce44SJohn Forte } else if (iscsi_find_key_value("OFMarker", text, 1551fcf3ce44SJohn Forte end, &value, &value_end)) { 1552fcf3ce44SJohn Forte 1553fcf3ce44SJohn Forte /* 1554fcf3ce44SJohn Forte * result function is AND, target must 1555fcf3ce44SJohn Forte * honor our No 1556fcf3ce44SJohn Forte */ 1557fcf3ce44SJohn Forte text = value_end; 1558fcf3ce44SJohn Forte 1559fcf3ce44SJohn Forte } else if (iscsi_find_key_value("OFMarkInt", text, 1560fcf3ce44SJohn Forte end, &value, &value_end)) { 1561fcf3ce44SJohn Forte 1562fcf3ce44SJohn Forte /* 1563fcf3ce44SJohn Forte * we don't do markers, so we don't care 1564fcf3ce44SJohn Forte */ 1565fcf3ce44SJohn Forte text = value_end; 1566fcf3ce44SJohn Forte 1567fcf3ce44SJohn Forte } else if (iscsi_find_key_value("IFMarker", text, 1568fcf3ce44SJohn Forte end, &value, &value_end)) { 1569fcf3ce44SJohn Forte 1570fcf3ce44SJohn Forte /* 1571fcf3ce44SJohn Forte * result function is AND, target must 1572fcf3ce44SJohn Forte * honor our No 1573fcf3ce44SJohn Forte */ 1574fcf3ce44SJohn Forte text = value_end; 1575fcf3ce44SJohn Forte 1576fcf3ce44SJohn Forte } else if (iscsi_find_key_value("IFMarkInt", text, 1577fcf3ce44SJohn Forte end, &value, &value_end)) { 1578fcf3ce44SJohn Forte 1579fcf3ce44SJohn Forte /* 1580fcf3ce44SJohn Forte * we don't do markers, so we don't care 1581fcf3ce44SJohn Forte */ 1582fcf3ce44SJohn Forte text = value_end; 1583fcf3ce44SJohn Forte 1584fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DataPDUInOrder", 1585fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1586fcf3ce44SJohn Forte 1587fcf3ce44SJohn Forte /* 1588fcf3ce44SJohn Forte * iSCSI RFC section 12.18 states that 1589fcf3ce44SJohn Forte * DataPDUInOrder is Irrelevant for a 1590fcf3ce44SJohn Forte * discovery session. 1591fcf3ce44SJohn Forte */ 1592fcf3ce44SJohn Forte if (isp->sess_type == 1593fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1594fcf3ce44SJohn Forte /* EMPTY */ 1595fcf3ce44SJohn Forte } else if (value == NULL) { 1596fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1597fcf3ce44SJohn Forte "login failed - InitialR2T is " 1598fcf3ce44SJohn Forte "invalid - protocol error", 1599fcf3ce44SJohn Forte icp->conn_oid); 1600fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1601fcf3ce44SJohn Forte } else if (strcmp(value, "Yes") == 0) { 1602fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order = 1603fcf3ce44SJohn Forte B_TRUE; 1604fcf3ce44SJohn Forte } else if (strcmp(value, "No") == 0) { 1605fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order = 1606fcf3ce44SJohn Forte B_FALSE; 1607fcf3ce44SJohn Forte } else { 1608fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1609fcf3ce44SJohn Forte "login failed - InitialR2T is " 1610fcf3ce44SJohn Forte "invalid - protocol error", 1611fcf3ce44SJohn Forte icp->conn_oid); 1612fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1613fcf3ce44SJohn Forte } 1614fcf3ce44SJohn Forte text = value_end; 1615fcf3ce44SJohn Forte 1616fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DataSequenceInOrder", 1617fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1618fcf3ce44SJohn Forte 1619fcf3ce44SJohn Forte /* 1620fcf3ce44SJohn Forte * iSCSI RFC section 12.19 states that 1621fcf3ce44SJohn Forte * DataSequenceInOrder is Irrelevant for a 1622fcf3ce44SJohn Forte * discovery session. 1623fcf3ce44SJohn Forte */ 1624fcf3ce44SJohn Forte if (isp->sess_type == 1625fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1626fcf3ce44SJohn Forte /* EMPTY */ 1627fcf3ce44SJohn Forte } else if (value == NULL) { 1628fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1629fcf3ce44SJohn Forte "login failed - InitialR2T is " 1630fcf3ce44SJohn Forte "invalid - protocol error", 1631fcf3ce44SJohn Forte icp->conn_oid); 1632fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1633fcf3ce44SJohn Forte } else if (strcmp(value, "Yes") == 0) { 1634fcf3ce44SJohn Forte icp->conn_params. 1635fcf3ce44SJohn Forte data_sequence_in_order = B_TRUE; 1636fcf3ce44SJohn Forte } else if (strcmp(value, "No") == 0) { 1637fcf3ce44SJohn Forte icp->conn_params. 1638fcf3ce44SJohn Forte data_sequence_in_order = B_FALSE; 1639fcf3ce44SJohn Forte } else { 1640fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1641fcf3ce44SJohn Forte "login failed - InitialR2T is " 1642fcf3ce44SJohn Forte "invalid - protocol error", 1643fcf3ce44SJohn Forte icp->conn_oid); 1644fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1645fcf3ce44SJohn Forte } 1646fcf3ce44SJohn Forte text = value_end; 1647fcf3ce44SJohn Forte 1648fcf3ce44SJohn Forte } else if (iscsi_find_key_value("MaxOutstandingR2T", 1649fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1650fcf3ce44SJohn Forte 1651fcf3ce44SJohn Forte /* 1652fcf3ce44SJohn Forte * iSCSI RFC section 12.17 states that 1653fcf3ce44SJohn Forte * MaxOutstandingR2T is Irrelevant for a 1654fcf3ce44SJohn Forte * discovery session. 1655fcf3ce44SJohn Forte */ 1656fcf3ce44SJohn Forte if (isp->sess_type == 1657fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1658fcf3ce44SJohn Forte /* EMPTY */ 1659fcf3ce44SJohn Forte } else if (strcmp(value, "1")) { 1660fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1661fcf3ce44SJohn Forte "login failed - can't accept " 1662fcf3ce44SJohn Forte "MaxOutstandingR2T %s", 1663fcf3ce44SJohn Forte icp->conn_oid, value); 1664fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1665fcf3ce44SJohn Forte } 1666fcf3ce44SJohn Forte text = value_end; 1667fcf3ce44SJohn Forte 1668fcf3ce44SJohn Forte } else if (iscsi_find_key_value("MaxConnections", 1669fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1670fcf3ce44SJohn Forte 1671fcf3ce44SJohn Forte /* 1672fcf3ce44SJohn Forte * iSCSI RFC section 12.2 states that 1673fcf3ce44SJohn Forte * MaxConnections is Irrelevant for a 1674fcf3ce44SJohn Forte * discovery session. 1675fcf3ce44SJohn Forte */ 1676fcf3ce44SJohn Forte if (isp->sess_type == 1677fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1678fcf3ce44SJohn Forte /* EMPTY */ 1679fcf3ce44SJohn Forte } else if (strcmp(value, "1")) { 1680fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1681fcf3ce44SJohn Forte "login failed - can't accept " 1682fcf3ce44SJohn Forte "MaxConnections %s", 1683fcf3ce44SJohn Forte icp->conn_oid, value); 1684fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1685fcf3ce44SJohn Forte } 1686fcf3ce44SJohn Forte text = value_end; 1687fcf3ce44SJohn Forte 1688fcf3ce44SJohn Forte } else if (iscsi_find_key_value("ErrorRecoveryLevel", 1689fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1690fcf3ce44SJohn Forte 1691fcf3ce44SJohn Forte if (strcmp(value, "0")) { 1692fcf3ce44SJohn Forte 1693fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1694fcf3ce44SJohn Forte "login failed - can't accept " 1695fcf3ce44SJohn Forte "ErrorRecoveryLevel %s", 1696fcf3ce44SJohn Forte icp->conn_oid, value); 1697fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1698fcf3ce44SJohn Forte } 1699fcf3ce44SJohn Forte text = value_end; 1700fcf3ce44SJohn Forte 1701fcf3ce44SJohn Forte } else { 1702fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1703fcf3ce44SJohn Forte "login failed - ignoring login " 1704fcf3ce44SJohn Forte "parameter %s", icp->conn_oid, value); 1705fcf3ce44SJohn Forte text = value_end; 1706fcf3ce44SJohn Forte } 1707fcf3ce44SJohn Forte break; 1708fcf3ce44SJohn Forte default: 1709fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1710fcf3ce44SJohn Forte } 1711fcf3ce44SJohn Forte } 1712fcf3ce44SJohn Forte 1713fcf3ce44SJohn Forte /* 1714fcf3ce44SJohn Forte * iSCSI RFC section 12.14 states that 1715fcf3ce44SJohn Forte * FirstBurstLength is Irrelevant if 1716fcf3ce44SJohn Forte * InitialR2T=Yes and ImmediateData=No. 1717fcf3ce44SJohn Forte * This is a final check to make sure 1718fcf3ce44SJohn Forte * the array didn't make a protocol 1719fcf3ce44SJohn Forte * violation. 1720fcf3ce44SJohn Forte */ 1721fcf3ce44SJohn Forte if ((fbl_irrelevant == B_TRUE) && 1722fcf3ce44SJohn Forte ((icp->conn_params.initial_r2t != B_TRUE) || 1723fcf3ce44SJohn Forte (icp->conn_params.immediate_data != B_FALSE))) { 1724fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1725fcf3ce44SJohn Forte "FirstBurstLength=Irrelevant and (InitialR2T!=Yes or " 1726fcf3ce44SJohn Forte "ImmediateData!=No) - protocol error", icp->conn_oid); 1727fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1728fcf3ce44SJohn Forte } 1729fcf3ce44SJohn Forte 1730fcf3ce44SJohn Forte if (icp->conn_current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE) { 1731fcf3ce44SJohn Forte switch (iscsiAuthClientRecvEnd(auth_client, iscsi_null_callback, 1732fcf3ce44SJohn Forte (void *)isp, NULL)) { 1733fcf3ce44SJohn Forte case iscsiAuthStatusContinue: 1734fcf3ce44SJohn Forte /* 1735fcf3ce44SJohn Forte * continue sending PDUs 1736fcf3ce44SJohn Forte */ 1737fcf3ce44SJohn Forte break; 1738fcf3ce44SJohn Forte 1739fcf3ce44SJohn Forte case iscsiAuthStatusPass: 1740fcf3ce44SJohn Forte break; 1741fcf3ce44SJohn Forte 1742fcf3ce44SJohn Forte case iscsiAuthStatusInProgress: 1743fcf3ce44SJohn Forte /* 1744fcf3ce44SJohn Forte * this should only occur if we were authenticating the 1745fcf3ce44SJohn Forte * target, which we don't do yet, so treat this as an 1746fcf3ce44SJohn Forte * error. 1747fcf3ce44SJohn Forte */ 1748fcf3ce44SJohn Forte case iscsiAuthStatusNoError: 1749fcf3ce44SJohn Forte /* 1750fcf3ce44SJohn Forte * treat this as an error, since we should get a 1751fcf3ce44SJohn Forte * different code 1752fcf3ce44SJohn Forte */ 1753fcf3ce44SJohn Forte case iscsiAuthStatusError: 1754fcf3ce44SJohn Forte case iscsiAuthStatusFail: 1755fcf3ce44SJohn Forte default: 1756fcf3ce44SJohn Forte debug_status = 0; 1757fcf3ce44SJohn Forte 1758fcf3ce44SJohn Forte if (iscsiAuthClientGetDebugStatus(auth_client, 1759fcf3ce44SJohn Forte &debug_status) != iscsiAuthStatusNoError) { 1760fcf3ce44SJohn Forte 1761fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1762fcf3ce44SJohn Forte "failed - authentication failed with " 1763fcf3ce44SJohn Forte "target (%s)", icp->conn_oid, 1764fcf3ce44SJohn Forte iscsiAuthClientDebugStatusToText( 1765fcf3ce44SJohn Forte debug_status)); 1766fcf3ce44SJohn Forte 1767fcf3ce44SJohn Forte } else { 1768fcf3ce44SJohn Forte 1769fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1770fcf3ce44SJohn Forte "failed - authentication failed with " 1771fcf3ce44SJohn Forte "target", icp->conn_oid); 1772fcf3ce44SJohn Forte 1773fcf3ce44SJohn Forte } 1774fcf3ce44SJohn Forte return (ISCSI_STATUS_AUTHENTICATION_FAILED); 1775fcf3ce44SJohn Forte } 1776fcf3ce44SJohn Forte } 1777fcf3ce44SJohn Forte 1778fcf3ce44SJohn Forte /* 1779fcf3ce44SJohn Forte * record some of the PDU fields for later use 1780fcf3ce44SJohn Forte */ 1781fcf3ce44SJohn Forte isp->sess_tsid = ntohs(ilrhp->tsid); 1782fcf3ce44SJohn Forte isp->sess_expcmdsn = ntohl(ilrhp->expcmdsn); 1783fcf3ce44SJohn Forte isp->sess_maxcmdsn = ntohl(ilrhp->maxcmdsn); 1784fcf3ce44SJohn Forte if (ilrhp->status_class == ISCSI_STATUS_CLASS_SUCCESS) { 1785fcf3ce44SJohn Forte icp->conn_expstatsn = ntohl(ilrhp->statsn) + 1; 1786fcf3ce44SJohn Forte } 1787fcf3ce44SJohn Forte 1788fcf3ce44SJohn Forte if (transit) { 1789fcf3ce44SJohn Forte /* 1790fcf3ce44SJohn Forte * advance to the next stage 1791fcf3ce44SJohn Forte */ 1792fcf3ce44SJohn Forte icp->conn_partial_response = 0; 1793fcf3ce44SJohn Forte icp->conn_current_stage = 1794fcf3ce44SJohn Forte ilrhp->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; 1795fcf3ce44SJohn Forte } else { 1796fcf3ce44SJohn Forte /* 1797fcf3ce44SJohn Forte * we got a partial response, don't advance, more 1798fcf3ce44SJohn Forte * negotiation to do 1799fcf3ce44SJohn Forte */ 1800fcf3ce44SJohn Forte icp->conn_partial_response = 1; 1801fcf3ce44SJohn Forte } 1802fcf3ce44SJohn Forte 1803fcf3ce44SJohn Forte /* 1804fcf3ce44SJohn Forte * this PDU is ok, though the login process 1805fcf3ce44SJohn Forte * may not be done yet 1806fcf3ce44SJohn Forte */ 1807fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 1808fcf3ce44SJohn Forte } 1809fcf3ce44SJohn Forte 1810fcf3ce44SJohn Forte /* 1811fcf3ce44SJohn Forte * iscsi_add_text - caller is assumed to be well-behaved and passing NUL 1812fcf3ce44SJohn Forte * terminated strings 1813fcf3ce44SJohn Forte */ 1814fcf3ce44SJohn Forte int 181530e7468fSPeter Dunlap iscsi_add_text(idm_pdu_t *text_pdu, int max_data_length, 1816fcf3ce44SJohn Forte char *param, char *value) 1817fcf3ce44SJohn Forte { 1818fcf3ce44SJohn Forte int param_len = 0; 1819fcf3ce44SJohn Forte int value_len = 0; 1820fcf3ce44SJohn Forte int length = 0; 1821fcf3ce44SJohn Forte int pdu_length = 0; 1822fcf3ce44SJohn Forte char *text = NULL; 1823fcf3ce44SJohn Forte char *end = NULL; 1824fcf3ce44SJohn Forte 182530e7468fSPeter Dunlap ASSERT(text_pdu != NULL); 1826fcf3ce44SJohn Forte ASSERT(param != NULL); 1827fcf3ce44SJohn Forte ASSERT(value != NULL); 1828fcf3ce44SJohn Forte 1829fcf3ce44SJohn Forte param_len = strlen(param); 1830fcf3ce44SJohn Forte value_len = strlen(value); 1831fcf3ce44SJohn Forte /* param, separator, value, and trailing NULL */ 1832fcf3ce44SJohn Forte length = param_len + 1 + value_len + 1; 183330e7468fSPeter Dunlap pdu_length = text_pdu->isp_datalen; 183430e7468fSPeter Dunlap text = (char *)text_pdu->isp_data + pdu_length; 183530e7468fSPeter Dunlap end = (char *)text_pdu->isp_data + max_data_length; 1836fcf3ce44SJohn Forte pdu_length += length; 1837fcf3ce44SJohn Forte 1838fcf3ce44SJohn Forte if (text + length >= end) { 1839fcf3ce44SJohn Forte return (0); 1840fcf3ce44SJohn Forte } 1841fcf3ce44SJohn Forte 1842fcf3ce44SJohn Forte /* param */ 1843fcf3ce44SJohn Forte (void) strncpy(text, param, param_len); 1844fcf3ce44SJohn Forte text += param_len; 1845fcf3ce44SJohn Forte 1846fcf3ce44SJohn Forte /* separator */ 1847fcf3ce44SJohn Forte *text++ = ISCSI_TEXT_SEPARATOR; 1848fcf3ce44SJohn Forte 1849fcf3ce44SJohn Forte /* value */ 1850fcf3ce44SJohn Forte (void) strncpy(text, value, value_len); 1851fcf3ce44SJohn Forte text += value_len; 1852fcf3ce44SJohn Forte 1853fcf3ce44SJohn Forte /* NULL */ 1854fcf3ce44SJohn Forte *text++ = '\0'; 1855fcf3ce44SJohn Forte 1856fcf3ce44SJohn Forte /* update the length in the PDU header */ 185730e7468fSPeter Dunlap text_pdu->isp_datalen = pdu_length; 185830e7468fSPeter Dunlap hton24(text_pdu->isp_hdr->dlength, pdu_length); 1859fcf3ce44SJohn Forte 1860fcf3ce44SJohn Forte return (1); 1861fcf3ce44SJohn Forte } 1862fcf3ce44SJohn Forte 1863fcf3ce44SJohn Forte /* 1864fcf3ce44SJohn Forte * iscsi_get_next_text - get the next line of text from the given data 1865fcf3ce44SJohn Forte * buffer. This function searches from the address given for the 1866fcf3ce44SJohn Forte * curr_text parameter. If curr_text_parameter is NULL return first 1867fcf3ce44SJohn Forte * line in buffer. The return value is the address of the next line 1868fcf3ce44SJohn Forte * based upon where curr_text is located. 1869fcf3ce44SJohn Forte * 1870fcf3ce44SJohn Forte */ 1871fcf3ce44SJohn Forte char * 1872fcf3ce44SJohn Forte iscsi_get_next_text(char *data, int max_data_length, char *curr_text) 1873fcf3ce44SJohn Forte { 1874fcf3ce44SJohn Forte char *curr_data; 1875fcf3ce44SJohn Forte 1876fcf3ce44SJohn Forte ASSERT(data != NULL); 1877fcf3ce44SJohn Forte 1878fcf3ce44SJohn Forte /* check if any data exists, if not return */ 1879fcf3ce44SJohn Forte if (max_data_length == 0) { 1880fcf3ce44SJohn Forte return (NULL); 1881fcf3ce44SJohn Forte } 1882fcf3ce44SJohn Forte 1883fcf3ce44SJohn Forte /* handle first call to this function */ 1884fcf3ce44SJohn Forte if (curr_text == NULL) { 1885fcf3ce44SJohn Forte return (data); 1886fcf3ce44SJohn Forte } 1887fcf3ce44SJohn Forte 1888fcf3ce44SJohn Forte /* move to next text string */ 1889fcf3ce44SJohn Forte curr_data = curr_text; 1890fcf3ce44SJohn Forte while ((curr_data < (data + max_data_length)) && *curr_data) { 1891fcf3ce44SJohn Forte curr_data++; 1892fcf3ce44SJohn Forte } 1893fcf3ce44SJohn Forte curr_data++; /* go past the NULL to the next entry */ 1894fcf3ce44SJohn Forte 1895fcf3ce44SJohn Forte /* check whether data end reached */ 1896fcf3ce44SJohn Forte if (curr_data >= (data + max_data_length)) { 1897fcf3ce44SJohn Forte return (NULL); 1898fcf3ce44SJohn Forte } 1899fcf3ce44SJohn Forte 1900fcf3ce44SJohn Forte return (curr_data); 1901fcf3ce44SJohn Forte } 1902fcf3ce44SJohn Forte 1903fcf3ce44SJohn Forte 1904fcf3ce44SJohn Forte /* 1905fcf3ce44SJohn Forte * iscsi_find_key_value - 1906fcf3ce44SJohn Forte * 1907fcf3ce44SJohn Forte */ 1908fcf3ce44SJohn Forte static int 1909fcf3ce44SJohn Forte iscsi_find_key_value(char *param, char *ihp, char *pdu_end, 1910fcf3ce44SJohn Forte char **value_start, char **value_end) 1911fcf3ce44SJohn Forte { 1912fcf3ce44SJohn Forte char *str = param; 1913fcf3ce44SJohn Forte char *text = ihp; 1914fcf3ce44SJohn Forte char *value = NULL; 1915fcf3ce44SJohn Forte 1916fcf3ce44SJohn Forte if (value_start) 1917fcf3ce44SJohn Forte *value_start = NULL; 1918fcf3ce44SJohn Forte if (value_end) 1919fcf3ce44SJohn Forte *value_end = NULL; 1920fcf3ce44SJohn Forte 1921fcf3ce44SJohn Forte /* 1922fcf3ce44SJohn Forte * make sure they contain the same bytes 1923fcf3ce44SJohn Forte */ 1924fcf3ce44SJohn Forte while (*str) { 1925fcf3ce44SJohn Forte if (text >= pdu_end) { 1926fcf3ce44SJohn Forte return (0); 1927fcf3ce44SJohn Forte } 1928fcf3ce44SJohn Forte if (*text == '\0') { 1929fcf3ce44SJohn Forte return (0); 1930fcf3ce44SJohn Forte } 1931fcf3ce44SJohn Forte if (*str != *text) { 1932fcf3ce44SJohn Forte return (0); 1933fcf3ce44SJohn Forte } 1934fcf3ce44SJohn Forte str++; 1935fcf3ce44SJohn Forte text++; 1936fcf3ce44SJohn Forte } 1937fcf3ce44SJohn Forte 1938fcf3ce44SJohn Forte if ((text >= pdu_end) || 1939fcf3ce44SJohn Forte (*text == '\0') || 1940fcf3ce44SJohn Forte (*text != ISCSI_TEXT_SEPARATOR)) { 1941fcf3ce44SJohn Forte return (0); 1942fcf3ce44SJohn Forte } 1943fcf3ce44SJohn Forte 1944fcf3ce44SJohn Forte /* 1945fcf3ce44SJohn Forte * find the value 1946fcf3ce44SJohn Forte */ 1947fcf3ce44SJohn Forte value = text + 1; 1948fcf3ce44SJohn Forte 1949fcf3ce44SJohn Forte /* 1950fcf3ce44SJohn Forte * find the end of the value 1951fcf3ce44SJohn Forte */ 1952fcf3ce44SJohn Forte while ((text < pdu_end) && (*text)) 1953fcf3ce44SJohn Forte text++; 1954fcf3ce44SJohn Forte 1955fcf3ce44SJohn Forte if (value_start) 1956fcf3ce44SJohn Forte *value_start = value; 1957fcf3ce44SJohn Forte if (value_end) 1958fcf3ce44SJohn Forte *value_end = text; 1959fcf3ce44SJohn Forte 1960fcf3ce44SJohn Forte return (1); 1961fcf3ce44SJohn Forte } 1962fcf3ce44SJohn Forte 1963fcf3ce44SJohn Forte 1964fcf3ce44SJohn Forte /* 1965fcf3ce44SJohn Forte * iscsi_update_address - This function is used on a login redirection. 1966fcf3ce44SJohn Forte * During the login redirection we are asked to switch to an IP address 1967fcf3ce44SJohn Forte * port different than the one we were logging into. 1968fcf3ce44SJohn Forte */ 1969fcf3ce44SJohn Forte static iscsi_status_t 1970fcf3ce44SJohn Forte iscsi_update_address(iscsi_conn_t *icp, char *in) 1971fcf3ce44SJohn Forte { 1972fcf3ce44SJohn Forte char *addr_str, *port_str, *tpgt_str; 1973fcf3ce44SJohn Forte int type; 1974fcf3ce44SJohn Forte struct hostent *hptr; 1975fcf3ce44SJohn Forte unsigned long tmp; 1976fcf3ce44SJohn Forte int error_num; 1977fcf3ce44SJohn Forte int port; 1978fcf3ce44SJohn Forte 1979fcf3ce44SJohn Forte ASSERT(icp != NULL); 1980fcf3ce44SJohn Forte ASSERT(in != NULL); 1981fcf3ce44SJohn Forte 1982fcf3ce44SJohn Forte /* parse login redirection response */ 1983fcf3ce44SJohn Forte if (parse_addr_port_tpgt(in, &addr_str, &type, 1984fcf3ce44SJohn Forte &port_str, &tpgt_str) == B_FALSE) { 1985fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1986fcf3ce44SJohn Forte } 1987fcf3ce44SJohn Forte 1988fcf3ce44SJohn Forte /* convert addr_str */ 1989fcf3ce44SJohn Forte hptr = kgetipnodebyname(addr_str, type, AI_ALL, &error_num); 1990fcf3ce44SJohn Forte if (!hptr) { 1991fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1992fcf3ce44SJohn Forte } 1993fcf3ce44SJohn Forte 1994fcf3ce44SJohn Forte /* convert port_str */ 1995fcf3ce44SJohn Forte if (port_str != NULL) { 1996fcf3ce44SJohn Forte (void) ddi_strtoul(port_str, NULL, 0, &tmp); 1997fcf3ce44SJohn Forte port = (int)tmp; 1998fcf3ce44SJohn Forte } else { 1999fcf3ce44SJohn Forte port = ISCSI_LISTEN_PORT; 2000fcf3ce44SJohn Forte } 2001fcf3ce44SJohn Forte 2002fcf3ce44SJohn Forte iscsid_addr_to_sockaddr(hptr->h_length, *hptr->h_addr_list, 2003fcf3ce44SJohn Forte port, &icp->conn_curr_addr.sin); 2004fcf3ce44SJohn Forte 2005fcf3ce44SJohn Forte kfreehostent(hptr); 2006fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 2007fcf3ce44SJohn Forte } 2008fcf3ce44SJohn Forte 200930e7468fSPeter Dunlap void 201030e7468fSPeter Dunlap iscsi_login_update_state(iscsi_conn_t *icp, iscsi_login_state_t next_state) 201130e7468fSPeter Dunlap { 201230e7468fSPeter Dunlap mutex_enter(&icp->conn_login_mutex); 201330e7468fSPeter Dunlap (void) iscsi_login_update_state_locked(icp, next_state); 201430e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex); 201530e7468fSPeter Dunlap } 201630e7468fSPeter Dunlap 201730e7468fSPeter Dunlap void 201830e7468fSPeter Dunlap iscsi_login_update_state_locked(iscsi_conn_t *icp, 201930e7468fSPeter Dunlap iscsi_login_state_t next_state) 202030e7468fSPeter Dunlap { 202130e7468fSPeter Dunlap ASSERT(mutex_owned(&icp->conn_login_mutex)); 202230e7468fSPeter Dunlap next_state = (next_state > LOGIN_MAX) ? LOGIN_MAX : next_state; 202330e7468fSPeter Dunlap idm_sm_audit_state_change(&icp->conn_state_audit, 202430e7468fSPeter Dunlap SAS_ISCSI_LOGIN, icp->conn_login_state, next_state); 202530e7468fSPeter Dunlap 202630e7468fSPeter Dunlap ISCSI_LOGIN_LOG(CE_NOTE, "iscsi_login_update_state conn %p %d -> %d", 202730e7468fSPeter Dunlap (void *)icp, icp->conn_login_state, next_state); 202830e7468fSPeter Dunlap 202930e7468fSPeter Dunlap icp->conn_login_state = next_state; 203030e7468fSPeter Dunlap cv_broadcast(&icp->conn_login_cv); 203130e7468fSPeter Dunlap } 203230e7468fSPeter Dunlap 203330e7468fSPeter Dunlap 2034fcf3ce44SJohn Forte 2035fcf3ce44SJohn Forte /* 2036fcf3ce44SJohn Forte * iscsi_null_callback - This callback may be used under certain 2037fcf3ce44SJohn Forte * conditions when authenticating a target, but I'm not sure what 2038fcf3ce44SJohn Forte * we need to do here. 2039fcf3ce44SJohn Forte */ 2040fcf3ce44SJohn Forte /* ARGSUSED */ 2041fcf3ce44SJohn Forte static void 2042fcf3ce44SJohn Forte iscsi_null_callback(void *user_handle, void *message_handle, int auth_status) 2043fcf3ce44SJohn Forte { 2044fcf3ce44SJohn Forte } 2045fcf3ce44SJohn Forte 2046fcf3ce44SJohn Forte 2047fcf3ce44SJohn Forte /* 2048fcf3ce44SJohn Forte * iscsi_login_failure_str - 2049fcf3ce44SJohn Forte * 2050fcf3ce44SJohn Forte */ 2051fcf3ce44SJohn Forte static char * 2052fcf3ce44SJohn Forte iscsi_login_failure_str(uchar_t status_class, uchar_t status_detail) 2053fcf3ce44SJohn Forte { 2054fcf3ce44SJohn Forte switch (status_class) { 2055fcf3ce44SJohn Forte case 0x00: 2056fcf3ce44SJohn Forte switch (status_detail) { 2057fcf3ce44SJohn Forte case 0x00: 2058fcf3ce44SJohn Forte return ("Login is proceeding okay."); 2059fcf3ce44SJohn Forte default: 2060fcf3ce44SJohn Forte break; 2061fcf3ce44SJohn Forte } 2062fcf3ce44SJohn Forte case 0x01: 2063fcf3ce44SJohn Forte switch (status_detail) { 2064fcf3ce44SJohn Forte case 0x01: 2065fcf3ce44SJohn Forte return ("Requested ITN has moved temporarily to " 2066fcf3ce44SJohn Forte "the address provided."); 2067fcf3ce44SJohn Forte case 0x02: 2068fcf3ce44SJohn Forte return ("Requested ITN has moved permanently to " 2069fcf3ce44SJohn Forte "the address provided."); 2070fcf3ce44SJohn Forte default: 2071fcf3ce44SJohn Forte break; 2072fcf3ce44SJohn Forte } 2073fcf3ce44SJohn Forte case 0x02: 2074fcf3ce44SJohn Forte switch (status_detail) { 2075fcf3ce44SJohn Forte case 0x00: 2076fcf3ce44SJohn Forte return ("Miscellaneous iSCSI initiator errors."); 2077fcf3ce44SJohn Forte case 0x01: 2078fcf3ce44SJohn Forte return ("Initiator could not be successfully " 2079fcf3ce44SJohn Forte "authenticated."); 2080fcf3ce44SJohn Forte case 0x02: 2081fcf3ce44SJohn Forte return ("Initiator is not allowed access to the " 2082fcf3ce44SJohn Forte "given target."); 2083fcf3ce44SJohn Forte case 0x03: 2084fcf3ce44SJohn Forte return ("Requested ITN does not exist at this " 2085fcf3ce44SJohn Forte "address."); 2086fcf3ce44SJohn Forte case 0x04: 2087fcf3ce44SJohn Forte return ("Requested ITN has been removed and no " 2088fcf3ce44SJohn Forte "forwarding address is provided."); 2089fcf3ce44SJohn Forte case 0x05: 2090fcf3ce44SJohn Forte return ("Requested iSCSI version range is not " 2091fcf3ce44SJohn Forte "supported by the target."); 2092fcf3ce44SJohn Forte case 0x06: 2093fcf3ce44SJohn Forte return ("No more connections can be accepted on " 2094fcf3ce44SJohn Forte "this Session ID (SSID)."); 2095fcf3ce44SJohn Forte case 0x07: 2096fcf3ce44SJohn Forte return ("Missing parameters (e.g., iSCSI initiator " 2097fcf3ce44SJohn Forte "and/or target name)."); 2098fcf3ce44SJohn Forte case 0x08: 2099fcf3ce44SJohn Forte return ("Target does not support session spanning " 2100fcf3ce44SJohn Forte "to this connection (address)."); 2101fcf3ce44SJohn Forte case 0x09: 2102fcf3ce44SJohn Forte return ("Target does not support this type of " 2103fcf3ce44SJohn Forte "session or not from this initiator."); 2104fcf3ce44SJohn Forte case 0x0A: 2105fcf3ce44SJohn Forte return ("Attempt to add a connection to a " 2106fcf3ce44SJohn Forte "nonexistent session."); 2107fcf3ce44SJohn Forte case 0x0B: 2108fcf3ce44SJohn Forte return ("Invalid request type during login."); 2109fcf3ce44SJohn Forte default: 2110fcf3ce44SJohn Forte break; 2111fcf3ce44SJohn Forte } 2112fcf3ce44SJohn Forte case 0x03: 2113fcf3ce44SJohn Forte switch (status_detail) { 2114fcf3ce44SJohn Forte case 0x00: 2115fcf3ce44SJohn Forte return ("Target hardware or software error."); 2116fcf3ce44SJohn Forte case 0x01: 2117fcf3ce44SJohn Forte return ("iSCSI service or target is not currently " 2118fcf3ce44SJohn Forte "operational."); 2119fcf3ce44SJohn Forte case 0x02: 2120fcf3ce44SJohn Forte return ("Target has insufficient session, connection " 2121fcf3ce44SJohn Forte "or other resources."); 2122fcf3ce44SJohn Forte default: 2123fcf3ce44SJohn Forte break; 2124fcf3ce44SJohn Forte } 2125fcf3ce44SJohn Forte } 2126fcf3ce44SJohn Forte return ("Unknown login response received."); 2127fcf3ce44SJohn Forte } 2128fcf3ce44SJohn Forte 2129fcf3ce44SJohn Forte 2130fcf3ce44SJohn Forte /* 2131fcf3ce44SJohn Forte * iscsi_login_connect - 2132fcf3ce44SJohn Forte */ 2133fcf3ce44SJohn Forte static iscsi_status_t 2134fcf3ce44SJohn Forte iscsi_login_connect(iscsi_conn_t *icp) 2135fcf3ce44SJohn Forte { 21360f1702c5SYu Xiangning iscsi_hba_t *ihp; 21370f1702c5SYu Xiangning iscsi_sess_t *isp; 21380f1702c5SYu Xiangning struct sockaddr *addr; 213930e7468fSPeter Dunlap idm_conn_req_t cr; 214030e7468fSPeter Dunlap idm_status_t rval; 2141d3d50737SRafael Vanoni clock_t lbolt; 2142fcf3ce44SJohn Forte 2143fcf3ce44SJohn Forte ASSERT(icp != NULL); 2144fcf3ce44SJohn Forte isp = icp->conn_sess; 2145fcf3ce44SJohn Forte ASSERT(isp != NULL); 2146fcf3ce44SJohn Forte ihp = isp->sess_hba; 2147fcf3ce44SJohn Forte ASSERT(ihp != NULL); 2148fcf3ce44SJohn Forte addr = &icp->conn_curr_addr.sin; 2149fcf3ce44SJohn Forte 215030e7468fSPeter Dunlap /* Make sure that scope_id is zero if it is an IPv6 address */ 215130e7468fSPeter Dunlap if (addr->sa_family == AF_INET6) { 215230e7468fSPeter Dunlap ((struct sockaddr_in6 *)addr)->sin6_scope_id = 0; 2153fcf3ce44SJohn Forte } 2154fcf3ce44SJohn Forte 215530e7468fSPeter Dunlap /* delay the connect process if required */ 215630e7468fSPeter Dunlap lbolt = ddi_get_lbolt(); 215730e7468fSPeter Dunlap if (lbolt < icp->conn_login_min) { 2158aff4bce5Syi zhang - Sun Microsystems - Beijing China if (icp->conn_login_max < icp->conn_login_min) { 2159aff4bce5Syi zhang - Sun Microsystems - Beijing China delay(icp->conn_login_max - lbolt); 2160aff4bce5Syi zhang - Sun Microsystems - Beijing China } else { 2161aff4bce5Syi zhang - Sun Microsystems - Beijing China delay(icp->conn_login_min - lbolt); 2162aff4bce5Syi zhang - Sun Microsystems - Beijing China } 2163fcf3ce44SJohn Forte } 2164fcf3ce44SJohn Forte 216530e7468fSPeter Dunlap /* Create IDM connection context */ 216630e7468fSPeter Dunlap cr.cr_domain = addr->sa_family; 216730e7468fSPeter Dunlap cr.cr_type = SOCK_STREAM; 216830e7468fSPeter Dunlap cr.cr_protocol = 0; 216930e7468fSPeter Dunlap cr.cr_bound = icp->conn_bound; 217030e7468fSPeter Dunlap cr.cr_li = icp->conn_sess->sess_hba->hba_li; 217130e7468fSPeter Dunlap cr.icr_conn_ops.icb_rx_misc = &iscsi_rx_misc_pdu; 217230e7468fSPeter Dunlap cr.icr_conn_ops.icb_rx_error = &iscsi_rx_error_pdu; 217330e7468fSPeter Dunlap cr.icr_conn_ops.icb_rx_scsi_rsp = &iscsi_rx_scsi_rsp; 217430e7468fSPeter Dunlap cr.icr_conn_ops.icb_client_notify = &iscsi_client_notify; 217530e7468fSPeter Dunlap cr.icr_conn_ops.icb_build_hdr = &iscsi_build_hdr; 217630e7468fSPeter Dunlap cr.icr_conn_ops.icb_task_aborted = &iscsi_task_aborted; 217730e7468fSPeter Dunlap bcopy(addr, &cr.cr_ini_dst_addr, 217830e7468fSPeter Dunlap sizeof (cr.cr_ini_dst_addr)); 217930e7468fSPeter Dunlap bcopy(&icp->conn_bound_addr, &cr.cr_bound_addr, 218030e7468fSPeter Dunlap sizeof (cr.cr_bound_addr)); 2181dedec472SJack Meng if (isp->sess_boot == B_TRUE) { 2182dedec472SJack Meng cr.cr_boot_conn = B_TRUE; 2183dedec472SJack Meng } else { 2184dedec472SJack Meng cr.cr_boot_conn = B_FALSE; 2185dedec472SJack Meng } 218630e7468fSPeter Dunlap 218730e7468fSPeter Dunlap /* 218830e7468fSPeter Dunlap * Allocate IDM connection context 218930e7468fSPeter Dunlap */ 219030e7468fSPeter Dunlap rval = idm_ini_conn_create(&cr, &icp->conn_ic); 219130e7468fSPeter Dunlap if (rval != IDM_STATUS_SUCCESS) { 219230e7468fSPeter Dunlap return (ISCSI_STATUS_LOGIN_FAILED); 2193fcf3ce44SJohn Forte } 2194fcf3ce44SJohn Forte 219530e7468fSPeter Dunlap icp->conn_ic->ic_handle = icp; 219630e7468fSPeter Dunlap 219730e7468fSPeter Dunlap /* 219830e7468fSPeter Dunlap * About to initiate connect, reset login state. 219930e7468fSPeter Dunlap */ 220030e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_START); 220130e7468fSPeter Dunlap 220230e7468fSPeter Dunlap /* 220330e7468fSPeter Dunlap * Make sure the connection doesn't go away until we are done with it. 220430e7468fSPeter Dunlap * This hold will prevent us from receiving a CN_CONNECT_DESTROY 220530e7468fSPeter Dunlap * notification on this connection until we are ready. 220630e7468fSPeter Dunlap */ 220730e7468fSPeter Dunlap idm_conn_hold(icp->conn_ic); 220830e7468fSPeter Dunlap 2209aff4bce5Syi zhang - Sun Microsystems - Beijing China /* 2210aff4bce5Syi zhang - Sun Microsystems - Beijing China * When iSCSI initiator to target IO timeout or connection failure 2211aff4bce5Syi zhang - Sun Microsystems - Beijing China * Connection retry is needed for normal operational session. 2212aff4bce5Syi zhang - Sun Microsystems - Beijing China */ 2213aff4bce5Syi zhang - Sun Microsystems - Beijing China if ((icp->conn_sess->sess_type == ISCSI_SESS_TYPE_NORMAL) && 2214aff4bce5Syi zhang - Sun Microsystems - Beijing China ((icp->conn_state == ISCSI_CONN_STATE_FAILED) || 2215aff4bce5Syi zhang - Sun Microsystems - Beijing China (icp->conn_state == ISCSI_CONN_STATE_POLLING))) { 2216aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.nonblock_socket = B_TRUE; 2217aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_max = 2218aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_login_max; 2219aff4bce5Syi zhang - Sun Microsystems - Beijing China if (icp->conn_state == ISCSI_CONN_STATE_POLLING) { 2220aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_interval = 2221aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_tunable_params.polling_login_delay; 2222aff4bce5Syi zhang - Sun Microsystems - Beijing China } else { 2223aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_interval = 2224aff4bce5Syi zhang - Sun Microsystems - Beijing China ISCSI_LOGIN_RETRY_DELAY; 2225aff4bce5Syi zhang - Sun Microsystems - Beijing China } 2226aff4bce5Syi zhang - Sun Microsystems - Beijing China 2227aff4bce5Syi zhang - Sun Microsystems - Beijing China } else { 2228aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.nonblock_socket = B_FALSE; 2229aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_max = 0; 2230aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_interval = 0; 2231aff4bce5Syi zhang - Sun Microsystems - Beijing China } 223230e7468fSPeter Dunlap /* 223330e7468fSPeter Dunlap * Attempt connection. Upon return we will either be ready to 223430e7468fSPeter Dunlap * login or disconnected. If idm_ini_conn_connect fails we 223530e7468fSPeter Dunlap * will eventually receive a CN_CONNECT_DESTROY at which point 223630e7468fSPeter Dunlap * we will destroy the connection allocated above (so there 223730e7468fSPeter Dunlap * is no need to explicitly free it here). 223830e7468fSPeter Dunlap */ 223930e7468fSPeter Dunlap rval = idm_ini_conn_connect(icp->conn_ic); 2240fcf3ce44SJohn Forte 224130e7468fSPeter Dunlap if (rval != IDM_STATUS_SUCCESS) { 2242fcf3ce44SJohn Forte cmn_err(CE_NOTE, "iscsi connection(%u) unable to " 2243fcf3ce44SJohn Forte "connect to target %s", icp->conn_oid, 2244fcf3ce44SJohn Forte icp->conn_sess->sess_name); 224530e7468fSPeter Dunlap idm_conn_rele(icp->conn_ic); 224630e7468fSPeter Dunlap } 2247fcf3ce44SJohn Forte 224830e7468fSPeter Dunlap return (rval == IDM_STATUS_SUCCESS ? 224930e7468fSPeter Dunlap ISCSI_STATUS_SUCCESS : ISCSI_STATUS_INTERNAL_ERROR); 225030e7468fSPeter Dunlap } 225130e7468fSPeter Dunlap 225230e7468fSPeter Dunlap /* 225330e7468fSPeter Dunlap * iscsi_login_disconnect 225430e7468fSPeter Dunlap */ 225530e7468fSPeter Dunlap static void 225630e7468fSPeter Dunlap iscsi_login_disconnect(iscsi_conn_t *icp) 225730e7468fSPeter Dunlap { 225830e7468fSPeter Dunlap /* Tell IDM to disconnect is if we are not already disconnect */ 225930e7468fSPeter Dunlap idm_ini_conn_disconnect_sync(icp->conn_ic); 226030e7468fSPeter Dunlap 226130e7468fSPeter Dunlap /* 226230e7468fSPeter Dunlap * The function above may return before the CN_CONNECT_LOST 226330e7468fSPeter Dunlap * notification. Wait for it. 226430e7468fSPeter Dunlap */ 226530e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 226630e7468fSPeter Dunlap while (icp->conn_state_idm_connected) 226730e7468fSPeter Dunlap cv_wait(&icp->conn_state_change, 226830e7468fSPeter Dunlap &icp->conn_state_mutex); 226930e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 227030e7468fSPeter Dunlap } 227130e7468fSPeter Dunlap 227230e7468fSPeter Dunlap /* 227330e7468fSPeter Dunlap * iscsi_notice_key_values - Create an nvlist containing the values 227430e7468fSPeter Dunlap * that have been negotiated for this connection and pass them down to 227530e7468fSPeter Dunlap * IDM so it can pick up any values that are important. 227630e7468fSPeter Dunlap */ 227730e7468fSPeter Dunlap static void 227830e7468fSPeter Dunlap iscsi_notice_key_values(iscsi_conn_t *icp) 227930e7468fSPeter Dunlap { 228030e7468fSPeter Dunlap nvlist_t *neg_nvl; 228130e7468fSPeter Dunlap int rc; 228230e7468fSPeter Dunlap 228330e7468fSPeter Dunlap rc = nvlist_alloc(&neg_nvl, NV_UNIQUE_NAME, KM_SLEEP); 228430e7468fSPeter Dunlap ASSERT(rc == 0); 228530e7468fSPeter Dunlap 228630e7468fSPeter Dunlap /* Only crc32c is supported so the digest logic is simple */ 228730e7468fSPeter Dunlap if (icp->conn_params.header_digest) { 228830e7468fSPeter Dunlap rc = nvlist_add_string(neg_nvl, "HeaderDigest", "crc32c"); 228930e7468fSPeter Dunlap } else { 229030e7468fSPeter Dunlap rc = nvlist_add_string(neg_nvl, "HeaderDigest", "none"); 2291fcf3ce44SJohn Forte } 229230e7468fSPeter Dunlap ASSERT(rc == 0); 2293fcf3ce44SJohn Forte 229430e7468fSPeter Dunlap if (icp->conn_params.data_digest) { 229530e7468fSPeter Dunlap rc = nvlist_add_string(neg_nvl, "DataDigest", "crc32c"); 229630e7468fSPeter Dunlap } else { 229730e7468fSPeter Dunlap rc = nvlist_add_string(neg_nvl, "DataDigest", "none"); 2298fcf3ce44SJohn Forte } 229930e7468fSPeter Dunlap ASSERT(rc == 0); 2300fcf3ce44SJohn Forte 230130e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "MaxRecvDataSegmentLength", 230230e7468fSPeter Dunlap (uint64_t)icp->conn_params.max_recv_data_seg_len); 230330e7468fSPeter Dunlap ASSERT(rc == 0); 230430e7468fSPeter Dunlap 230530e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "MaxBurstLength", 230630e7468fSPeter Dunlap (uint64_t)icp->conn_params.max_burst_length); 230730e7468fSPeter Dunlap ASSERT(rc == 0); 230830e7468fSPeter Dunlap 230930e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "MaxOutstandingR2T", 231030e7468fSPeter Dunlap (uint64_t)icp->conn_params.max_outstanding_r2t); 231130e7468fSPeter Dunlap ASSERT(rc == 0); 231230e7468fSPeter Dunlap 231330e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "ErrorRecoveryLevel", 231430e7468fSPeter Dunlap (uint64_t)icp->conn_params.error_recovery_level); 231530e7468fSPeter Dunlap ASSERT(rc == 0); 231630e7468fSPeter Dunlap 231730e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "DefaultTime2Wait", 231830e7468fSPeter Dunlap (uint64_t)icp->conn_params.default_time_to_wait); 231930e7468fSPeter Dunlap ASSERT(rc == 0); 232030e7468fSPeter Dunlap 232130e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "DefaultTime2Retain", 232230e7468fSPeter Dunlap (uint64_t)icp->conn_params.default_time_to_retain); 232330e7468fSPeter Dunlap ASSERT(rc == 0); 232430e7468fSPeter Dunlap 232530e7468fSPeter Dunlap /* Pass the list to IDM to examine, then free it */ 232630e7468fSPeter Dunlap idm_notice_key_values(icp->conn_ic, neg_nvl); 232730e7468fSPeter Dunlap nvlist_free(neg_nvl); 2328fcf3ce44SJohn Forte } 2329