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