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