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. 23904e51f6SJack 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 { 237904e51f6SJack 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; 257904e51f6SJack 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); 28030e7468fSPeter Dunlap 28130e7468fSPeter Dunlap /* Notify the session that a connection is logged in */ 282904e51f6SJack Meng event_count = atomic_inc_32_nv(&isp->sess_state_event_count); 283904e51f6SJack Meng iscsi_sess_enter_state_zone(isp); 284904e51f6SJack Meng iscsi_sess_state_machine(isp, ISCSI_SESS_EVENT_N1, event_count); 285904e51f6SJack Meng iscsi_sess_exit_state_zone(isp); 28630e7468fSPeter Dunlap } else { 28730e7468fSPeter Dunlap /* If login failed reset nego tpgt */ 28830e7468fSPeter Dunlap isp->sess_tpgt_nego = ISCSI_DEFAULT_TPGT; 28930e7468fSPeter Dunlap 290fcf3ce44SJohn Forte 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 } 306fcf3ce44SJohn Forte mutex_exit(&icp->conn_state_mutex); 307904e51f6SJack Meng event_count = atomic_inc_32_nv( 308904e51f6SJack Meng &isp->sess_state_event_count); 309904e51f6SJack Meng iscsi_sess_enter_state_zone(isp); 310904e51f6SJack Meng iscsi_sess_state_machine(isp, ISCSI_SESS_EVENT_N6, 311904e51f6SJack Meng event_count); 312904e51f6SJack 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); 323904e51f6SJack Meng event_count = atomic_inc_32_nv( 324904e51f6SJack Meng &isp->sess_state_event_count); 325904e51f6SJack Meng iscsi_sess_enter_state_zone(isp); 32630e7468fSPeter Dunlap 32730e7468fSPeter Dunlap iscsi_sess_state_machine(isp, 328904e51f6SJack Meng ISCSI_SESS_EVENT_N6, event_count); 329904e51f6SJack Meng 330904e51f6SJack 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 510*6e7514aeSPeter Gill icp->conn_login_resp_hdr.opcode = 0; 51130e7468fSPeter Dunlap iscsi_login_update_state_locked(icp, LOGIN_TX); 51230e7468fSPeter Dunlap icp->conn_login_data = data; 51330e7468fSPeter Dunlap icp->conn_login_max_data_length = max_data_length; 514fcf3ce44SJohn Forte 51530e7468fSPeter Dunlap /* 51630e7468fSPeter Dunlap * send a PDU to the target. This is asynchronous but 51730e7468fSPeter Dunlap * we don't have any particular need for a TX completion 51830e7468fSPeter Dunlap * notification since we are going to block waiting for the 51930e7468fSPeter Dunlap * receive. 52030e7468fSPeter Dunlap */ 52130e7468fSPeter Dunlap response_timeout = ddi_get_lbolt() + 522aff4bce5Syi zhang - Sun Microsystems - Beijing China SEC_TO_TICK(icp->conn_tunable_params. 523aff4bce5Syi zhang - Sun Microsystems - Beijing China recv_login_rsp_timeout); 52430e7468fSPeter Dunlap idm_pdu_tx(text_pdu); 52530e7468fSPeter Dunlap 52630e7468fSPeter Dunlap /* 52730e7468fSPeter Dunlap * Wait for login failure indication or login RX. 52830e7468fSPeter Dunlap * Handler for login response PDU will copy any data into 52930e7468fSPeter Dunlap * the buffer pointed to by icp->conn_login_data 53030e7468fSPeter Dunlap */ 53130e7468fSPeter Dunlap while (icp->conn_login_state == LOGIN_TX) { 53230e7468fSPeter Dunlap timeout_result = cv_timedwait(&icp->conn_login_cv, 53330e7468fSPeter Dunlap &icp->conn_login_mutex, response_timeout); 53430e7468fSPeter Dunlap if (timeout_result == -1) 53530e7468fSPeter Dunlap break; 53630e7468fSPeter Dunlap } 53730e7468fSPeter Dunlap 538*6e7514aeSPeter Gill /* 539*6e7514aeSPeter Gill * We have either received a login response or the connection 540*6e7514aeSPeter Gill * has gone down or both. If a login response is present, 541*6e7514aeSPeter Gill * then process it. 542*6e7514aeSPeter Gill */ 543*6e7514aeSPeter Gill ilrhp = (iscsi_login_rsp_hdr_t *)&icp->conn_login_resp_hdr; 544*6e7514aeSPeter Gill if (icp->conn_login_state != LOGIN_RX && ilrhp->opcode == 0) { 545*6e7514aeSPeter Gill /* connection down, with no login response */ 54630e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex); 54730e7468fSPeter Dunlap rval = (ISCSI_STATUS_INTERNAL_ERROR); 548fcf3ce44SJohn Forte goto iscsi_login_done; 549fcf3ce44SJohn Forte } 55030e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex); 551fcf3ce44SJohn Forte 552fcf3ce44SJohn Forte /* check the PDU response type */ 55330e7468fSPeter Dunlap if (ilrhp->opcode != ISCSI_OP_LOGIN_RSP) { 554fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 555fcf3ce44SJohn Forte "received invalid login response (0x%02x)", 55630e7468fSPeter Dunlap icp->conn_oid, ilrhp->opcode); 557fcf3ce44SJohn Forte rval = (ISCSI_STATUS_PROTOCOL_ERROR); 558fcf3ce44SJohn Forte goto iscsi_login_done; 559fcf3ce44SJohn Forte } 560fcf3ce44SJohn Forte 561fcf3ce44SJohn Forte /* 562fcf3ce44SJohn Forte * give the caller the status class and detail from the 563fcf3ce44SJohn Forte * last login response PDU received 564fcf3ce44SJohn Forte */ 565fcf3ce44SJohn Forte if (status_class) { 566fcf3ce44SJohn Forte *status_class = ilrhp->status_class; 567fcf3ce44SJohn Forte } 568fcf3ce44SJohn Forte if (status_detail) { 569fcf3ce44SJohn Forte *status_detail = ilrhp->status_detail; 570fcf3ce44SJohn Forte } 571fcf3ce44SJohn Forte 572fcf3ce44SJohn Forte switch (ilrhp->status_class) { 573fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_SUCCESS: 574fcf3ce44SJohn Forte /* 575fcf3ce44SJohn Forte * process this response and possibly continue 576fcf3ce44SJohn Forte * sending PDUs 577fcf3ce44SJohn Forte */ 578fcf3ce44SJohn Forte rval = iscsi_process_login_response(icp, 57930e7468fSPeter Dunlap ilrhp, (char *)icp->conn_login_data, 58030e7468fSPeter Dunlap icp->conn_login_max_data_length); 581fcf3ce44SJohn Forte /* pass back whatever error we discovered */ 582fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(rval)) { 58319944f88Syi zhang - Sun Microsystems - Beijing China if (ISCSI_LOGIN_TRANSIT_FFP(ilrhp->flags)) { 58419944f88Syi zhang - Sun Microsystems - Beijing China /* 58519944f88Syi zhang - Sun Microsystems - Beijing China * iSCSI connection transit to next 58619944f88Syi zhang - Sun Microsystems - Beijing China * FFP stage while iscsi params 58719944f88Syi zhang - Sun Microsystems - Beijing China * ngeotiate error, LOGIN_ERROR 58819944f88Syi zhang - Sun Microsystems - Beijing China * marked so CN_FFP_ENABLED can 58919944f88Syi zhang - Sun Microsystems - Beijing China * be fully handled before 59019944f88Syi zhang - Sun Microsystems - Beijing China * CN_FFP_DISABLED can be processed. 59119944f88Syi zhang - Sun Microsystems - Beijing China */ 59219944f88Syi zhang - Sun Microsystems - Beijing China iscsi_login_update_state(icp, 59319944f88Syi zhang - Sun Microsystems - Beijing China LOGIN_ERROR); 59419944f88Syi zhang - Sun Microsystems - Beijing China } 595fcf3ce44SJohn Forte goto iscsi_login_done; 596fcf3ce44SJohn Forte } 597fcf3ce44SJohn Forte 598fcf3ce44SJohn Forte break; 599fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_REDIRECT: 600fcf3ce44SJohn Forte /* 601fcf3ce44SJohn Forte * we need to process this response to get the 602fcf3ce44SJohn Forte * TargetAddress of the redirect, but we don't 603fcf3ce44SJohn Forte * care about the return code. 604fcf3ce44SJohn Forte */ 60530e7468fSPeter Dunlap (void) iscsi_process_login_response(icp, 60630e7468fSPeter Dunlap ilrhp, (char *)icp->conn_login_data, 60730e7468fSPeter Dunlap icp->conn_login_max_data_length); 608fcf3ce44SJohn Forte rval = ISCSI_STATUS_SUCCESS; 609fcf3ce44SJohn Forte goto iscsi_login_done; 610fcf3ce44SJohn Forte case ISCSI_STATUS_CLASS_INITIATOR_ERR: 611fcf3ce44SJohn Forte if (ilrhp->status_detail == 612fcf3ce44SJohn Forte ISCSI_LOGIN_STATUS_AUTH_FAILED) { 613fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 614fcf3ce44SJohn Forte "failed - login failed to authenticate " 615fcf3ce44SJohn Forte "with target", icp->conn_oid); 616fcf3ce44SJohn Forte } 617fcf3ce44SJohn Forte rval = ISCSI_STATUS_SUCCESS; 618fcf3ce44SJohn Forte goto iscsi_login_done; 619fcf3ce44SJohn Forte default: 620fcf3ce44SJohn Forte /* 621fcf3ce44SJohn Forte * some sort of error, login terminated unsuccessfully, 622fcf3ce44SJohn Forte * though this function did it's job. the caller must 623fcf3ce44SJohn Forte * check the status_class and status_detail and decide 624fcf3ce44SJohn Forte * what to do next. 625fcf3ce44SJohn Forte */ 626fcf3ce44SJohn Forte rval = ISCSI_STATUS_SUCCESS; 627fcf3ce44SJohn Forte goto iscsi_login_done; 628fcf3ce44SJohn Forte } 629fcf3ce44SJohn Forte 630fcf3ce44SJohn Forte } while (icp->conn_current_stage != ISCSI_FULL_FEATURE_PHASE); 631fcf3ce44SJohn Forte 632fcf3ce44SJohn Forte rval = ISCSI_STATUS_SUCCESS; 633fcf3ce44SJohn Forte 634fcf3ce44SJohn Forte iscsi_login_done: 635fcf3ce44SJohn Forte if (auth_client) { 636fcf3ce44SJohn Forte if (iscsiAuthClientFinish(auth_client) != 637fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 638fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 639fcf3ce44SJohn Forte "failed - login failed to authenticate " 640fcf3ce44SJohn Forte "with target", icp->conn_oid); 641fcf3ce44SJohn Forte if (ISCSI_SUCCESS(rval)) 642fcf3ce44SJohn Forte rval = ISCSI_STATUS_INTERNAL_ERROR; 643fcf3ce44SJohn Forte } 644fcf3ce44SJohn Forte } 64530e7468fSPeter Dunlap 646cc7ef495Syi zhang - Sun Microsystems - Beijing China icp->conn_login_status = rval; 64730e7468fSPeter Dunlap if (ISCSI_SUCCESS(rval) && 64830e7468fSPeter Dunlap (*status_class == ISCSI_STATUS_CLASS_SUCCESS)) { 64930e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 65030e7468fSPeter Dunlap while (!icp->conn_state_ffp) 65130e7468fSPeter Dunlap cv_wait(&icp->conn_state_change, 65230e7468fSPeter Dunlap &icp->conn_state_mutex); 65330e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 65430e7468fSPeter Dunlap } else { 65530e7468fSPeter Dunlap iscsi_login_disconnect(icp); 65630e7468fSPeter Dunlap } 65730e7468fSPeter Dunlap 65830e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_DONE); 65930e7468fSPeter Dunlap 660fcf3ce44SJohn Forte return (rval); 661fcf3ce44SJohn Forte } 662fcf3ce44SJohn Forte 663fcf3ce44SJohn Forte 664fcf3ce44SJohn Forte /* 665fcf3ce44SJohn Forte * iscsi_make_login_pdu - 666fcf3ce44SJohn Forte * 667fcf3ce44SJohn Forte */ 668fcf3ce44SJohn Forte static iscsi_status_t 66930e7468fSPeter Dunlap iscsi_make_login_pdu(iscsi_conn_t *icp, idm_pdu_t *text_pdu, 670fcf3ce44SJohn Forte char *data, int max_data_length) 671fcf3ce44SJohn Forte { 672fcf3ce44SJohn Forte struct iscsi_sess *isp = NULL; 673fcf3ce44SJohn Forte int transit = 0; 67430e7468fSPeter Dunlap iscsi_hdr_t *ihp = text_pdu->isp_hdr; 67530e7468fSPeter Dunlap iscsi_login_hdr_t *ilhp = 67630e7468fSPeter Dunlap (iscsi_login_hdr_t *)text_pdu->isp_hdr; 677fcf3ce44SJohn Forte IscsiAuthClient *auth_client = NULL; 678fcf3ce44SJohn Forte int keytype = 0; 679fcf3ce44SJohn Forte int rc = 0; 680fcf3ce44SJohn Forte char value[iscsiAuthStringMaxLength]; 681fcf3ce44SJohn Forte 682fcf3ce44SJohn Forte ASSERT(icp != NULL); 68330e7468fSPeter Dunlap ASSERT(text_pdu != NULL); 684fcf3ce44SJohn Forte isp = icp->conn_sess; 685fcf3ce44SJohn Forte ASSERT(isp != NULL); 686fcf3ce44SJohn Forte 687fcf3ce44SJohn Forte auth_client = 688fcf3ce44SJohn Forte (isp->sess_auth.auth_buffers && isp->sess_auth.num_auth_buffers) ? 689fcf3ce44SJohn Forte (IscsiAuthClient *)isp->sess_auth.auth_buffers[0].address : NULL; 690fcf3ce44SJohn Forte 691fcf3ce44SJohn Forte /* 692fcf3ce44SJohn Forte * initialize the PDU header 693fcf3ce44SJohn Forte */ 694fcf3ce44SJohn Forte bzero(ilhp, sizeof (*ilhp)); 695fcf3ce44SJohn Forte ilhp->opcode = ISCSI_OP_LOGIN_CMD | ISCSI_OP_IMMEDIATE; 696fcf3ce44SJohn Forte ilhp->cid = icp->conn_cid; 697fcf3ce44SJohn Forte bcopy(&isp->sess_isid[0], &ilhp->isid[0], sizeof (isp->sess_isid)); 698fcf3ce44SJohn Forte ilhp->tsid = 0; 699fcf3ce44SJohn Forte 70030e7468fSPeter Dunlap /* 70130e7468fSPeter Dunlap * Set data buffer pointer. The calls to iscsi_add_text will update the 70230e7468fSPeter Dunlap * data length. 70330e7468fSPeter Dunlap */ 70430e7468fSPeter Dunlap text_pdu->isp_data = (uint8_t *)data; 70530e7468fSPeter Dunlap 706fcf3ce44SJohn Forte /* don't increment on immediate */ 707fcf3ce44SJohn Forte ilhp->cmdsn = htonl(isp->sess_cmdsn); 708fcf3ce44SJohn Forte 709fcf3ce44SJohn Forte ilhp->min_version = ISCSI_DRAFT20_VERSION; 710fcf3ce44SJohn Forte ilhp->max_version = ISCSI_DRAFT20_VERSION; 711fcf3ce44SJohn Forte 712fcf3ce44SJohn Forte /* 713fcf3ce44SJohn Forte * we have to send 0 until full-feature stage 714fcf3ce44SJohn Forte */ 715fcf3ce44SJohn Forte ilhp->expstatsn = htonl(icp->conn_expstatsn); 716fcf3ce44SJohn Forte 717fcf3ce44SJohn Forte /* 718fcf3ce44SJohn Forte * the very first Login PDU has some additional requirements, 719fcf3ce44SJohn Forte * * and we need to decide what stage to start in. 720fcf3ce44SJohn Forte */ 721fcf3ce44SJohn Forte if (icp->conn_current_stage == ISCSI_INITIAL_LOGIN_STAGE) { 722fcf3ce44SJohn Forte if ((isp->sess_hba->hba_name) && 723fcf3ce44SJohn Forte (isp->sess_hba->hba_name[0])) { 72430e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 725fcf3ce44SJohn Forte "InitiatorName", 726fcf3ce44SJohn Forte (char *)isp->sess_hba->hba_name)) { 727fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 728fcf3ce44SJohn Forte } 729fcf3ce44SJohn Forte } else { 730fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 731fcf3ce44SJohn Forte "failed - initiator name is required", 732fcf3ce44SJohn Forte icp->conn_oid); 733fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 734fcf3ce44SJohn Forte } 735fcf3ce44SJohn Forte 736fcf3ce44SJohn Forte if ((isp->sess_hba->hba_alias) && 737fcf3ce44SJohn Forte (isp->sess_hba->hba_alias[0])) { 73830e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 739fcf3ce44SJohn Forte "InitiatorAlias", 740fcf3ce44SJohn Forte (char *)isp->sess_hba->hba_alias)) { 741fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 742fcf3ce44SJohn Forte } 743fcf3ce44SJohn Forte } 744fcf3ce44SJohn Forte 745fcf3ce44SJohn Forte if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 746fcf3ce44SJohn Forte if (isp->sess_name[0] != '\0') { 74730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 748fcf3ce44SJohn Forte "TargetName", (char *)isp->sess_name)) { 749fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 750fcf3ce44SJohn Forte } 751fcf3ce44SJohn Forte } 752fcf3ce44SJohn Forte 75330e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 754fcf3ce44SJohn Forte "SessionType", "Normal")) { 755fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 756fcf3ce44SJohn Forte } 757fcf3ce44SJohn Forte } else if (isp->sess_type == ISCSI_SESS_TYPE_DISCOVERY) { 75830e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 759fcf3ce44SJohn Forte "SessionType", "Discovery")) { 760fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 761fcf3ce44SJohn Forte } 762fcf3ce44SJohn Forte } else { 763fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 764fcf3ce44SJohn Forte } 765fcf3ce44SJohn Forte 766fcf3ce44SJohn Forte if (auth_client) { 767fcf3ce44SJohn Forte /* we're prepared to do authentication */ 768fcf3ce44SJohn Forte icp->conn_current_stage = 769fcf3ce44SJohn Forte ISCSI_SECURITY_NEGOTIATION_STAGE; 770fcf3ce44SJohn Forte } else { 771fcf3ce44SJohn Forte /* can't do any authentication, skip that stage */ 772fcf3ce44SJohn Forte icp->conn_current_stage = 773fcf3ce44SJohn Forte ISCSI_OP_PARMS_NEGOTIATION_STAGE; 774fcf3ce44SJohn Forte } 775fcf3ce44SJohn Forte } 776fcf3ce44SJohn Forte 777fcf3ce44SJohn Forte /* 778fcf3ce44SJohn Forte * fill in text based on the stage 779fcf3ce44SJohn Forte */ 780fcf3ce44SJohn Forte switch (icp->conn_current_stage) { 781fcf3ce44SJohn Forte case ISCSI_OP_PARMS_NEGOTIATION_STAGE: 782fcf3ce44SJohn Forte /* 783fcf3ce44SJohn Forte * we always try to go from op params to full 784fcf3ce44SJohn Forte * feature stage 785fcf3ce44SJohn Forte */ 786fcf3ce44SJohn Forte icp->conn_next_stage = ISCSI_FULL_FEATURE_PHASE; 787fcf3ce44SJohn Forte transit = 1; 788fcf3ce44SJohn Forte 789fcf3ce44SJohn Forte /* 790fcf3ce44SJohn Forte * The terminology here may have gotten dated. A partial 791fcf3ce44SJohn Forte * response is a login response that doesn't complete a 792fcf3ce44SJohn Forte * login. If we haven't gotten a partial response, then 793fcf3ce44SJohn Forte * either we shouldn't be here, or we just switched to 794fcf3ce44SJohn Forte * this stage, and need to start offering keys. 795fcf3ce44SJohn Forte */ 796fcf3ce44SJohn Forte if (!icp->conn_partial_response) { 797fcf3ce44SJohn Forte /* 798fcf3ce44SJohn Forte * request the desired settings the first time 799fcf3ce44SJohn Forte * we are in this stage 800fcf3ce44SJohn Forte */ 801fcf3ce44SJohn Forte switch (icp->conn_params.header_digest) { 802fcf3ce44SJohn Forte case ISCSI_DIGEST_NONE: 80330e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 804fcf3ce44SJohn Forte max_data_length, "HeaderDigest", "None")) { 805fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 806fcf3ce44SJohn Forte } 807fcf3ce44SJohn Forte break; 808fcf3ce44SJohn Forte case ISCSI_DIGEST_CRC32C: 80930e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 810fcf3ce44SJohn Forte max_data_length, 811fcf3ce44SJohn Forte "HeaderDigest", "CRC32C")) { 812fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 813fcf3ce44SJohn Forte } 814fcf3ce44SJohn Forte break; 815fcf3ce44SJohn Forte case ISCSI_DIGEST_CRC32C_NONE: 81630e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 817fcf3ce44SJohn Forte max_data_length, "HeaderDigest", 818fcf3ce44SJohn Forte "CRC32C,None")) { 819fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 820fcf3ce44SJohn Forte } 821fcf3ce44SJohn Forte break; 822fcf3ce44SJohn Forte default: 823fcf3ce44SJohn Forte case ISCSI_DIGEST_NONE_CRC32C: 82430e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 825fcf3ce44SJohn Forte max_data_length, "HeaderDigest", 826fcf3ce44SJohn Forte "None,CRC32C")) { 827fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 828fcf3ce44SJohn Forte } 829fcf3ce44SJohn Forte break; 830fcf3ce44SJohn Forte } 831fcf3ce44SJohn Forte 832fcf3ce44SJohn Forte switch (icp->conn_params.data_digest) { 833fcf3ce44SJohn Forte case ISCSI_DIGEST_NONE: 83430e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 835fcf3ce44SJohn Forte max_data_length, "DataDigest", "None")) { 836fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 837fcf3ce44SJohn Forte } 838fcf3ce44SJohn Forte break; 839fcf3ce44SJohn Forte case ISCSI_DIGEST_CRC32C: 84030e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 841fcf3ce44SJohn Forte max_data_length, "DataDigest", "CRC32C")) { 842fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 843fcf3ce44SJohn Forte } 844fcf3ce44SJohn Forte break; 845fcf3ce44SJohn Forte case ISCSI_DIGEST_CRC32C_NONE: 84630e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 847fcf3ce44SJohn Forte max_data_length, "DataDigest", 848fcf3ce44SJohn Forte "CRC32C,None")) { 849fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 850fcf3ce44SJohn Forte } 851fcf3ce44SJohn Forte break; 852fcf3ce44SJohn Forte default: 853fcf3ce44SJohn Forte case ISCSI_DIGEST_NONE_CRC32C: 85430e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 855fcf3ce44SJohn Forte max_data_length, "DataDigest", 856fcf3ce44SJohn Forte "None,CRC32C")) { 857fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 858fcf3ce44SJohn Forte } 859fcf3ce44SJohn Forte break; 860fcf3ce44SJohn Forte } 861fcf3ce44SJohn Forte 862fcf3ce44SJohn Forte (void) sprintf(value, "%d", 863fcf3ce44SJohn Forte icp->conn_params.max_recv_data_seg_len); 86430e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 865fcf3ce44SJohn Forte "MaxRecvDataSegmentLength", 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_wait); 87130e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 872fcf3ce44SJohn Forte max_data_length, "DefaultTime2Wait", value)) { 873fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 874fcf3ce44SJohn Forte } 875fcf3ce44SJohn Forte 876fcf3ce44SJohn Forte (void) sprintf(value, "%d", 877fcf3ce44SJohn Forte icp->conn_params.default_time_to_retain); 87830e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 879fcf3ce44SJohn Forte max_data_length, "DefaultTime2Retain", value)) { 880fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 881fcf3ce44SJohn Forte } 882fcf3ce44SJohn Forte 883fcf3ce44SJohn Forte (void) sprintf(value, "%d", 884fcf3ce44SJohn Forte icp->conn_params.error_recovery_level); 88530e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 886fcf3ce44SJohn Forte max_data_length, "ErrorRecoveryLevel", "0")) { 887fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 888fcf3ce44SJohn Forte } 889fcf3ce44SJohn Forte 89030e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 891fcf3ce44SJohn Forte max_data_length, "IFMarker", 892fcf3ce44SJohn Forte icp->conn_params.ifmarker ? "Yes" : "No")) { 893fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 894fcf3ce44SJohn Forte } 895fcf3ce44SJohn Forte 89630e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 897fcf3ce44SJohn Forte max_data_length, "OFMarker", 898fcf3ce44SJohn Forte icp->conn_params.ofmarker ? "Yes" : "No")) { 899fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 900fcf3ce44SJohn Forte } 901fcf3ce44SJohn Forte 902fcf3ce44SJohn Forte /* 903fcf3ce44SJohn Forte * The following login parameters are "Irrelevant" 904fcf3ce44SJohn Forte * for discovery sessions 905fcf3ce44SJohn Forte */ 906fcf3ce44SJohn Forte if (isp->sess_type != ISCSI_SESS_TYPE_DISCOVERY) { 907fcf3ce44SJohn Forte 90830e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 909fcf3ce44SJohn Forte max_data_length, "InitialR2T", 910fcf3ce44SJohn Forte icp->conn_params.initial_r2t ? 911fcf3ce44SJohn Forte "Yes" : "No")) { 912fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 913fcf3ce44SJohn Forte } 914fcf3ce44SJohn Forte 91530e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 916fcf3ce44SJohn Forte max_data_length, "ImmediateData", 917fcf3ce44SJohn Forte icp->conn_params.immediate_data ? 918fcf3ce44SJohn Forte "Yes" : "No")) { 919fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 920fcf3ce44SJohn Forte } 921fcf3ce44SJohn Forte 922fcf3ce44SJohn Forte (void) sprintf(value, "%d", 923fcf3ce44SJohn Forte icp->conn_params.max_burst_length); 92430e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 925fcf3ce44SJohn Forte max_data_length, "MaxBurstLength", value)) { 926fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 927fcf3ce44SJohn Forte } 928fcf3ce44SJohn Forte 929fcf3ce44SJohn Forte (void) sprintf(value, "%d", 930fcf3ce44SJohn Forte icp->conn_params.first_burst_length); 93130e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 932fcf3ce44SJohn Forte "FirstBurstLength", value)) { 933fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 934fcf3ce44SJohn Forte } 935fcf3ce44SJohn Forte 936fcf3ce44SJohn Forte (void) sprintf(value, "%d", 937fcf3ce44SJohn Forte icp->conn_params.max_outstanding_r2t); 93830e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 939fcf3ce44SJohn Forte "MaxOutstandingR2T", value)) { 940fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 941fcf3ce44SJohn Forte } 942fcf3ce44SJohn Forte 943fcf3ce44SJohn Forte (void) sprintf(value, "%d", 944fcf3ce44SJohn Forte icp->conn_params.max_connections); 94530e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, max_data_length, 946fcf3ce44SJohn Forte "MaxConnections", value)) { 947fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 948fcf3ce44SJohn Forte } 949fcf3ce44SJohn Forte 95030e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 951fcf3ce44SJohn Forte max_data_length, "DataPDUInOrder", 952fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order ? 953fcf3ce44SJohn Forte "Yes" : "No")) { 954fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 955fcf3ce44SJohn Forte } 956fcf3ce44SJohn Forte 95730e7468fSPeter Dunlap if (!iscsi_add_text(text_pdu, 958fcf3ce44SJohn Forte max_data_length, "DataSequenceInOrder", 959fcf3ce44SJohn Forte icp->conn_params.data_sequence_in_order ? 960fcf3ce44SJohn Forte "Yes" : "No")) { 961fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 962fcf3ce44SJohn Forte } 963fcf3ce44SJohn Forte } 964fcf3ce44SJohn Forte } 965fcf3ce44SJohn Forte break; 966fcf3ce44SJohn Forte 967fcf3ce44SJohn Forte case ISCSI_SECURITY_NEGOTIATION_STAGE: 968fcf3ce44SJohn Forte keytype = iscsiAuthKeyTypeNone; 969fcf3ce44SJohn Forte rc = iscsiAuthClientSendTransitBit(auth_client, &transit); 970fcf3ce44SJohn Forte 971fcf3ce44SJohn Forte /* 972fcf3ce44SJohn Forte * see if we're ready for a stage change 973fcf3ce44SJohn Forte */ 974fcf3ce44SJohn Forte if (rc == iscsiAuthStatusNoError) { 975fcf3ce44SJohn Forte if (transit) { 976fcf3ce44SJohn Forte icp->conn_next_stage = 977fcf3ce44SJohn Forte ISCSI_OP_PARMS_NEGOTIATION_STAGE; 978fcf3ce44SJohn Forte } else { 979fcf3ce44SJohn Forte icp->conn_next_stage = 980fcf3ce44SJohn Forte ISCSI_SECURITY_NEGOTIATION_STAGE; 981fcf3ce44SJohn Forte } 982fcf3ce44SJohn Forte } else { 983fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 984fcf3ce44SJohn Forte } 985fcf3ce44SJohn Forte 986fcf3ce44SJohn Forte /* 987fcf3ce44SJohn Forte * enumerate all the keys the auth code might want to send 988fcf3ce44SJohn Forte */ 989fcf3ce44SJohn Forte while (iscsiAuthClientGetNextKeyType(&keytype) == 990fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 991fcf3ce44SJohn Forte int present = 0; 992fcf3ce44SJohn Forte char *key = (char *)iscsiAuthClientGetKeyName(keytype); 993fcf3ce44SJohn Forte int key_length = key ? strlen(key) : 0; 99430e7468fSPeter Dunlap int pdu_length = text_pdu->isp_datalen; 995fcf3ce44SJohn Forte char *auth_value = data + pdu_length + key_length + 1; 996fcf3ce44SJohn Forte unsigned int max_length = max_data_length - 997fcf3ce44SJohn Forte (pdu_length + key_length + 1); 998fcf3ce44SJohn Forte 999fcf3ce44SJohn Forte /* 1000fcf3ce44SJohn Forte * add the key/value pairs the auth code wants to 1001fcf3ce44SJohn Forte * send directly to the PDU, since they could in 1002fcf3ce44SJohn Forte * theory be large. 1003fcf3ce44SJohn Forte */ 1004fcf3ce44SJohn Forte rc = iscsiAuthClientSendKeyValue(auth_client, keytype, 1005fcf3ce44SJohn Forte &present, auth_value, max_length); 1006fcf3ce44SJohn Forte if ((rc == iscsiAuthStatusNoError) && present) { 1007fcf3ce44SJohn Forte /* 1008fcf3ce44SJohn Forte * actually fill in the key 1009fcf3ce44SJohn Forte */ 1010fcf3ce44SJohn Forte (void) strncpy(&data[pdu_length], key, 1011fcf3ce44SJohn Forte key_length); 1012fcf3ce44SJohn Forte pdu_length += key_length; 1013fcf3ce44SJohn Forte data[pdu_length] = '='; 1014fcf3ce44SJohn Forte pdu_length++; 1015fcf3ce44SJohn Forte /* 1016fcf3ce44SJohn Forte * adjust the PDU's data segment length to 1017fcf3ce44SJohn Forte * include the value and trailing NULL 1018fcf3ce44SJohn Forte */ 1019fcf3ce44SJohn Forte pdu_length += strlen(auth_value) + 1; 102030e7468fSPeter Dunlap text_pdu->isp_datalen = pdu_length; 1021fcf3ce44SJohn Forte hton24(ihp->dlength, pdu_length); 1022fcf3ce44SJohn Forte } 1023fcf3ce44SJohn Forte } 1024fcf3ce44SJohn Forte 1025fcf3ce44SJohn Forte break; 1026fcf3ce44SJohn Forte case ISCSI_FULL_FEATURE_PHASE: 1027fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1028fcf3ce44SJohn Forte "failed - can't send login in full feature stage", 1029fcf3ce44SJohn Forte icp->conn_oid); 1030fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1031fcf3ce44SJohn Forte default: 1032fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1033fcf3ce44SJohn Forte "failed - can't send login in unknown stage (%d)", 1034fcf3ce44SJohn Forte icp->conn_oid, icp->conn_current_stage); 1035fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1036fcf3ce44SJohn Forte } 1037fcf3ce44SJohn Forte 1038fcf3ce44SJohn Forte /* fill in the flags */ 1039fcf3ce44SJohn Forte ilhp->flags = icp->conn_current_stage << 2; 1040fcf3ce44SJohn Forte if (transit) { 1041fcf3ce44SJohn Forte /* transit to the next stage */ 1042fcf3ce44SJohn Forte ilhp->flags |= icp->conn_next_stage; 1043fcf3ce44SJohn Forte ilhp->flags |= ISCSI_FLAG_LOGIN_TRANSIT; 1044fcf3ce44SJohn Forte } else { 1045fcf3ce44SJohn Forte /* next == current */ 1046fcf3ce44SJohn Forte ilhp->flags |= icp->conn_current_stage; 1047fcf3ce44SJohn Forte } 1048fcf3ce44SJohn Forte 1049fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 1050fcf3ce44SJohn Forte } 1051fcf3ce44SJohn Forte 1052fcf3ce44SJohn Forte 1053fcf3ce44SJohn Forte /* 1054fcf3ce44SJohn Forte * iscsi_process_login_response - This assumes the text data is 1055fcf3ce44SJohn Forte * always NUL terminated. The caller can always arrange for that by 1056fcf3ce44SJohn Forte * using a slightly larger buffer than the max PDU size, and then 1057fcf3ce44SJohn Forte * appending a NUL to the PDU. 1058fcf3ce44SJohn Forte */ 1059fcf3ce44SJohn Forte static iscsi_status_t 1060fcf3ce44SJohn Forte iscsi_process_login_response(iscsi_conn_t *icp, 1061fcf3ce44SJohn Forte iscsi_login_rsp_hdr_t *ilrhp, char *data, int max_data_length) 1062fcf3ce44SJohn Forte { 1063fcf3ce44SJohn Forte iscsi_sess_t *isp = NULL; 1064fcf3ce44SJohn Forte IscsiAuthClient *auth_client = NULL; 1065fcf3ce44SJohn Forte int transit = 0; 1066fcf3ce44SJohn Forte char *text = data; 1067fcf3ce44SJohn Forte char *end = NULL; 1068fcf3ce44SJohn Forte int pdu_current_stage = 0; 1069fcf3ce44SJohn Forte int pdu_next_stage = 0; 1070fcf3ce44SJohn Forte int debug_status = 0; 1071fcf3ce44SJohn Forte unsigned long tmp; 1072fcf3ce44SJohn Forte char *tmpe; 1073fcf3ce44SJohn Forte boolean_t fbl_irrelevant = B_FALSE; 1074fcf3ce44SJohn Forte 1075fcf3ce44SJohn Forte ASSERT(icp != NULL); 1076fcf3ce44SJohn Forte ASSERT(ilrhp != NULL); 1077fcf3ce44SJohn Forte ASSERT(data != NULL); 1078fcf3ce44SJohn Forte isp = icp->conn_sess; 1079fcf3ce44SJohn Forte ASSERT(isp != NULL); 1080fcf3ce44SJohn Forte 1081fcf3ce44SJohn Forte auth_client = 1082fcf3ce44SJohn Forte (isp->sess_auth.auth_buffers && isp->sess_auth.num_auth_buffers) ? 1083fcf3ce44SJohn Forte (IscsiAuthClient *) isp->sess_auth.auth_buffers[0].address : NULL; 1084fcf3ce44SJohn Forte transit = ilrhp->flags & ISCSI_FLAG_LOGIN_TRANSIT; 1085fcf3ce44SJohn Forte 1086fcf3ce44SJohn Forte /* verify the initial buffer was big enough to hold everything */ 1087fcf3ce44SJohn Forte end = text + ntoh24(ilrhp->dlength) + 1; 1088fcf3ce44SJohn Forte if (end >= (data + max_data_length)) { 1089fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1090fcf3ce44SJohn Forte "buffer too small", icp->conn_oid); 1091fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1092fcf3ce44SJohn Forte } 1093fcf3ce44SJohn Forte *end = '\0'; 1094fcf3ce44SJohn Forte 1095fcf3ce44SJohn Forte /* if the response status was success, sanity check the response */ 1096fcf3ce44SJohn Forte if (ilrhp->status_class == ISCSI_STATUS_CLASS_SUCCESS) { 1097fcf3ce44SJohn Forte /* check the active version */ 1098fcf3ce44SJohn Forte if (ilrhp->active_version != ISCSI_DRAFT20_VERSION) { 1099fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1100fcf3ce44SJohn Forte "failed - target version incompatible " 1101fcf3ce44SJohn Forte "received:0x%0x2x expected:0x%02x", 1102fcf3ce44SJohn Forte icp->conn_oid, ilrhp->active_version, 1103fcf3ce44SJohn Forte ISCSI_DRAFT20_VERSION); 1104fcf3ce44SJohn Forte return (ISCSI_STATUS_VERSION_MISMATCH); 1105fcf3ce44SJohn Forte } 1106fcf3ce44SJohn Forte 1107fcf3ce44SJohn Forte /* make sure the current stage matches */ 1108fcf3ce44SJohn Forte pdu_current_stage = (ilrhp->flags & 1109fcf3ce44SJohn Forte ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2; 1110fcf3ce44SJohn Forte if (pdu_current_stage != icp->conn_current_stage) { 1111fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1112fcf3ce44SJohn Forte "failed - login response contained invalid " 1113fcf3ce44SJohn Forte "stage %d", icp->conn_oid, pdu_current_stage); 1114fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1115fcf3ce44SJohn Forte } 1116fcf3ce44SJohn Forte 1117fcf3ce44SJohn Forte /* 1118fcf3ce44SJohn Forte * Make sure that we're actually advancing 1119fcf3ce44SJohn Forte * if the T-bit is set 1120fcf3ce44SJohn Forte */ 1121fcf3ce44SJohn Forte pdu_next_stage = ilrhp->flags & 1122fcf3ce44SJohn Forte ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; 1123fcf3ce44SJohn Forte if (transit && (pdu_next_stage <= icp->conn_current_stage)) { 1124fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1125fcf3ce44SJohn Forte "failed - login response wants to go to stage " 1126fcf3ce44SJohn Forte "%d, but we want stage %d", icp->conn_oid, 1127fcf3ce44SJohn Forte pdu_next_stage, icp->conn_next_stage); 1128fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1129fcf3ce44SJohn Forte } 1130fcf3ce44SJohn Forte } 1131fcf3ce44SJohn Forte 1132fcf3ce44SJohn Forte if (icp->conn_current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE) { 1133fcf3ce44SJohn Forte if (iscsiAuthClientRecvBegin(auth_client) != 1134fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 1135fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1136fcf3ce44SJohn Forte "authentication receive failed", icp->conn_oid); 1137fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1138fcf3ce44SJohn Forte } 1139fcf3ce44SJohn Forte 1140fcf3ce44SJohn Forte if (iscsiAuthClientRecvTransitBit(auth_client, 1141fcf3ce44SJohn Forte transit) != iscsiAuthStatusNoError) { 1142fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1143fcf3ce44SJohn Forte "authentication transmit failed", icp->conn_oid); 1144fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1145fcf3ce44SJohn Forte } 1146fcf3ce44SJohn Forte } 1147fcf3ce44SJohn Forte 1148fcf3ce44SJohn Forte /* 1149fcf3ce44SJohn Forte * scan the text data 1150fcf3ce44SJohn Forte */ 1151fcf3ce44SJohn Forte more_text: 1152fcf3ce44SJohn Forte while (text && (text < end)) { 1153fcf3ce44SJohn Forte char *value = NULL; 1154fcf3ce44SJohn Forte char *value_end = NULL; 1155fcf3ce44SJohn Forte 1156fcf3ce44SJohn Forte /* 1157fcf3ce44SJohn Forte * skip any NULs separating each text key=value pair 1158fcf3ce44SJohn Forte */ 1159fcf3ce44SJohn Forte while ((text < end) && (*text == '\0')) { 1160fcf3ce44SJohn Forte text++; 1161fcf3ce44SJohn Forte } 1162fcf3ce44SJohn Forte if (text >= end) { 1163fcf3ce44SJohn Forte break; 1164fcf3ce44SJohn Forte } 1165fcf3ce44SJohn Forte 1166fcf3ce44SJohn Forte /* 1167fcf3ce44SJohn Forte * handle keys appropriate for each stage 1168fcf3ce44SJohn Forte */ 1169fcf3ce44SJohn Forte switch (icp->conn_current_stage) { 1170fcf3ce44SJohn Forte case ISCSI_SECURITY_NEGOTIATION_STAGE: 1171fcf3ce44SJohn Forte /* 1172fcf3ce44SJohn Forte * a few keys are possible in Security stage 1173fcf3ce44SJohn Forte * * which the auth code doesn't care about, 1174fcf3ce44SJohn Forte * * but which we might want to see, or at 1175fcf3ce44SJohn Forte * * least not choke on. 1176fcf3ce44SJohn Forte */ 1177fcf3ce44SJohn Forte if (iscsi_find_key_value("TargetAlias", 1178fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1179fcf3ce44SJohn Forte isp->sess_alias_length = 1180fcf3ce44SJohn Forte sizeof (isp->sess_alias) - 1; 1181fcf3ce44SJohn Forte 1182fcf3ce44SJohn Forte if ((value_end - value) < 1183fcf3ce44SJohn Forte isp->sess_alias_length) { 1184fcf3ce44SJohn Forte isp->sess_alias_length = 1185fcf3ce44SJohn Forte value_end - value; 1186fcf3ce44SJohn Forte } 1187fcf3ce44SJohn Forte 1188fcf3ce44SJohn Forte bcopy(value, isp->sess_alias, 1189fcf3ce44SJohn Forte isp->sess_alias_length); 1190fcf3ce44SJohn Forte isp->sess_alias[isp->sess_alias_length + 1] = 1191fcf3ce44SJohn Forte '\0'; 1192fcf3ce44SJohn Forte text = value_end; 1193fcf3ce44SJohn Forte 1194fcf3ce44SJohn Forte } else if (iscsi_find_key_value("TargetAddress", 1195fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1196fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(iscsi_update_address( 1197fcf3ce44SJohn Forte icp, value))) { 1198fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1199fcf3ce44SJohn Forte "login failed - login redirection " 1200fcf3ce44SJohn Forte "invalid", icp->conn_oid); 1201fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1202fcf3ce44SJohn Forte } 1203fcf3ce44SJohn Forte text = value_end; 1204fcf3ce44SJohn Forte } else if (iscsi_find_key_value("TargetPortalGroupTag", 1205fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1206fcf3ce44SJohn Forte /* 1207fcf3ce44SJohn Forte * We should have already obtained this via 1208fcf3ce44SJohn Forte * discovery. We've already picked an isid, 1209fcf3ce44SJohn Forte * so the most we can do is confirm we reached 1210fcf3ce44SJohn Forte * the portal group we were expecting to. 1211fcf3ce44SJohn Forte */ 1212fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1213fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1214fcf3ce44SJohn Forte } 1215fcf3ce44SJohn Forte if (isp->sess_tpgt_conf != ISCSI_DEFAULT_TPGT) { 1216fcf3ce44SJohn Forte if (tmp != isp->sess_tpgt_conf) { 1217fcf3ce44SJohn Forte 1218fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - target " 1219fcf3ce44SJohn Forte "protocol group tag mismatch, expected %d, received %lu", 1220fcf3ce44SJohn Forte icp->conn_oid, isp->sess_tpgt_conf, tmp); 1221cc7ef495Syi zhang - Sun Microsystems - Beijing China return (ISCSI_STATUS_LOGIN_TPGT_NEGO_FAIL); 1222fcf3ce44SJohn Forte 1223fcf3ce44SJohn Forte } 1224fcf3ce44SJohn Forte } 1225fcf3ce44SJohn Forte isp->sess_tpgt_nego = (int)tmp; 1226fcf3ce44SJohn Forte text = value_end; 1227fcf3ce44SJohn Forte } else { 1228fcf3ce44SJohn Forte /* 1229fcf3ce44SJohn Forte * any key we don't recognize either goes 1230fcf3ce44SJohn Forte * to the auth code, or we choke on it 1231fcf3ce44SJohn Forte */ 1232fcf3ce44SJohn Forte int keytype = iscsiAuthKeyTypeNone; 1233fcf3ce44SJohn Forte 1234fcf3ce44SJohn Forte while (iscsiAuthClientGetNextKeyType( 1235fcf3ce44SJohn Forte &keytype) == iscsiAuthStatusNoError) { 1236fcf3ce44SJohn Forte 1237fcf3ce44SJohn Forte char *key = 1238fcf3ce44SJohn Forte (char *)iscsiAuthClientGetKeyName( 1239fcf3ce44SJohn Forte keytype); 1240fcf3ce44SJohn Forte 1241fcf3ce44SJohn Forte if ((key) && 1242fcf3ce44SJohn Forte (iscsi_find_key_value(key, 1243fcf3ce44SJohn Forte text, end, &value, &value_end))) { 1244fcf3ce44SJohn Forte 1245fcf3ce44SJohn Forte if (iscsiAuthClientRecvKeyValue 1246fcf3ce44SJohn Forte (auth_client, keytype, 1247fcf3ce44SJohn Forte value) != 1248fcf3ce44SJohn Forte iscsiAuthStatusNoError) { 1249fcf3ce44SJohn Forte 1250fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - can't accept " 1251fcf3ce44SJohn Forte "%s in security stage", icp->conn_oid, text); 1252fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1253fcf3ce44SJohn Forte 1254fcf3ce44SJohn Forte } 1255fcf3ce44SJohn Forte text = value_end; 1256fcf3ce44SJohn Forte goto more_text; 1257fcf3ce44SJohn Forte } 1258fcf3ce44SJohn Forte } 1259fcf3ce44SJohn Forte 1260fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - can't except " 1261fcf3ce44SJohn Forte "%s in security stage", icp->conn_oid, text); 1262fcf3ce44SJohn Forte 1263fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1264fcf3ce44SJohn Forte } 1265fcf3ce44SJohn Forte break; 1266fcf3ce44SJohn Forte case ISCSI_OP_PARMS_NEGOTIATION_STAGE: 1267fcf3ce44SJohn Forte if (iscsi_find_key_value("TargetAlias", text, 1268fcf3ce44SJohn Forte end, &value, &value_end)) { 1269fcf3ce44SJohn Forte isp->sess_alias_length = 1270fcf3ce44SJohn Forte sizeof (isp->sess_alias) - 1; 1271fcf3ce44SJohn Forte 1272fcf3ce44SJohn Forte if ((value_end - value) < 1273fcf3ce44SJohn Forte isp->sess_alias_length) { 1274fcf3ce44SJohn Forte isp->sess_alias_length = 1275fcf3ce44SJohn Forte value_end - value; 1276fcf3ce44SJohn Forte } 1277fcf3ce44SJohn Forte 1278fcf3ce44SJohn Forte bcopy(value, isp->sess_alias, 1279fcf3ce44SJohn Forte isp->sess_alias_length); 1280fcf3ce44SJohn Forte isp->sess_alias[isp->sess_alias_length + 1] = 1281fcf3ce44SJohn Forte '\0'; 1282fcf3ce44SJohn Forte text = value_end; 1283fcf3ce44SJohn Forte 1284fcf3ce44SJohn Forte } else if (iscsi_find_key_value("TargetAddress", 1285fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1286fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(iscsi_update_address( 1287fcf3ce44SJohn Forte icp, value))) { 1288fcf3ce44SJohn Forte 1289fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - login " 1290fcf3ce44SJohn Forte "redirection invalid", icp->conn_oid); 1291fcf3ce44SJohn Forte 1292fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1293fcf3ce44SJohn Forte } 1294fcf3ce44SJohn Forte text = value_end; 1295fcf3ce44SJohn Forte } else if (iscsi_find_key_value("TargetPortalGroupTag", 1296fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1297fcf3ce44SJohn Forte /* 1298fcf3ce44SJohn Forte * We should have already obtained this via 1299fcf3ce44SJohn Forte * discovery. We've already picked an isid, 1300fcf3ce44SJohn Forte * so the most we can do is confirm we reached 1301fcf3ce44SJohn Forte * the portal group we were expecting to. 1302fcf3ce44SJohn Forte */ 1303fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1304fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1305fcf3ce44SJohn Forte } 1306fcf3ce44SJohn Forte if (isp->sess_tpgt_conf != ISCSI_DEFAULT_TPGT) { 1307fcf3ce44SJohn Forte if (tmp != isp->sess_tpgt_conf) { 1308fcf3ce44SJohn Forte 1309fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - target portal " 1310fcf3ce44SJohn Forte "tag mismatch, expected:%d received:%lu", icp->conn_oid, 1311fcf3ce44SJohn Forte isp->sess_tpgt_conf, tmp); 1312cc7ef495Syi zhang - Sun Microsystems - Beijing China return (ISCSI_STATUS_LOGIN_TPGT_NEGO_FAIL); 1313fcf3ce44SJohn Forte 1314fcf3ce44SJohn Forte } 1315fcf3ce44SJohn Forte } 1316fcf3ce44SJohn Forte isp->sess_tpgt_nego = (int)tmp; 1317fcf3ce44SJohn Forte text = value_end; 1318fcf3ce44SJohn Forte 1319fcf3ce44SJohn Forte } else if (iscsi_find_key_value("InitialR2T", 1320fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1321fcf3ce44SJohn Forte 1322fcf3ce44SJohn Forte /* 1323fcf3ce44SJohn Forte * iSCSI RFC section 12.10 states that 1324fcf3ce44SJohn Forte * InitialR2T is Irrelevant for a 1325fcf3ce44SJohn Forte * discovery session. 1326fcf3ce44SJohn Forte */ 1327fcf3ce44SJohn Forte if (isp->sess_type == 1328fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1329fcf3ce44SJohn Forte /* EMPTY */ 1330fcf3ce44SJohn Forte } else if (value == NULL) { 1331fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1332fcf3ce44SJohn Forte "login failed - InitialR2T is " 1333fcf3ce44SJohn Forte "invalid - protocol error", 1334fcf3ce44SJohn Forte icp->conn_oid); 1335fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1336fcf3ce44SJohn Forte } else if (strcmp(value, "Yes") == 0) { 1337fcf3ce44SJohn Forte icp->conn_params.initial_r2t = B_TRUE; 1338fcf3ce44SJohn Forte } else if (strcmp(value, "No") == 0) { 1339fcf3ce44SJohn Forte icp->conn_params.initial_r2t = B_FALSE; 1340fcf3ce44SJohn Forte } else { 1341fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1342fcf3ce44SJohn Forte "login failed - InitialR2T is " 1343fcf3ce44SJohn Forte "invalid - protocol error", 1344fcf3ce44SJohn Forte icp->conn_oid); 1345fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1346fcf3ce44SJohn Forte } 1347fcf3ce44SJohn Forte text = value_end; 1348fcf3ce44SJohn Forte 1349fcf3ce44SJohn Forte } else if (iscsi_find_key_value("ImmediateData", 1350fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1351fcf3ce44SJohn Forte 1352fcf3ce44SJohn Forte /* 1353fcf3ce44SJohn Forte * iSCSI RFC section 12.11 states that 1354fcf3ce44SJohn Forte * ImmediateData is Irrelevant for a 1355fcf3ce44SJohn Forte * discovery session. 1356fcf3ce44SJohn Forte */ 1357fcf3ce44SJohn Forte if (isp->sess_type == 1358fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1359fcf3ce44SJohn Forte /* EMPTY */ 1360fcf3ce44SJohn Forte } else if (value == NULL) { 1361fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1362fcf3ce44SJohn Forte "login failed - ImmediateData is " 1363fcf3ce44SJohn Forte "invalid - protocol error", 1364fcf3ce44SJohn Forte icp->conn_oid); 1365fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1366fcf3ce44SJohn Forte } else if (strcmp(value, "Yes") == 0) { 1367fcf3ce44SJohn Forte icp->conn_params.immediate_data = 1; 1368fcf3ce44SJohn Forte } else if (strcmp(value, "No") == 0) { 1369fcf3ce44SJohn Forte icp->conn_params.immediate_data = 0; 1370fcf3ce44SJohn Forte } else { 1371fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1372fcf3ce44SJohn Forte "login failed - ImmediateData is " 1373fcf3ce44SJohn Forte "invalid - protocol error", 1374fcf3ce44SJohn Forte icp->conn_oid); 1375fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1376fcf3ce44SJohn Forte } 1377fcf3ce44SJohn Forte text = value_end; 1378fcf3ce44SJohn Forte 1379fcf3ce44SJohn Forte } else if (iscsi_find_key_value( 1380fcf3ce44SJohn Forte "MaxRecvDataSegmentLength", text, end, 1381fcf3ce44SJohn Forte &value, &value_end)) { 1382fcf3ce44SJohn Forte 1383fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1384fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1385fcf3ce44SJohn Forte "login failed - MaxRecvDataSegment" 1386fcf3ce44SJohn Forte "Length is invalid - protocol " 1387fcf3ce44SJohn Forte "error", icp->conn_oid); 1388fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1389fcf3ce44SJohn Forte } 1390fcf3ce44SJohn Forte icp->conn_params.max_recv_data_seg_len = 1391fcf3ce44SJohn Forte icp->conn_params.max_xmit_data_seg_len = 1392fcf3ce44SJohn Forte (int)tmp; 1393fcf3ce44SJohn Forte 1394fcf3ce44SJohn Forte text = value_end; 1395fcf3ce44SJohn Forte } else if (iscsi_find_key_value("FirstBurstLength", 1396fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1397fcf3ce44SJohn Forte 1398fcf3ce44SJohn Forte /* 1399fcf3ce44SJohn Forte * iSCSI RFC section 12.14 states that 1400fcf3ce44SJohn Forte * FirstBurstLength is Irrelevant if 1401fcf3ce44SJohn Forte * InitialR2T=Yes and ImmediateData=No 1402fcf3ce44SJohn Forte * or is this is a discovery session. 1403fcf3ce44SJohn Forte */ 1404fcf3ce44SJohn Forte if ((isp->sess_type == 1405fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY)) { 1406fcf3ce44SJohn Forte /* EMPTY */ 1407fcf3ce44SJohn Forte } else if (value && 1408fcf3ce44SJohn Forte (strcmp(value, "Irrelevant") == 0)) { 1409fcf3ce44SJohn Forte /* irrelevant */ 1410fcf3ce44SJohn Forte fbl_irrelevant = B_TRUE; 1411fcf3ce44SJohn Forte } else if (ddi_strtoul( 1412fcf3ce44SJohn Forte value, &tmpe, 0, &tmp) != 0) { 1413fcf3ce44SJohn Forte /* bad value */ 1414fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1415fcf3ce44SJohn Forte "login failed - FirstBurstLength" 1416fcf3ce44SJohn Forte "is invalid - protocol error", 1417fcf3ce44SJohn Forte icp->conn_oid); 1418fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1419fcf3ce44SJohn Forte } else { 1420fcf3ce44SJohn Forte /* good value */ 1421fcf3ce44SJohn Forte icp->conn_params.first_burst_length = 1422fcf3ce44SJohn Forte (int)tmp; 1423fcf3ce44SJohn Forte } 1424fcf3ce44SJohn Forte text = value_end; 1425fcf3ce44SJohn Forte } else if (iscsi_find_key_value("MaxBurstLength", 1426fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1427fcf3ce44SJohn Forte /* 1428fcf3ce44SJohn Forte * iSCSI RFC section 12.13 states that 1429fcf3ce44SJohn Forte * MaxBurstLength is Irrelevant for a 1430fcf3ce44SJohn Forte * discovery session. 1431fcf3ce44SJohn Forte */ 1432fcf3ce44SJohn Forte if (isp->sess_type == 1433fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1434fcf3ce44SJohn Forte /* EMPTY */ 1435fcf3ce44SJohn Forte } else if (ddi_strtoul( 1436fcf3ce44SJohn Forte value, &tmpe, 0, &tmp) != 0) { 1437fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1438fcf3ce44SJohn Forte "login failed - MaxBurstLength" 1439fcf3ce44SJohn Forte "is invalid - protocol error", 1440fcf3ce44SJohn Forte icp->conn_oid); 1441fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1442fcf3ce44SJohn Forte } else { 1443fcf3ce44SJohn Forte icp->conn_params.max_burst_length = 1444fcf3ce44SJohn Forte (int)tmp; 1445fcf3ce44SJohn Forte } 1446fcf3ce44SJohn Forte 1447fcf3ce44SJohn Forte text = value_end; 1448fcf3ce44SJohn Forte 1449fcf3ce44SJohn Forte } else if (iscsi_find_key_value("HeaderDigest", 1450fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1451fcf3ce44SJohn Forte 1452fcf3ce44SJohn Forte if (strcmp(value, "None") == 0) { 1453fcf3ce44SJohn Forte if (icp->conn_params.header_digest != 1454fcf3ce44SJohn Forte ISCSI_DIGEST_CRC32C) { 1455fcf3ce44SJohn Forte icp->conn_params.header_digest = 1456fcf3ce44SJohn Forte ISCSI_DIGEST_NONE; 1457fcf3ce44SJohn Forte } else { 1458fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi " 1459fcf3ce44SJohn Forte "connection(%u) login " 1460fcf3ce44SJohn Forte "failed - HeaderDigest=" 1461fcf3ce44SJohn Forte "CRC32 is required, can't " 1462fcf3ce44SJohn Forte "accept %s", 1463fcf3ce44SJohn Forte icp->conn_oid, text); 1464fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1465fcf3ce44SJohn Forte } 1466fcf3ce44SJohn Forte } else if (strcmp(value, "CRC32C") == 0) { 1467fcf3ce44SJohn Forte if (icp->conn_params.header_digest != 1468fcf3ce44SJohn Forte ISCSI_DIGEST_NONE) { 1469fcf3ce44SJohn Forte icp->conn_params.header_digest = 1470fcf3ce44SJohn Forte ISCSI_DIGEST_CRC32C; 1471fcf3ce44SJohn Forte } else { 1472fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi " 1473fcf3ce44SJohn Forte "connection(%u) login " 1474fcf3ce44SJohn Forte "failed - HeaderDigest=" 1475fcf3ce44SJohn Forte "None is required, can't " 1476fcf3ce44SJohn Forte "accept %s", 1477fcf3ce44SJohn Forte icp->conn_oid, text); 1478fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1479fcf3ce44SJohn Forte } 1480fcf3ce44SJohn Forte } else { 1481fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1482fcf3ce44SJohn Forte "login failed - HeaderDigest " 1483fcf3ce44SJohn Forte "can't accept %s", icp->conn_oid, 1484fcf3ce44SJohn Forte text); 1485fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1486fcf3ce44SJohn Forte } 1487fcf3ce44SJohn Forte text = value_end; 1488fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DataDigest", text, 1489fcf3ce44SJohn Forte end, &value, &value_end)) { 1490fcf3ce44SJohn Forte 1491fcf3ce44SJohn Forte if (strcmp(value, "None") == 0) { 1492fcf3ce44SJohn Forte if (icp->conn_params.data_digest != 1493fcf3ce44SJohn Forte ISCSI_DIGEST_CRC32C) { 1494fcf3ce44SJohn Forte icp->conn_params.data_digest = 1495fcf3ce44SJohn Forte ISCSI_DIGEST_NONE; 1496fcf3ce44SJohn Forte } else { 1497fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi " 1498fcf3ce44SJohn Forte "connection(%u) login " 1499fcf3ce44SJohn Forte "failed - DataDigest=" 1500fcf3ce44SJohn Forte "CRC32C is required, " 1501fcf3ce44SJohn Forte "can't accept %s", 1502fcf3ce44SJohn Forte icp->conn_oid, text); 1503fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1504fcf3ce44SJohn Forte } 1505fcf3ce44SJohn Forte } else if (strcmp(value, "CRC32C") == 0) { 1506fcf3ce44SJohn Forte if (icp->conn_params.data_digest != 1507fcf3ce44SJohn Forte ISCSI_DIGEST_NONE) { 1508fcf3ce44SJohn Forte icp->conn_params.data_digest = 1509fcf3ce44SJohn Forte ISCSI_DIGEST_CRC32C; 1510fcf3ce44SJohn Forte } else { 1511fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi " 1512fcf3ce44SJohn Forte "connection(%u) login " 1513fcf3ce44SJohn Forte "failed - DataDigest=None " 1514fcf3ce44SJohn Forte "is required, can't " 1515fcf3ce44SJohn Forte "accept %s", 1516fcf3ce44SJohn Forte icp->conn_oid, text); 1517fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1518fcf3ce44SJohn Forte } 1519fcf3ce44SJohn Forte } else { 1520fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1521fcf3ce44SJohn Forte "login failed - can't accept %s", 1522fcf3ce44SJohn Forte icp->conn_oid, text); 1523fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1524fcf3ce44SJohn Forte } 1525fcf3ce44SJohn Forte text = value_end; 1526fcf3ce44SJohn Forte 1527fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DefaultTime2Wait", 1528fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1529fcf3ce44SJohn Forte 1530fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1531fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1532fcf3ce44SJohn Forte "login failed - DefaultTime2Wait " 1533fcf3ce44SJohn Forte "is invalid - protocol error", 1534fcf3ce44SJohn Forte icp->conn_oid); 1535fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1536fcf3ce44SJohn Forte } 1537fcf3ce44SJohn Forte icp->conn_params.default_time_to_wait = 1538fcf3ce44SJohn Forte (int)tmp; 1539fcf3ce44SJohn Forte 1540fcf3ce44SJohn Forte text = value_end; 1541fcf3ce44SJohn Forte 1542fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DefaultTime2Retain", 1543fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1544fcf3ce44SJohn Forte 1545fcf3ce44SJohn Forte if (ddi_strtoul(value, &tmpe, 0, &tmp) != 0) { 1546fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1547fcf3ce44SJohn Forte "login failed - DefaultTime2Retain " 1548fcf3ce44SJohn Forte "is invalid - protocol error", 1549fcf3ce44SJohn Forte icp->conn_oid); 1550fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1551fcf3ce44SJohn Forte } 1552fcf3ce44SJohn Forte icp->conn_params.default_time_to_retain = 1553fcf3ce44SJohn Forte (int)tmp; 1554fcf3ce44SJohn Forte 1555fcf3ce44SJohn Forte text = value_end; 1556fcf3ce44SJohn Forte 1557fcf3ce44SJohn Forte } else if (iscsi_find_key_value("OFMarker", text, 1558fcf3ce44SJohn Forte end, &value, &value_end)) { 1559fcf3ce44SJohn Forte 1560fcf3ce44SJohn Forte /* 1561fcf3ce44SJohn Forte * result function is AND, target must 1562fcf3ce44SJohn Forte * honor our No 1563fcf3ce44SJohn Forte */ 1564fcf3ce44SJohn Forte text = value_end; 1565fcf3ce44SJohn Forte 1566fcf3ce44SJohn Forte } else if (iscsi_find_key_value("OFMarkInt", text, 1567fcf3ce44SJohn Forte end, &value, &value_end)) { 1568fcf3ce44SJohn Forte 1569fcf3ce44SJohn Forte /* 1570fcf3ce44SJohn Forte * we don't do markers, so we don't care 1571fcf3ce44SJohn Forte */ 1572fcf3ce44SJohn Forte text = value_end; 1573fcf3ce44SJohn Forte 1574fcf3ce44SJohn Forte } else if (iscsi_find_key_value("IFMarker", text, 1575fcf3ce44SJohn Forte end, &value, &value_end)) { 1576fcf3ce44SJohn Forte 1577fcf3ce44SJohn Forte /* 1578fcf3ce44SJohn Forte * result function is AND, target must 1579fcf3ce44SJohn Forte * honor our No 1580fcf3ce44SJohn Forte */ 1581fcf3ce44SJohn Forte text = value_end; 1582fcf3ce44SJohn Forte 1583fcf3ce44SJohn Forte } else if (iscsi_find_key_value("IFMarkInt", text, 1584fcf3ce44SJohn Forte end, &value, &value_end)) { 1585fcf3ce44SJohn Forte 1586fcf3ce44SJohn Forte /* 1587fcf3ce44SJohn Forte * we don't do markers, so we don't care 1588fcf3ce44SJohn Forte */ 1589fcf3ce44SJohn Forte text = value_end; 1590fcf3ce44SJohn Forte 1591fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DataPDUInOrder", 1592fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1593fcf3ce44SJohn Forte 1594fcf3ce44SJohn Forte /* 1595fcf3ce44SJohn Forte * iSCSI RFC section 12.18 states that 1596fcf3ce44SJohn Forte * DataPDUInOrder is Irrelevant for a 1597fcf3ce44SJohn Forte * discovery session. 1598fcf3ce44SJohn Forte */ 1599fcf3ce44SJohn Forte if (isp->sess_type == 1600fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1601fcf3ce44SJohn Forte /* EMPTY */ 1602fcf3ce44SJohn Forte } else if (value == NULL) { 1603fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1604fcf3ce44SJohn Forte "login failed - InitialR2T is " 1605fcf3ce44SJohn Forte "invalid - protocol error", 1606fcf3ce44SJohn Forte icp->conn_oid); 1607fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1608fcf3ce44SJohn Forte } else if (strcmp(value, "Yes") == 0) { 1609fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order = 1610fcf3ce44SJohn Forte B_TRUE; 1611fcf3ce44SJohn Forte } else if (strcmp(value, "No") == 0) { 1612fcf3ce44SJohn Forte icp->conn_params.data_pdu_in_order = 1613fcf3ce44SJohn Forte B_FALSE; 1614fcf3ce44SJohn Forte } else { 1615fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1616fcf3ce44SJohn Forte "login failed - InitialR2T is " 1617fcf3ce44SJohn Forte "invalid - protocol error", 1618fcf3ce44SJohn Forte icp->conn_oid); 1619fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1620fcf3ce44SJohn Forte } 1621fcf3ce44SJohn Forte text = value_end; 1622fcf3ce44SJohn Forte 1623fcf3ce44SJohn Forte } else if (iscsi_find_key_value("DataSequenceInOrder", 1624fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1625fcf3ce44SJohn Forte 1626fcf3ce44SJohn Forte /* 1627fcf3ce44SJohn Forte * iSCSI RFC section 12.19 states that 1628fcf3ce44SJohn Forte * DataSequenceInOrder is Irrelevant for a 1629fcf3ce44SJohn Forte * discovery session. 1630fcf3ce44SJohn Forte */ 1631fcf3ce44SJohn Forte if (isp->sess_type == 1632fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1633fcf3ce44SJohn Forte /* EMPTY */ 1634fcf3ce44SJohn Forte } else if (value == NULL) { 1635fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1636fcf3ce44SJohn Forte "login failed - InitialR2T is " 1637fcf3ce44SJohn Forte "invalid - protocol error", 1638fcf3ce44SJohn Forte icp->conn_oid); 1639fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1640fcf3ce44SJohn Forte } else if (strcmp(value, "Yes") == 0) { 1641fcf3ce44SJohn Forte icp->conn_params. 1642fcf3ce44SJohn Forte data_sequence_in_order = B_TRUE; 1643fcf3ce44SJohn Forte } else if (strcmp(value, "No") == 0) { 1644fcf3ce44SJohn Forte icp->conn_params. 1645fcf3ce44SJohn Forte data_sequence_in_order = B_FALSE; 1646fcf3ce44SJohn Forte } else { 1647fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1648fcf3ce44SJohn Forte "login failed - InitialR2T is " 1649fcf3ce44SJohn Forte "invalid - protocol error", 1650fcf3ce44SJohn Forte icp->conn_oid); 1651fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1652fcf3ce44SJohn Forte } 1653fcf3ce44SJohn Forte text = value_end; 1654fcf3ce44SJohn Forte 1655fcf3ce44SJohn Forte } else if (iscsi_find_key_value("MaxOutstandingR2T", 1656fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1657fcf3ce44SJohn Forte 1658fcf3ce44SJohn Forte /* 1659fcf3ce44SJohn Forte * iSCSI RFC section 12.17 states that 1660fcf3ce44SJohn Forte * MaxOutstandingR2T is Irrelevant for a 1661fcf3ce44SJohn Forte * discovery session. 1662fcf3ce44SJohn Forte */ 1663fcf3ce44SJohn Forte if (isp->sess_type == 1664fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1665fcf3ce44SJohn Forte /* EMPTY */ 1666fcf3ce44SJohn Forte } else if (strcmp(value, "1")) { 1667fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1668fcf3ce44SJohn Forte "login failed - can't accept " 1669fcf3ce44SJohn Forte "MaxOutstandingR2T %s", 1670fcf3ce44SJohn Forte icp->conn_oid, value); 1671fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1672fcf3ce44SJohn Forte } 1673fcf3ce44SJohn Forte text = value_end; 1674fcf3ce44SJohn Forte 1675fcf3ce44SJohn Forte } else if (iscsi_find_key_value("MaxConnections", 1676fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1677fcf3ce44SJohn Forte 1678fcf3ce44SJohn Forte /* 1679fcf3ce44SJohn Forte * iSCSI RFC section 12.2 states that 1680fcf3ce44SJohn Forte * MaxConnections is Irrelevant for a 1681fcf3ce44SJohn Forte * discovery session. 1682fcf3ce44SJohn Forte */ 1683fcf3ce44SJohn Forte if (isp->sess_type == 1684fcf3ce44SJohn Forte ISCSI_SESS_TYPE_DISCOVERY) { 1685fcf3ce44SJohn Forte /* EMPTY */ 1686fcf3ce44SJohn Forte } else if (strcmp(value, "1")) { 1687fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1688fcf3ce44SJohn Forte "login failed - can't accept " 1689fcf3ce44SJohn Forte "MaxConnections %s", 1690fcf3ce44SJohn Forte icp->conn_oid, value); 1691fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1692fcf3ce44SJohn Forte } 1693fcf3ce44SJohn Forte text = value_end; 1694fcf3ce44SJohn Forte 1695fcf3ce44SJohn Forte } else if (iscsi_find_key_value("ErrorRecoveryLevel", 1696fcf3ce44SJohn Forte text, end, &value, &value_end)) { 1697fcf3ce44SJohn Forte 1698fcf3ce44SJohn Forte if (strcmp(value, "0")) { 1699fcf3ce44SJohn Forte 1700fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1701fcf3ce44SJohn Forte "login failed - can't accept " 1702fcf3ce44SJohn Forte "ErrorRecoveryLevel %s", 1703fcf3ce44SJohn Forte icp->conn_oid, value); 1704fcf3ce44SJohn Forte return (ISCSI_STATUS_NEGO_FAIL); 1705fcf3ce44SJohn Forte } 1706fcf3ce44SJohn Forte text = value_end; 1707fcf3ce44SJohn Forte 1708fcf3ce44SJohn Forte } else { 1709fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) " 1710fcf3ce44SJohn Forte "login failed - ignoring login " 1711fcf3ce44SJohn Forte "parameter %s", icp->conn_oid, value); 1712fcf3ce44SJohn Forte text = value_end; 1713fcf3ce44SJohn Forte } 1714fcf3ce44SJohn Forte break; 1715fcf3ce44SJohn Forte default: 1716fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR); 1717fcf3ce44SJohn Forte } 1718fcf3ce44SJohn Forte } 1719fcf3ce44SJohn Forte 1720fcf3ce44SJohn Forte /* 1721fcf3ce44SJohn Forte * iSCSI RFC section 12.14 states that 1722fcf3ce44SJohn Forte * FirstBurstLength is Irrelevant if 1723fcf3ce44SJohn Forte * InitialR2T=Yes and ImmediateData=No. 1724fcf3ce44SJohn Forte * This is a final check to make sure 1725fcf3ce44SJohn Forte * the array didn't make a protocol 1726fcf3ce44SJohn Forte * violation. 1727fcf3ce44SJohn Forte */ 1728fcf3ce44SJohn Forte if ((fbl_irrelevant == B_TRUE) && 1729fcf3ce44SJohn Forte ((icp->conn_params.initial_r2t != B_TRUE) || 1730fcf3ce44SJohn Forte (icp->conn_params.immediate_data != B_FALSE))) { 1731fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login failed - " 1732fcf3ce44SJohn Forte "FirstBurstLength=Irrelevant and (InitialR2T!=Yes or " 1733fcf3ce44SJohn Forte "ImmediateData!=No) - protocol error", icp->conn_oid); 1734fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1735fcf3ce44SJohn Forte } 1736fcf3ce44SJohn Forte 1737fcf3ce44SJohn Forte if (icp->conn_current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE) { 1738fcf3ce44SJohn Forte switch (iscsiAuthClientRecvEnd(auth_client, iscsi_null_callback, 1739fcf3ce44SJohn Forte (void *)isp, NULL)) { 1740fcf3ce44SJohn Forte case iscsiAuthStatusContinue: 1741fcf3ce44SJohn Forte /* 1742fcf3ce44SJohn Forte * continue sending PDUs 1743fcf3ce44SJohn Forte */ 1744fcf3ce44SJohn Forte break; 1745fcf3ce44SJohn Forte 1746fcf3ce44SJohn Forte case iscsiAuthStatusPass: 1747fcf3ce44SJohn Forte break; 1748fcf3ce44SJohn Forte 1749fcf3ce44SJohn Forte case iscsiAuthStatusInProgress: 1750fcf3ce44SJohn Forte /* 1751fcf3ce44SJohn Forte * this should only occur if we were authenticating the 1752fcf3ce44SJohn Forte * target, which we don't do yet, so treat this as an 1753fcf3ce44SJohn Forte * error. 1754fcf3ce44SJohn Forte */ 1755fcf3ce44SJohn Forte case iscsiAuthStatusNoError: 1756fcf3ce44SJohn Forte /* 1757fcf3ce44SJohn Forte * treat this as an error, since we should get a 1758fcf3ce44SJohn Forte * different code 1759fcf3ce44SJohn Forte */ 1760fcf3ce44SJohn Forte case iscsiAuthStatusError: 1761fcf3ce44SJohn Forte case iscsiAuthStatusFail: 1762fcf3ce44SJohn Forte default: 1763fcf3ce44SJohn Forte debug_status = 0; 1764fcf3ce44SJohn Forte 1765fcf3ce44SJohn Forte if (iscsiAuthClientGetDebugStatus(auth_client, 1766fcf3ce44SJohn Forte &debug_status) != iscsiAuthStatusNoError) { 1767fcf3ce44SJohn Forte 1768fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1769fcf3ce44SJohn Forte "failed - authentication failed with " 1770fcf3ce44SJohn Forte "target (%s)", icp->conn_oid, 1771fcf3ce44SJohn Forte iscsiAuthClientDebugStatusToText( 1772fcf3ce44SJohn Forte debug_status)); 1773fcf3ce44SJohn Forte 1774fcf3ce44SJohn Forte } else { 1775fcf3ce44SJohn Forte 1776fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) login " 1777fcf3ce44SJohn Forte "failed - authentication failed with " 1778fcf3ce44SJohn Forte "target", icp->conn_oid); 1779fcf3ce44SJohn Forte 1780fcf3ce44SJohn Forte } 1781fcf3ce44SJohn Forte return (ISCSI_STATUS_AUTHENTICATION_FAILED); 1782fcf3ce44SJohn Forte } 1783fcf3ce44SJohn Forte } 1784fcf3ce44SJohn Forte 1785fcf3ce44SJohn Forte /* 1786fcf3ce44SJohn Forte * record some of the PDU fields for later use 1787fcf3ce44SJohn Forte */ 1788fcf3ce44SJohn Forte isp->sess_tsid = ntohs(ilrhp->tsid); 1789fcf3ce44SJohn Forte isp->sess_expcmdsn = ntohl(ilrhp->expcmdsn); 1790fcf3ce44SJohn Forte isp->sess_maxcmdsn = ntohl(ilrhp->maxcmdsn); 1791fcf3ce44SJohn Forte if (ilrhp->status_class == ISCSI_STATUS_CLASS_SUCCESS) { 1792fcf3ce44SJohn Forte icp->conn_expstatsn = ntohl(ilrhp->statsn) + 1; 1793fcf3ce44SJohn Forte } 1794fcf3ce44SJohn Forte 1795fcf3ce44SJohn Forte if (transit) { 1796fcf3ce44SJohn Forte /* 1797fcf3ce44SJohn Forte * advance to the next stage 1798fcf3ce44SJohn Forte */ 1799fcf3ce44SJohn Forte icp->conn_partial_response = 0; 1800fcf3ce44SJohn Forte icp->conn_current_stage = 1801fcf3ce44SJohn Forte ilrhp->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; 1802fcf3ce44SJohn Forte } else { 1803fcf3ce44SJohn Forte /* 1804fcf3ce44SJohn Forte * we got a partial response, don't advance, more 1805fcf3ce44SJohn Forte * negotiation to do 1806fcf3ce44SJohn Forte */ 1807fcf3ce44SJohn Forte icp->conn_partial_response = 1; 1808fcf3ce44SJohn Forte } 1809fcf3ce44SJohn Forte 1810fcf3ce44SJohn Forte /* 1811fcf3ce44SJohn Forte * this PDU is ok, though the login process 1812fcf3ce44SJohn Forte * may not be done yet 1813fcf3ce44SJohn Forte */ 1814fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 1815fcf3ce44SJohn Forte } 1816fcf3ce44SJohn Forte 1817fcf3ce44SJohn Forte /* 1818fcf3ce44SJohn Forte * iscsi_add_text - caller is assumed to be well-behaved and passing NUL 1819fcf3ce44SJohn Forte * terminated strings 1820fcf3ce44SJohn Forte */ 1821fcf3ce44SJohn Forte int 182230e7468fSPeter Dunlap iscsi_add_text(idm_pdu_t *text_pdu, int max_data_length, 1823fcf3ce44SJohn Forte char *param, char *value) 1824fcf3ce44SJohn Forte { 1825fcf3ce44SJohn Forte int param_len = 0; 1826fcf3ce44SJohn Forte int value_len = 0; 1827fcf3ce44SJohn Forte int length = 0; 1828fcf3ce44SJohn Forte int pdu_length = 0; 1829fcf3ce44SJohn Forte char *text = NULL; 1830fcf3ce44SJohn Forte char *end = NULL; 1831fcf3ce44SJohn Forte 183230e7468fSPeter Dunlap ASSERT(text_pdu != NULL); 1833fcf3ce44SJohn Forte ASSERT(param != NULL); 1834fcf3ce44SJohn Forte ASSERT(value != NULL); 1835fcf3ce44SJohn Forte 1836fcf3ce44SJohn Forte param_len = strlen(param); 1837fcf3ce44SJohn Forte value_len = strlen(value); 1838fcf3ce44SJohn Forte /* param, separator, value, and trailing NULL */ 1839fcf3ce44SJohn Forte length = param_len + 1 + value_len + 1; 184030e7468fSPeter Dunlap pdu_length = text_pdu->isp_datalen; 184130e7468fSPeter Dunlap text = (char *)text_pdu->isp_data + pdu_length; 184230e7468fSPeter Dunlap end = (char *)text_pdu->isp_data + max_data_length; 1843fcf3ce44SJohn Forte pdu_length += length; 1844fcf3ce44SJohn Forte 1845fcf3ce44SJohn Forte if (text + length >= end) { 1846fcf3ce44SJohn Forte return (0); 1847fcf3ce44SJohn Forte } 1848fcf3ce44SJohn Forte 1849fcf3ce44SJohn Forte /* param */ 1850fcf3ce44SJohn Forte (void) strncpy(text, param, param_len); 1851fcf3ce44SJohn Forte text += param_len; 1852fcf3ce44SJohn Forte 1853fcf3ce44SJohn Forte /* separator */ 1854fcf3ce44SJohn Forte *text++ = ISCSI_TEXT_SEPARATOR; 1855fcf3ce44SJohn Forte 1856fcf3ce44SJohn Forte /* value */ 1857fcf3ce44SJohn Forte (void) strncpy(text, value, value_len); 1858fcf3ce44SJohn Forte text += value_len; 1859fcf3ce44SJohn Forte 1860fcf3ce44SJohn Forte /* NULL */ 1861fcf3ce44SJohn Forte *text++ = '\0'; 1862fcf3ce44SJohn Forte 1863fcf3ce44SJohn Forte /* update the length in the PDU header */ 186430e7468fSPeter Dunlap text_pdu->isp_datalen = pdu_length; 186530e7468fSPeter Dunlap hton24(text_pdu->isp_hdr->dlength, pdu_length); 1866fcf3ce44SJohn Forte 1867fcf3ce44SJohn Forte return (1); 1868fcf3ce44SJohn Forte } 1869fcf3ce44SJohn Forte 1870fcf3ce44SJohn Forte /* 1871fcf3ce44SJohn Forte * iscsi_get_next_text - get the next line of text from the given data 1872fcf3ce44SJohn Forte * buffer. This function searches from the address given for the 1873fcf3ce44SJohn Forte * curr_text parameter. If curr_text_parameter is NULL return first 1874fcf3ce44SJohn Forte * line in buffer. The return value is the address of the next line 1875fcf3ce44SJohn Forte * based upon where curr_text is located. 1876fcf3ce44SJohn Forte * 1877fcf3ce44SJohn Forte */ 1878fcf3ce44SJohn Forte char * 1879fcf3ce44SJohn Forte iscsi_get_next_text(char *data, int max_data_length, char *curr_text) 1880fcf3ce44SJohn Forte { 1881fcf3ce44SJohn Forte char *curr_data; 1882fcf3ce44SJohn Forte 1883fcf3ce44SJohn Forte ASSERT(data != NULL); 1884fcf3ce44SJohn Forte 1885fcf3ce44SJohn Forte /* check if any data exists, if not return */ 1886fcf3ce44SJohn Forte if (max_data_length == 0) { 1887fcf3ce44SJohn Forte return (NULL); 1888fcf3ce44SJohn Forte } 1889fcf3ce44SJohn Forte 1890fcf3ce44SJohn Forte /* handle first call to this function */ 1891fcf3ce44SJohn Forte if (curr_text == NULL) { 1892fcf3ce44SJohn Forte return (data); 1893fcf3ce44SJohn Forte } 1894fcf3ce44SJohn Forte 1895fcf3ce44SJohn Forte /* move to next text string */ 1896fcf3ce44SJohn Forte curr_data = curr_text; 1897fcf3ce44SJohn Forte while ((curr_data < (data + max_data_length)) && *curr_data) { 1898fcf3ce44SJohn Forte curr_data++; 1899fcf3ce44SJohn Forte } 1900fcf3ce44SJohn Forte curr_data++; /* go past the NULL to the next entry */ 1901fcf3ce44SJohn Forte 1902fcf3ce44SJohn Forte /* check whether data end reached */ 1903fcf3ce44SJohn Forte if (curr_data >= (data + max_data_length)) { 1904fcf3ce44SJohn Forte return (NULL); 1905fcf3ce44SJohn Forte } 1906fcf3ce44SJohn Forte 1907fcf3ce44SJohn Forte return (curr_data); 1908fcf3ce44SJohn Forte } 1909fcf3ce44SJohn Forte 1910fcf3ce44SJohn Forte 1911fcf3ce44SJohn Forte /* 1912fcf3ce44SJohn Forte * iscsi_find_key_value - 1913fcf3ce44SJohn Forte * 1914fcf3ce44SJohn Forte */ 1915fcf3ce44SJohn Forte static int 1916fcf3ce44SJohn Forte iscsi_find_key_value(char *param, char *ihp, char *pdu_end, 1917fcf3ce44SJohn Forte char **value_start, char **value_end) 1918fcf3ce44SJohn Forte { 1919fcf3ce44SJohn Forte char *str = param; 1920fcf3ce44SJohn Forte char *text = ihp; 1921fcf3ce44SJohn Forte char *value = NULL; 1922fcf3ce44SJohn Forte 1923fcf3ce44SJohn Forte if (value_start) 1924fcf3ce44SJohn Forte *value_start = NULL; 1925fcf3ce44SJohn Forte if (value_end) 1926fcf3ce44SJohn Forte *value_end = NULL; 1927fcf3ce44SJohn Forte 1928fcf3ce44SJohn Forte /* 1929fcf3ce44SJohn Forte * make sure they contain the same bytes 1930fcf3ce44SJohn Forte */ 1931fcf3ce44SJohn Forte while (*str) { 1932fcf3ce44SJohn Forte if (text >= pdu_end) { 1933fcf3ce44SJohn Forte return (0); 1934fcf3ce44SJohn Forte } 1935fcf3ce44SJohn Forte if (*text == '\0') { 1936fcf3ce44SJohn Forte return (0); 1937fcf3ce44SJohn Forte } 1938fcf3ce44SJohn Forte if (*str != *text) { 1939fcf3ce44SJohn Forte return (0); 1940fcf3ce44SJohn Forte } 1941fcf3ce44SJohn Forte str++; 1942fcf3ce44SJohn Forte text++; 1943fcf3ce44SJohn Forte } 1944fcf3ce44SJohn Forte 1945fcf3ce44SJohn Forte if ((text >= pdu_end) || 1946fcf3ce44SJohn Forte (*text == '\0') || 1947fcf3ce44SJohn Forte (*text != ISCSI_TEXT_SEPARATOR)) { 1948fcf3ce44SJohn Forte return (0); 1949fcf3ce44SJohn Forte } 1950fcf3ce44SJohn Forte 1951fcf3ce44SJohn Forte /* 1952fcf3ce44SJohn Forte * find the value 1953fcf3ce44SJohn Forte */ 1954fcf3ce44SJohn Forte value = text + 1; 1955fcf3ce44SJohn Forte 1956fcf3ce44SJohn Forte /* 1957fcf3ce44SJohn Forte * find the end of the value 1958fcf3ce44SJohn Forte */ 1959fcf3ce44SJohn Forte while ((text < pdu_end) && (*text)) 1960fcf3ce44SJohn Forte text++; 1961fcf3ce44SJohn Forte 1962fcf3ce44SJohn Forte if (value_start) 1963fcf3ce44SJohn Forte *value_start = value; 1964fcf3ce44SJohn Forte if (value_end) 1965fcf3ce44SJohn Forte *value_end = text; 1966fcf3ce44SJohn Forte 1967fcf3ce44SJohn Forte return (1); 1968fcf3ce44SJohn Forte } 1969fcf3ce44SJohn Forte 1970fcf3ce44SJohn Forte 1971fcf3ce44SJohn Forte /* 1972fcf3ce44SJohn Forte * iscsi_update_address - This function is used on a login redirection. 1973fcf3ce44SJohn Forte * During the login redirection we are asked to switch to an IP address 1974fcf3ce44SJohn Forte * port different than the one we were logging into. 1975fcf3ce44SJohn Forte */ 1976fcf3ce44SJohn Forte static iscsi_status_t 1977fcf3ce44SJohn Forte iscsi_update_address(iscsi_conn_t *icp, char *in) 1978fcf3ce44SJohn Forte { 1979fcf3ce44SJohn Forte char *addr_str, *port_str, *tpgt_str; 1980fcf3ce44SJohn Forte int type; 1981fcf3ce44SJohn Forte struct hostent *hptr; 1982fcf3ce44SJohn Forte unsigned long tmp; 1983fcf3ce44SJohn Forte int error_num; 1984fcf3ce44SJohn Forte int port; 1985fcf3ce44SJohn Forte 1986fcf3ce44SJohn Forte ASSERT(icp != NULL); 1987fcf3ce44SJohn Forte ASSERT(in != NULL); 1988fcf3ce44SJohn Forte 1989fcf3ce44SJohn Forte /* parse login redirection response */ 1990fcf3ce44SJohn Forte if (parse_addr_port_tpgt(in, &addr_str, &type, 1991fcf3ce44SJohn Forte &port_str, &tpgt_str) == B_FALSE) { 1992fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1993fcf3ce44SJohn Forte } 1994fcf3ce44SJohn Forte 1995fcf3ce44SJohn Forte /* convert addr_str */ 1996fcf3ce44SJohn Forte hptr = kgetipnodebyname(addr_str, type, AI_ALL, &error_num); 1997fcf3ce44SJohn Forte if (!hptr) { 1998fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 1999fcf3ce44SJohn Forte } 2000fcf3ce44SJohn Forte 2001fcf3ce44SJohn Forte /* convert port_str */ 2002fcf3ce44SJohn Forte if (port_str != NULL) { 2003fcf3ce44SJohn Forte (void) ddi_strtoul(port_str, NULL, 0, &tmp); 2004fcf3ce44SJohn Forte port = (int)tmp; 2005fcf3ce44SJohn Forte } else { 2006fcf3ce44SJohn Forte port = ISCSI_LISTEN_PORT; 2007fcf3ce44SJohn Forte } 2008fcf3ce44SJohn Forte 2009fcf3ce44SJohn Forte iscsid_addr_to_sockaddr(hptr->h_length, *hptr->h_addr_list, 2010fcf3ce44SJohn Forte port, &icp->conn_curr_addr.sin); 2011fcf3ce44SJohn Forte 2012fcf3ce44SJohn Forte kfreehostent(hptr); 2013fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 2014fcf3ce44SJohn Forte } 2015fcf3ce44SJohn Forte 201630e7468fSPeter Dunlap void 201730e7468fSPeter Dunlap iscsi_login_update_state(iscsi_conn_t *icp, iscsi_login_state_t next_state) 201830e7468fSPeter Dunlap { 201930e7468fSPeter Dunlap mutex_enter(&icp->conn_login_mutex); 202030e7468fSPeter Dunlap (void) iscsi_login_update_state_locked(icp, next_state); 202130e7468fSPeter Dunlap mutex_exit(&icp->conn_login_mutex); 202230e7468fSPeter Dunlap } 202330e7468fSPeter Dunlap 202430e7468fSPeter Dunlap void 202530e7468fSPeter Dunlap iscsi_login_update_state_locked(iscsi_conn_t *icp, 202630e7468fSPeter Dunlap iscsi_login_state_t next_state) 202730e7468fSPeter Dunlap { 202830e7468fSPeter Dunlap ASSERT(mutex_owned(&icp->conn_login_mutex)); 202930e7468fSPeter Dunlap next_state = (next_state > LOGIN_MAX) ? LOGIN_MAX : next_state; 203030e7468fSPeter Dunlap idm_sm_audit_state_change(&icp->conn_state_audit, 203130e7468fSPeter Dunlap SAS_ISCSI_LOGIN, icp->conn_login_state, next_state); 203230e7468fSPeter Dunlap 203330e7468fSPeter Dunlap ISCSI_LOGIN_LOG(CE_NOTE, "iscsi_login_update_state conn %p %d -> %d", 203430e7468fSPeter Dunlap (void *)icp, icp->conn_login_state, next_state); 203530e7468fSPeter Dunlap 203630e7468fSPeter Dunlap icp->conn_login_state = next_state; 203730e7468fSPeter Dunlap cv_broadcast(&icp->conn_login_cv); 203830e7468fSPeter Dunlap } 203930e7468fSPeter Dunlap 204030e7468fSPeter Dunlap 2041fcf3ce44SJohn Forte 2042fcf3ce44SJohn Forte /* 2043fcf3ce44SJohn Forte * iscsi_null_callback - This callback may be used under certain 2044fcf3ce44SJohn Forte * conditions when authenticating a target, but I'm not sure what 2045fcf3ce44SJohn Forte * we need to do here. 2046fcf3ce44SJohn Forte */ 2047fcf3ce44SJohn Forte /* ARGSUSED */ 2048fcf3ce44SJohn Forte static void 2049fcf3ce44SJohn Forte iscsi_null_callback(void *user_handle, void *message_handle, int auth_status) 2050fcf3ce44SJohn Forte { 2051fcf3ce44SJohn Forte } 2052fcf3ce44SJohn Forte 2053fcf3ce44SJohn Forte 2054fcf3ce44SJohn Forte /* 2055fcf3ce44SJohn Forte * iscsi_login_failure_str - 2056fcf3ce44SJohn Forte * 2057fcf3ce44SJohn Forte */ 2058fcf3ce44SJohn Forte static char * 2059fcf3ce44SJohn Forte iscsi_login_failure_str(uchar_t status_class, uchar_t status_detail) 2060fcf3ce44SJohn Forte { 2061fcf3ce44SJohn Forte switch (status_class) { 2062fcf3ce44SJohn Forte case 0x00: 2063fcf3ce44SJohn Forte switch (status_detail) { 2064fcf3ce44SJohn Forte case 0x00: 2065fcf3ce44SJohn Forte return ("Login is proceeding okay."); 2066fcf3ce44SJohn Forte default: 2067fcf3ce44SJohn Forte break; 2068fcf3ce44SJohn Forte } 2069fcf3ce44SJohn Forte case 0x01: 2070fcf3ce44SJohn Forte switch (status_detail) { 2071fcf3ce44SJohn Forte case 0x01: 2072fcf3ce44SJohn Forte return ("Requested ITN has moved temporarily to " 2073fcf3ce44SJohn Forte "the address provided."); 2074fcf3ce44SJohn Forte case 0x02: 2075fcf3ce44SJohn Forte return ("Requested ITN has moved permanently to " 2076fcf3ce44SJohn Forte "the address provided."); 2077fcf3ce44SJohn Forte default: 2078fcf3ce44SJohn Forte break; 2079fcf3ce44SJohn Forte } 2080fcf3ce44SJohn Forte case 0x02: 2081fcf3ce44SJohn Forte switch (status_detail) { 2082fcf3ce44SJohn Forte case 0x00: 2083fcf3ce44SJohn Forte return ("Miscellaneous iSCSI initiator errors."); 2084fcf3ce44SJohn Forte case 0x01: 2085fcf3ce44SJohn Forte return ("Initiator could not be successfully " 2086fcf3ce44SJohn Forte "authenticated."); 2087fcf3ce44SJohn Forte case 0x02: 2088fcf3ce44SJohn Forte return ("Initiator is not allowed access to the " 2089fcf3ce44SJohn Forte "given target."); 2090fcf3ce44SJohn Forte case 0x03: 2091fcf3ce44SJohn Forte return ("Requested ITN does not exist at this " 2092fcf3ce44SJohn Forte "address."); 2093fcf3ce44SJohn Forte case 0x04: 2094fcf3ce44SJohn Forte return ("Requested ITN has been removed and no " 2095fcf3ce44SJohn Forte "forwarding address is provided."); 2096fcf3ce44SJohn Forte case 0x05: 2097fcf3ce44SJohn Forte return ("Requested iSCSI version range is not " 2098fcf3ce44SJohn Forte "supported by the target."); 2099fcf3ce44SJohn Forte case 0x06: 2100fcf3ce44SJohn Forte return ("No more connections can be accepted on " 2101fcf3ce44SJohn Forte "this Session ID (SSID)."); 2102fcf3ce44SJohn Forte case 0x07: 2103fcf3ce44SJohn Forte return ("Missing parameters (e.g., iSCSI initiator " 2104fcf3ce44SJohn Forte "and/or target name)."); 2105fcf3ce44SJohn Forte case 0x08: 2106fcf3ce44SJohn Forte return ("Target does not support session spanning " 2107fcf3ce44SJohn Forte "to this connection (address)."); 2108fcf3ce44SJohn Forte case 0x09: 2109fcf3ce44SJohn Forte return ("Target does not support this type of " 2110fcf3ce44SJohn Forte "session or not from this initiator."); 2111fcf3ce44SJohn Forte case 0x0A: 2112fcf3ce44SJohn Forte return ("Attempt to add a connection to a " 2113fcf3ce44SJohn Forte "nonexistent session."); 2114fcf3ce44SJohn Forte case 0x0B: 2115fcf3ce44SJohn Forte return ("Invalid request type during login."); 2116fcf3ce44SJohn Forte default: 2117fcf3ce44SJohn Forte break; 2118fcf3ce44SJohn Forte } 2119fcf3ce44SJohn Forte case 0x03: 2120fcf3ce44SJohn Forte switch (status_detail) { 2121fcf3ce44SJohn Forte case 0x00: 2122fcf3ce44SJohn Forte return ("Target hardware or software error."); 2123fcf3ce44SJohn Forte case 0x01: 2124fcf3ce44SJohn Forte return ("iSCSI service or target is not currently " 2125fcf3ce44SJohn Forte "operational."); 2126fcf3ce44SJohn Forte case 0x02: 2127fcf3ce44SJohn Forte return ("Target has insufficient session, connection " 2128fcf3ce44SJohn Forte "or other resources."); 2129fcf3ce44SJohn Forte default: 2130fcf3ce44SJohn Forte break; 2131fcf3ce44SJohn Forte } 2132fcf3ce44SJohn Forte } 2133fcf3ce44SJohn Forte return ("Unknown login response received."); 2134fcf3ce44SJohn Forte } 2135fcf3ce44SJohn Forte 2136fcf3ce44SJohn Forte 2137fcf3ce44SJohn Forte /* 2138fcf3ce44SJohn Forte * iscsi_login_connect - 2139fcf3ce44SJohn Forte */ 2140fcf3ce44SJohn Forte static iscsi_status_t 2141fcf3ce44SJohn Forte iscsi_login_connect(iscsi_conn_t *icp) 2142fcf3ce44SJohn Forte { 2143fcf3ce44SJohn Forte iscsi_hba_t *ihp; 2144fcf3ce44SJohn Forte iscsi_sess_t *isp; 2145fcf3ce44SJohn Forte struct sockaddr *addr; 214630e7468fSPeter Dunlap idm_conn_req_t cr; 214730e7468fSPeter Dunlap idm_status_t rval; 2148d3d50737SRafael Vanoni clock_t lbolt; 2149fcf3ce44SJohn Forte 2150fcf3ce44SJohn Forte ASSERT(icp != NULL); 2151fcf3ce44SJohn Forte isp = icp->conn_sess; 2152fcf3ce44SJohn Forte ASSERT(isp != NULL); 2153fcf3ce44SJohn Forte ihp = isp->sess_hba; 2154fcf3ce44SJohn Forte ASSERT(ihp != NULL); 2155fcf3ce44SJohn Forte addr = &icp->conn_curr_addr.sin; 2156fcf3ce44SJohn Forte 2157fcf3ce44SJohn Forte /* Make sure that scope_id is zero if it is an IPv6 address */ 2158fcf3ce44SJohn Forte if (addr->sa_family == AF_INET6) { 2159fcf3ce44SJohn Forte ((struct sockaddr_in6 *)addr)->sin6_scope_id = 0; 2160fcf3ce44SJohn Forte } 2161fcf3ce44SJohn Forte 216230e7468fSPeter Dunlap /* delay the connect process if required */ 216330e7468fSPeter Dunlap lbolt = ddi_get_lbolt(); 216430e7468fSPeter Dunlap if (lbolt < icp->conn_login_min) { 2165aff4bce5Syi zhang - Sun Microsystems - Beijing China if (icp->conn_login_max < icp->conn_login_min) { 2166aff4bce5Syi zhang - Sun Microsystems - Beijing China delay(icp->conn_login_max - lbolt); 2167aff4bce5Syi zhang - Sun Microsystems - Beijing China } else { 216830e7468fSPeter Dunlap delay(icp->conn_login_min - lbolt); 216930e7468fSPeter Dunlap } 2170aff4bce5Syi zhang - Sun Microsystems - Beijing China } 2171fcf3ce44SJohn Forte 217230e7468fSPeter Dunlap /* Create IDM connection context */ 217330e7468fSPeter Dunlap cr.cr_domain = addr->sa_family; 217430e7468fSPeter Dunlap cr.cr_type = SOCK_STREAM; 217530e7468fSPeter Dunlap cr.cr_protocol = 0; 217630e7468fSPeter Dunlap cr.cr_bound = icp->conn_bound; 217730e7468fSPeter Dunlap cr.cr_li = icp->conn_sess->sess_hba->hba_li; 217830e7468fSPeter Dunlap cr.icr_conn_ops.icb_rx_misc = &iscsi_rx_misc_pdu; 217930e7468fSPeter Dunlap cr.icr_conn_ops.icb_rx_error = &iscsi_rx_error_pdu; 218030e7468fSPeter Dunlap cr.icr_conn_ops.icb_rx_scsi_rsp = &iscsi_rx_scsi_rsp; 218130e7468fSPeter Dunlap cr.icr_conn_ops.icb_client_notify = &iscsi_client_notify; 218230e7468fSPeter Dunlap cr.icr_conn_ops.icb_build_hdr = &iscsi_build_hdr; 218330e7468fSPeter Dunlap cr.icr_conn_ops.icb_task_aborted = &iscsi_task_aborted; 218430e7468fSPeter Dunlap bcopy(addr, &cr.cr_ini_dst_addr, 218530e7468fSPeter Dunlap sizeof (cr.cr_ini_dst_addr)); 218630e7468fSPeter Dunlap bcopy(&icp->conn_bound_addr, &cr.cr_bound_addr, 218730e7468fSPeter Dunlap sizeof (cr.cr_bound_addr)); 2188dedec472SJack Meng if (isp->sess_boot == B_TRUE) { 2189dedec472SJack Meng cr.cr_boot_conn = B_TRUE; 2190dedec472SJack Meng } else { 2191dedec472SJack Meng cr.cr_boot_conn = B_FALSE; 2192dedec472SJack Meng } 219330e7468fSPeter Dunlap 219430e7468fSPeter Dunlap /* 219530e7468fSPeter Dunlap * Allocate IDM connection context 219630e7468fSPeter Dunlap */ 219730e7468fSPeter Dunlap rval = idm_ini_conn_create(&cr, &icp->conn_ic); 219830e7468fSPeter Dunlap if (rval != IDM_STATUS_SUCCESS) { 219930e7468fSPeter Dunlap return (ISCSI_STATUS_LOGIN_FAILED); 220030e7468fSPeter Dunlap } 220130e7468fSPeter Dunlap 220230e7468fSPeter Dunlap icp->conn_ic->ic_handle = icp; 220330e7468fSPeter Dunlap 220430e7468fSPeter Dunlap /* 220530e7468fSPeter Dunlap * About to initiate connect, reset login state. 220630e7468fSPeter Dunlap */ 220730e7468fSPeter Dunlap iscsi_login_update_state(icp, LOGIN_START); 220830e7468fSPeter Dunlap 220930e7468fSPeter Dunlap /* 221030e7468fSPeter Dunlap * Make sure the connection doesn't go away until we are done with it. 221130e7468fSPeter Dunlap * This hold will prevent us from receiving a CN_CONNECT_DESTROY 221230e7468fSPeter Dunlap * notification on this connection until we are ready. 221330e7468fSPeter Dunlap */ 221430e7468fSPeter Dunlap idm_conn_hold(icp->conn_ic); 221530e7468fSPeter Dunlap 221630e7468fSPeter Dunlap /* 2217aff4bce5Syi zhang - Sun Microsystems - Beijing China * When iSCSI initiator to target IO timeout or connection failure 2218aff4bce5Syi zhang - Sun Microsystems - Beijing China * Connection retry is needed for normal operational session. 2219aff4bce5Syi zhang - Sun Microsystems - Beijing China */ 2220aff4bce5Syi zhang - Sun Microsystems - Beijing China if ((icp->conn_sess->sess_type == ISCSI_SESS_TYPE_NORMAL) && 2221aff4bce5Syi zhang - Sun Microsystems - Beijing China ((icp->conn_state == ISCSI_CONN_STATE_FAILED) || 2222aff4bce5Syi zhang - Sun Microsystems - Beijing China (icp->conn_state == ISCSI_CONN_STATE_POLLING))) { 2223aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.nonblock_socket = B_TRUE; 2224aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_max = 2225aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_login_max; 2226aff4bce5Syi zhang - Sun Microsystems - Beijing China if (icp->conn_state == ISCSI_CONN_STATE_POLLING) { 2227aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_interval = 2228aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_tunable_params.polling_login_delay; 2229aff4bce5Syi zhang - Sun Microsystems - Beijing China } else { 2230aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_interval = 2231aff4bce5Syi zhang - Sun Microsystems - Beijing China ISCSI_LOGIN_RETRY_DELAY; 2232aff4bce5Syi zhang - Sun Microsystems - Beijing China } 2233aff4bce5Syi zhang - Sun Microsystems - Beijing China 2234aff4bce5Syi zhang - Sun Microsystems - Beijing China } else { 2235aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.nonblock_socket = B_FALSE; 2236aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_max = 0; 2237aff4bce5Syi zhang - Sun Microsystems - Beijing China icp->conn_ic->ic_conn_params.conn_login_interval = 0; 2238aff4bce5Syi zhang - Sun Microsystems - Beijing China } 2239aff4bce5Syi zhang - Sun Microsystems - Beijing China /* 224030e7468fSPeter Dunlap * Attempt connection. Upon return we will either be ready to 224130e7468fSPeter Dunlap * login or disconnected. If idm_ini_conn_connect fails we 224230e7468fSPeter Dunlap * will eventually receive a CN_CONNECT_DESTROY at which point 224330e7468fSPeter Dunlap * we will destroy the connection allocated above (so there 224430e7468fSPeter Dunlap * is no need to explicitly free it here). 224530e7468fSPeter Dunlap */ 224630e7468fSPeter Dunlap rval = idm_ini_conn_connect(icp->conn_ic); 224730e7468fSPeter Dunlap 224830e7468fSPeter Dunlap if (rval != IDM_STATUS_SUCCESS) { 2249fcf3ce44SJohn Forte cmn_err(CE_NOTE, "iscsi connection(%u) unable to " 2250fcf3ce44SJohn Forte "connect to target %s", icp->conn_oid, 2251fcf3ce44SJohn Forte icp->conn_sess->sess_name); 225230e7468fSPeter Dunlap idm_conn_rele(icp->conn_ic); 2253fcf3ce44SJohn Forte } 2254fcf3ce44SJohn Forte 225530e7468fSPeter Dunlap return (rval == IDM_STATUS_SUCCESS ? 225630e7468fSPeter Dunlap ISCSI_STATUS_SUCCESS : ISCSI_STATUS_INTERNAL_ERROR); 2257fcf3ce44SJohn Forte } 2258fcf3ce44SJohn Forte 225930e7468fSPeter Dunlap /* 226030e7468fSPeter Dunlap * iscsi_login_disconnect 226130e7468fSPeter Dunlap */ 226230e7468fSPeter Dunlap static void 226330e7468fSPeter Dunlap iscsi_login_disconnect(iscsi_conn_t *icp) 226430e7468fSPeter Dunlap { 226530e7468fSPeter Dunlap /* Tell IDM to disconnect is if we are not already disconnect */ 226630e7468fSPeter Dunlap idm_ini_conn_disconnect_sync(icp->conn_ic); 226730e7468fSPeter Dunlap 226830e7468fSPeter Dunlap /* 226930e7468fSPeter Dunlap * The function above may return before the CN_CONNECT_LOST 227030e7468fSPeter Dunlap * notification. Wait for it. 227130e7468fSPeter Dunlap */ 227230e7468fSPeter Dunlap mutex_enter(&icp->conn_state_mutex); 227330e7468fSPeter Dunlap while (icp->conn_state_idm_connected) 227430e7468fSPeter Dunlap cv_wait(&icp->conn_state_change, 227530e7468fSPeter Dunlap &icp->conn_state_mutex); 227630e7468fSPeter Dunlap mutex_exit(&icp->conn_state_mutex); 227730e7468fSPeter Dunlap } 227830e7468fSPeter Dunlap 227930e7468fSPeter Dunlap /* 228030e7468fSPeter Dunlap * iscsi_notice_key_values - Create an nvlist containing the values 228130e7468fSPeter Dunlap * that have been negotiated for this connection and pass them down to 228230e7468fSPeter Dunlap * IDM so it can pick up any values that are important. 228330e7468fSPeter Dunlap */ 228430e7468fSPeter Dunlap static void 228530e7468fSPeter Dunlap iscsi_notice_key_values(iscsi_conn_t *icp) 228630e7468fSPeter Dunlap { 228730e7468fSPeter Dunlap nvlist_t *neg_nvl; 228830e7468fSPeter Dunlap int rc; 228930e7468fSPeter Dunlap 229030e7468fSPeter Dunlap rc = nvlist_alloc(&neg_nvl, NV_UNIQUE_NAME, KM_SLEEP); 229130e7468fSPeter Dunlap ASSERT(rc == 0); 229230e7468fSPeter Dunlap 229330e7468fSPeter Dunlap /* Only crc32c is supported so the digest logic is simple */ 229430e7468fSPeter Dunlap if (icp->conn_params.header_digest) { 229530e7468fSPeter Dunlap rc = nvlist_add_string(neg_nvl, "HeaderDigest", "crc32c"); 229630e7468fSPeter Dunlap } else { 229730e7468fSPeter Dunlap rc = nvlist_add_string(neg_nvl, "HeaderDigest", "none"); 229830e7468fSPeter Dunlap } 229930e7468fSPeter Dunlap ASSERT(rc == 0); 230030e7468fSPeter Dunlap 230130e7468fSPeter Dunlap if (icp->conn_params.data_digest) { 230230e7468fSPeter Dunlap rc = nvlist_add_string(neg_nvl, "DataDigest", "crc32c"); 230330e7468fSPeter Dunlap } else { 230430e7468fSPeter Dunlap rc = nvlist_add_string(neg_nvl, "DataDigest", "none"); 230530e7468fSPeter Dunlap } 230630e7468fSPeter Dunlap ASSERT(rc == 0); 230730e7468fSPeter Dunlap 230830e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "MaxRecvDataSegmentLength", 230930e7468fSPeter Dunlap (uint64_t)icp->conn_params.max_recv_data_seg_len); 231030e7468fSPeter Dunlap ASSERT(rc == 0); 231130e7468fSPeter Dunlap 231230e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "MaxBurstLength", 231330e7468fSPeter Dunlap (uint64_t)icp->conn_params.max_burst_length); 231430e7468fSPeter Dunlap ASSERT(rc == 0); 231530e7468fSPeter Dunlap 231630e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "MaxOutstandingR2T", 231730e7468fSPeter Dunlap (uint64_t)icp->conn_params.max_outstanding_r2t); 231830e7468fSPeter Dunlap ASSERT(rc == 0); 231930e7468fSPeter Dunlap 232030e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "ErrorRecoveryLevel", 232130e7468fSPeter Dunlap (uint64_t)icp->conn_params.error_recovery_level); 232230e7468fSPeter Dunlap ASSERT(rc == 0); 232330e7468fSPeter Dunlap 232430e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "DefaultTime2Wait", 232530e7468fSPeter Dunlap (uint64_t)icp->conn_params.default_time_to_wait); 232630e7468fSPeter Dunlap ASSERT(rc == 0); 232730e7468fSPeter Dunlap 232830e7468fSPeter Dunlap rc = nvlist_add_uint64(neg_nvl, "DefaultTime2Retain", 232930e7468fSPeter Dunlap (uint64_t)icp->conn_params.default_time_to_retain); 233030e7468fSPeter Dunlap ASSERT(rc == 0); 233130e7468fSPeter Dunlap 233230e7468fSPeter Dunlap /* Pass the list to IDM to examine, then free it */ 233330e7468fSPeter Dunlap idm_notice_key_values(icp->conn_ic, neg_nvl); 233430e7468fSPeter Dunlap nvlist_free(neg_nvl); 2335fcf3ce44SJohn Forte } 2336