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 2008 Sun Microsystems, Inc. All rights reserved. 23fcf3ce44SJohn Forte * Use is subject to license terms. 24fcf3ce44SJohn Forte * 25fcf3ce44SJohn Forte * iSCSI Software Initiator 26fcf3ce44SJohn Forte */ 27fcf3ce44SJohn Forte 28fcf3ce44SJohn Forte /* 29fcf3ce44SJohn Forte * Framework interface routines for iSCSI 30fcf3ce44SJohn Forte */ 31fcf3ce44SJohn Forte #include "iscsi.h" /* main header */ 32fcf3ce44SJohn Forte #include <sys/scsi/adapters/iscsi_if.h> /* ioctl interfaces */ 33fcf3ce44SJohn Forte /* protocol structs and defines */ 34fcf3ce44SJohn Forte #include <sys/scsi/adapters/iscsi_protocol.h> 35fcf3ce44SJohn Forte #include "persistent.h" 36fcf3ce44SJohn Forte #include <sys/scsi/adapters/iscsi_door.h> 37fcf3ce44SJohn Forte #include "iscsi_targetparam.h" 38fcf3ce44SJohn Forte #include <sys/strsubr.h> 39fcf3ce44SJohn Forte #include <sys/socketvar.h> 40*6cefaae1SJack Meng #include <sys/bootprops.h> 41*6cefaae1SJack Meng 42*6cefaae1SJack Meng extern ib_boot_prop_t *iscsiboot_prop; 43fcf3ce44SJohn Forte 44fcf3ce44SJohn Forte static iscsi_status_t iscsi_create_sendtgts_list(iscsi_conn_t *icp, 45fcf3ce44SJohn Forte char *data, int data_len, iscsi_sendtgts_list_t *stl); 46fcf3ce44SJohn Forte 47fcf3ce44SJohn Forte /* 48fcf3ce44SJohn Forte * iscsi_ioctl_copyin - 49fcf3ce44SJohn Forte */ 50fcf3ce44SJohn Forte void * 51fcf3ce44SJohn Forte iscsi_ioctl_copyin(caddr_t arg, int mode, size_t size) 52fcf3ce44SJohn Forte { 53fcf3ce44SJohn Forte void *data = NULL; 54fcf3ce44SJohn Forte 55fcf3ce44SJohn Forte ASSERT(arg != NULL); 56fcf3ce44SJohn Forte ASSERT(size != 0); 57fcf3ce44SJohn Forte 58fcf3ce44SJohn Forte data = kmem_alloc(size, KM_SLEEP); 59fcf3ce44SJohn Forte 60fcf3ce44SJohn Forte if (ddi_copyin(arg, data, size, mode) != 0) { 61fcf3ce44SJohn Forte kmem_free(data, size); 62fcf3ce44SJohn Forte data = NULL; 63fcf3ce44SJohn Forte } 64fcf3ce44SJohn Forte return (data); 65fcf3ce44SJohn Forte } 66fcf3ce44SJohn Forte 67fcf3ce44SJohn Forte /* 68fcf3ce44SJohn Forte * iscsi_ioctl_copyout - 69fcf3ce44SJohn Forte */ 70fcf3ce44SJohn Forte int 71fcf3ce44SJohn Forte iscsi_ioctl_copyout(void *data, size_t size, caddr_t arg, int mode) 72fcf3ce44SJohn Forte { 73fcf3ce44SJohn Forte int rtn; 74fcf3ce44SJohn Forte 75fcf3ce44SJohn Forte rtn = EFAULT; 76fcf3ce44SJohn Forte if (ddi_copyout(data, arg, size, mode) == 0) { 77fcf3ce44SJohn Forte rtn = 0; 78fcf3ce44SJohn Forte } 79fcf3ce44SJohn Forte kmem_free(data, size); 80fcf3ce44SJohn Forte return (rtn); 81fcf3ce44SJohn Forte } 82fcf3ce44SJohn Forte 83fcf3ce44SJohn Forte /* 84fcf3ce44SJohn Forte * iscsi_conn_list_get_copyin - 85fcf3ce44SJohn Forte */ 86fcf3ce44SJohn Forte iscsi_conn_list_t * 87fcf3ce44SJohn Forte iscsi_ioctl_conn_oid_list_get_copyin(caddr_t arg, int mode) 88fcf3ce44SJohn Forte { 89fcf3ce44SJohn Forte iscsi_conn_list_t *cl_tmp; 90fcf3ce44SJohn Forte iscsi_conn_list_t *cl = NULL; 91fcf3ce44SJohn Forte size_t alloc_len; 92fcf3ce44SJohn Forte 93fcf3ce44SJohn Forte ASSERT(arg != NULL); 94fcf3ce44SJohn Forte 95fcf3ce44SJohn Forte cl_tmp = (iscsi_conn_list_t *)kmem_zalloc(sizeof (*cl_tmp), KM_SLEEP); 96fcf3ce44SJohn Forte 97fcf3ce44SJohn Forte if (ddi_copyin(arg, cl_tmp, sizeof (*cl_tmp), mode) == 0) { 98fcf3ce44SJohn Forte 99fcf3ce44SJohn Forte if (cl_tmp->cl_vers == ISCSI_INTERFACE_VERSION) { 100fcf3ce44SJohn Forte alloc_len = sizeof (*cl); 101fcf3ce44SJohn Forte if (cl_tmp->cl_in_cnt != 0) { 102fcf3ce44SJohn Forte alloc_len += ((cl_tmp->cl_in_cnt - 1) * 103fcf3ce44SJohn Forte sizeof (iscsi_if_conn_t)); 104fcf3ce44SJohn Forte } 105fcf3ce44SJohn Forte 106fcf3ce44SJohn Forte cl = (iscsi_conn_list_t *)kmem_zalloc(alloc_len, 107fcf3ce44SJohn Forte KM_SLEEP); 108fcf3ce44SJohn Forte bcopy(cl_tmp, cl, sizeof (*cl_tmp)); 109fcf3ce44SJohn Forte } 110fcf3ce44SJohn Forte } 111fcf3ce44SJohn Forte kmem_free(cl_tmp, sizeof (*cl_tmp)); 112fcf3ce44SJohn Forte return (cl); 113fcf3ce44SJohn Forte } 114fcf3ce44SJohn Forte 115fcf3ce44SJohn Forte /* 116fcf3ce44SJohn Forte * iscsi_conn_list_get_copyout - 117fcf3ce44SJohn Forte */ 118fcf3ce44SJohn Forte int 119fcf3ce44SJohn Forte iscsi_ioctl_conn_oid_list_get_copyout(iscsi_conn_list_t *cl, caddr_t arg, 120fcf3ce44SJohn Forte int mode) 121fcf3ce44SJohn Forte { 122fcf3ce44SJohn Forte size_t alloc_len; 123fcf3ce44SJohn Forte int rtn; 124fcf3ce44SJohn Forte 125fcf3ce44SJohn Forte ASSERT(cl != NULL); 126fcf3ce44SJohn Forte ASSERT(arg != NULL); 127fcf3ce44SJohn Forte 128fcf3ce44SJohn Forte rtn = EFAULT; 129fcf3ce44SJohn Forte alloc_len = sizeof (*cl); 130fcf3ce44SJohn Forte if (cl->cl_in_cnt != 0) { 131fcf3ce44SJohn Forte alloc_len += ((cl->cl_in_cnt - 1) * sizeof (iscsi_if_conn_t)); 132fcf3ce44SJohn Forte } 133fcf3ce44SJohn Forte 134fcf3ce44SJohn Forte if (ddi_copyout(cl, arg, alloc_len, mode) == 0) { 135fcf3ce44SJohn Forte rtn = 0; 136fcf3ce44SJohn Forte } 137fcf3ce44SJohn Forte kmem_free(cl, alloc_len); 138fcf3ce44SJohn Forte return (rtn); 139fcf3ce44SJohn Forte } 140fcf3ce44SJohn Forte 141fcf3ce44SJohn Forte /* 142fcf3ce44SJohn Forte * iscsi_conn_oid_list_get - 143fcf3ce44SJohn Forte */ 144fcf3ce44SJohn Forte boolean_t 145fcf3ce44SJohn Forte iscsi_ioctl_conn_oid_list_get(iscsi_hba_t *ihp, iscsi_conn_list_t *cl) 146fcf3ce44SJohn Forte { 147fcf3ce44SJohn Forte iscsi_sess_t *isp; 148fcf3ce44SJohn Forte iscsi_conn_t *icp; 149fcf3ce44SJohn Forte iscsi_if_conn_t *cnx; 150fcf3ce44SJohn Forte uint32_t target_oid; 151fcf3ce44SJohn Forte 152fcf3ce44SJohn Forte /* Let's check the version. */ 153fcf3ce44SJohn Forte if (cl->cl_vers != ISCSI_INTERFACE_VERSION) { 154fcf3ce44SJohn Forte return (B_FALSE); 155fcf3ce44SJohn Forte } 156fcf3ce44SJohn Forte 157fcf3ce44SJohn Forte /* We preinitialize the output connection counter. */ 158fcf3ce44SJohn Forte cl->cl_out_cnt = 0; 159fcf3ce44SJohn Forte 160fcf3ce44SJohn Forte /* The list of sessions is walked holding the HBA mutex. */ 161fcf3ce44SJohn Forte rw_enter(&ihp->hba_sess_list_rwlock, RW_READER); 162fcf3ce44SJohn Forte isp = ihp->hba_sess_list; 163fcf3ce44SJohn Forte 164fcf3ce44SJohn Forte /* 165fcf3ce44SJohn Forte * Check to see if oid references a target-param oid. If so, 166fcf3ce44SJohn Forte * find the associated session oid before getting lu list. 167fcf3ce44SJohn Forte */ 168fcf3ce44SJohn Forte if (iscsi_targetparam_get_name(cl->cl_sess_oid) != NULL) { 169fcf3ce44SJohn Forte for (isp = ihp->hba_sess_list; isp; isp = isp->sess_next) { 170fcf3ce44SJohn Forte if (isp->sess_target_oid == cl->cl_sess_oid) { 171fcf3ce44SJohn Forte target_oid = isp->sess_oid; 172fcf3ce44SJohn Forte break; 173fcf3ce44SJohn Forte } 174fcf3ce44SJohn Forte } 175fcf3ce44SJohn Forte } else { 176fcf3ce44SJohn Forte target_oid = cl->cl_sess_oid; 177fcf3ce44SJohn Forte } 178fcf3ce44SJohn Forte 179fcf3ce44SJohn Forte while (isp != NULL) { 180fcf3ce44SJohn Forte ASSERT(isp->sess_sig == ISCSI_SIG_SESS); 181fcf3ce44SJohn Forte 182fcf3ce44SJohn Forte /* return connections for NORMAL sessions only */ 183fcf3ce44SJohn Forte if ((isp->sess_type == ISCSI_SESS_TYPE_NORMAL) && 184fcf3ce44SJohn Forte ((cl->cl_all_sess == B_TRUE) || 185fcf3ce44SJohn Forte (target_oid == isp->sess_oid))) { 186fcf3ce44SJohn Forte /* 187fcf3ce44SJohn Forte * The list of connections is walked holding 188fcf3ce44SJohn Forte * the session mutex. 189fcf3ce44SJohn Forte */ 190fcf3ce44SJohn Forte rw_enter(&isp->sess_conn_list_rwlock, RW_READER); 191fcf3ce44SJohn Forte icp = isp->sess_conn_list; 192fcf3ce44SJohn Forte 193fcf3ce44SJohn Forte while (icp != NULL) { 194fcf3ce44SJohn Forte ASSERT(icp->conn_sig == ISCSI_SIG_CONN); 195fcf3ce44SJohn Forte 196fcf3ce44SJohn Forte if (icp->conn_state == 197fcf3ce44SJohn Forte ISCSI_CONN_STATE_LOGGED_IN) { 198fcf3ce44SJohn Forte 199fcf3ce44SJohn Forte if (cl->cl_out_cnt < cl->cl_in_cnt) { 200fcf3ce44SJohn Forte /* There's still room. */ 201fcf3ce44SJohn Forte cnx = 202fcf3ce44SJohn Forte &cl->cl_list[ 203fcf3ce44SJohn Forte cl->cl_out_cnt]; 204fcf3ce44SJohn Forte 205fcf3ce44SJohn Forte bzero(cnx, sizeof (*cnx)); 206fcf3ce44SJohn Forte 207fcf3ce44SJohn Forte cnx->c_cid = icp->conn_cid; 208fcf3ce44SJohn Forte cnx->c_oid = icp->conn_oid; 209fcf3ce44SJohn Forte cnx->c_sess_oid = isp->sess_oid; 210fcf3ce44SJohn Forte } 211fcf3ce44SJohn Forte ++cl->cl_out_cnt; 212fcf3ce44SJohn Forte } 213fcf3ce44SJohn Forte icp = icp->conn_next; 214fcf3ce44SJohn Forte } 215fcf3ce44SJohn Forte rw_exit(&isp->sess_conn_list_rwlock); 216fcf3ce44SJohn Forte 217fcf3ce44SJohn Forte if (cl->cl_all_sess == B_FALSE) { 218fcf3ce44SJohn Forte /* 219fcf3ce44SJohn Forte * We got here because it was the only session 220fcf3ce44SJohn Forte * we were looking for. We can exit now. 221fcf3ce44SJohn Forte */ 222fcf3ce44SJohn Forte break; 223fcf3ce44SJohn Forte } 224fcf3ce44SJohn Forte } 225fcf3ce44SJohn Forte isp = isp->sess_next; 226fcf3ce44SJohn Forte } 227fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 228fcf3ce44SJohn Forte return (B_TRUE); 229fcf3ce44SJohn Forte } 230fcf3ce44SJohn Forte 231fcf3ce44SJohn Forte /* 232fcf3ce44SJohn Forte * iscsi_ioctl_conn_props_get - 233fcf3ce44SJohn Forte */ 234fcf3ce44SJohn Forte boolean_t 235fcf3ce44SJohn Forte iscsi_ioctl_conn_props_get(iscsi_hba_t *ihp, iscsi_conn_props_t *cp) 236fcf3ce44SJohn Forte { 237fcf3ce44SJohn Forte iscsi_sess_t *isp; 238fcf3ce44SJohn Forte iscsi_conn_t *icp; 239fcf3ce44SJohn Forte boolean_t rtn; 240fcf3ce44SJohn Forte 241fcf3ce44SJohn Forte /* Let's check the version. */ 242fcf3ce44SJohn Forte if (cp->cp_vers != ISCSI_INTERFACE_VERSION) { 243fcf3ce44SJohn Forte return (B_FALSE); 244fcf3ce44SJohn Forte } 245fcf3ce44SJohn Forte 246fcf3ce44SJohn Forte /* Let's find the session. */ 247fcf3ce44SJohn Forte rw_enter(&ihp->hba_sess_list_rwlock, RW_READER); 248fcf3ce44SJohn Forte if (iscsi_sess_get(cp->cp_sess_oid, ihp, &isp) != 0) { 249fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 250fcf3ce44SJohn Forte return (B_FALSE); 251fcf3ce44SJohn Forte } 252fcf3ce44SJohn Forte 253fcf3ce44SJohn Forte ASSERT(isp->sess_sig == ISCSI_SIG_SESS); 254fcf3ce44SJohn Forte 255fcf3ce44SJohn Forte rtn = B_FALSE; 256fcf3ce44SJohn Forte 257fcf3ce44SJohn Forte rw_enter(&isp->sess_conn_list_rwlock, RW_READER); 258fcf3ce44SJohn Forte icp = isp->sess_conn_list; 259fcf3ce44SJohn Forte cp->cp_params_valid = B_FALSE; 260fcf3ce44SJohn Forte 261fcf3ce44SJohn Forte while (icp != NULL) { 262fcf3ce44SJohn Forte 263fcf3ce44SJohn Forte ASSERT(icp->conn_sig == ISCSI_SIG_CONN); 264fcf3ce44SJohn Forte 265fcf3ce44SJohn Forte if (icp->conn_oid == cp->cp_oid) { 266fcf3ce44SJohn Forte 267fcf3ce44SJohn Forte if (icp->conn_socket->so_laddr.soa_len <= 268fcf3ce44SJohn Forte sizeof (cp->cp_local)) { 269fcf3ce44SJohn Forte bcopy(icp->conn_socket->so_laddr.soa_sa, 270fcf3ce44SJohn Forte &cp->cp_local, 271fcf3ce44SJohn Forte icp->conn_socket->so_laddr.soa_len); 272fcf3ce44SJohn Forte } 273fcf3ce44SJohn Forte if (icp->conn_socket->so_faddr.soa_len <= 274fcf3ce44SJohn Forte sizeof (cp->cp_peer)) { 275fcf3ce44SJohn Forte bcopy(icp->conn_socket->so_faddr.soa_sa, 276fcf3ce44SJohn Forte &cp->cp_peer, 277fcf3ce44SJohn Forte icp->conn_socket->so_faddr.soa_len); 278fcf3ce44SJohn Forte } 279fcf3ce44SJohn Forte 280fcf3ce44SJohn Forte if (icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN) { 281fcf3ce44SJohn Forte cp->cp_params_valid = B_TRUE; 282fcf3ce44SJohn Forte bcopy(&icp->conn_params, &cp->cp_params, 283fcf3ce44SJohn Forte sizeof (icp->conn_params)); 284fcf3ce44SJohn Forte } 285fcf3ce44SJohn Forte 286fcf3ce44SJohn Forte rtn = B_TRUE; 287fcf3ce44SJohn Forte break; 288fcf3ce44SJohn Forte } 289fcf3ce44SJohn Forte icp = icp->conn_next; 290fcf3ce44SJohn Forte } 291fcf3ce44SJohn Forte rw_exit(&isp->sess_conn_list_rwlock); 292fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 293fcf3ce44SJohn Forte return (rtn); 294fcf3ce44SJohn Forte } 295fcf3ce44SJohn Forte 296fcf3ce44SJohn Forte 297fcf3ce44SJohn Forte /* 298fcf3ce44SJohn Forte * iscsi_ioctl_sendtgts_get - 0 on success; errno on failure 299fcf3ce44SJohn Forte * 300fcf3ce44SJohn Forte */ 301fcf3ce44SJohn Forte int 302fcf3ce44SJohn Forte iscsi_ioctl_sendtgts_get(iscsi_hba_t *ihp, iscsi_sendtgts_list_t *stl) 303fcf3ce44SJohn Forte { 304fcf3ce44SJohn Forte #define ISCSI_SENDTGTS_REQ_STR "SendTargets=All" 305fcf3ce44SJohn Forte 306fcf3ce44SJohn Forte int rtn = EFAULT; 307fcf3ce44SJohn Forte iscsi_status_t status; 308fcf3ce44SJohn Forte iscsi_sess_t *isp; 309fcf3ce44SJohn Forte iscsi_conn_t *icp; 310fcf3ce44SJohn Forte uint32_t oid; 311fcf3ce44SJohn Forte char *data; 312fcf3ce44SJohn Forte uint32_t data_len; 313fcf3ce44SJohn Forte uint32_t rx_data_len; 314fcf3ce44SJohn Forte iscsi_sockaddr_t addr_snd; 315fcf3ce44SJohn Forte 316fcf3ce44SJohn Forte ASSERT(ihp != NULL); 317fcf3ce44SJohn Forte ASSERT(stl != NULL); 318fcf3ce44SJohn Forte 319fcf3ce44SJohn Forte iscsid_addr_to_sockaddr(stl->stl_entry.e_insize, 320fcf3ce44SJohn Forte &stl->stl_entry.e_u, stl->stl_entry.e_port, 321fcf3ce44SJohn Forte &addr_snd.sin); 322fcf3ce44SJohn Forte 323fcf3ce44SJohn Forte /* create discovery session */ 324fcf3ce44SJohn Forte rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 325fcf3ce44SJohn Forte isp = iscsi_sess_create(ihp, iSCSIDiscoveryMethodSendTargets, 326fcf3ce44SJohn Forte NULL, SENDTARGETS_DISCOVERY, ISCSI_DEFAULT_TPGT, 327fcf3ce44SJohn Forte ISCSI_SUN_ISID_5, ISCSI_SESS_TYPE_DISCOVERY, &oid); 328fcf3ce44SJohn Forte if (isp == NULL) { 329fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 330fcf3ce44SJohn Forte return (1); 331fcf3ce44SJohn Forte } 332fcf3ce44SJohn Forte 333fcf3ce44SJohn Forte /* create connection */ 334fcf3ce44SJohn Forte rw_enter(&isp->sess_conn_list_rwlock, RW_WRITER); 335fcf3ce44SJohn Forte status = iscsi_conn_create(&addr_snd.sin, isp, &icp); 336fcf3ce44SJohn Forte rw_exit(&isp->sess_conn_list_rwlock); 337fcf3ce44SJohn Forte 338fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(status)) { 339fcf3ce44SJohn Forte (void) iscsi_sess_destroy(isp); 340fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 341fcf3ce44SJohn Forte return (1); 342fcf3ce44SJohn Forte } 343fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 344fcf3ce44SJohn Forte 345fcf3ce44SJohn Forte /* start login */ 346fcf3ce44SJohn Forte mutex_enter(&icp->conn_state_mutex); 347fcf3ce44SJohn Forte (void) iscsi_conn_state_machine(icp, ISCSI_CONN_EVENT_T1); 348fcf3ce44SJohn Forte mutex_exit(&icp->conn_state_mutex); 349fcf3ce44SJohn Forte 350fcf3ce44SJohn Forte if (icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN) { 351fcf3ce44SJohn Forte data_len = icp->conn_params.max_xmit_data_seg_len; 352fcf3ce44SJohn Forte retry_sendtgts: 353fcf3ce44SJohn Forte /* alloc/init buffer for SendTargets req/resp */ 354fcf3ce44SJohn Forte data = kmem_zalloc(data_len, KM_SLEEP); 355fcf3ce44SJohn Forte bcopy(ISCSI_SENDTGTS_REQ_STR, data, 356fcf3ce44SJohn Forte sizeof (ISCSI_SENDTGTS_REQ_STR)); 357fcf3ce44SJohn Forte 358fcf3ce44SJohn Forte /* execute SendTargets operation */ 359fcf3ce44SJohn Forte status = iscsi_handle_text(icp, data, data_len, 360fcf3ce44SJohn Forte sizeof (ISCSI_SENDTGTS_REQ_STR), &rx_data_len); 361fcf3ce44SJohn Forte 362fcf3ce44SJohn Forte /* check if allocated buffer is too small for response */ 363fcf3ce44SJohn Forte if (status == ISCSI_STATUS_DATA_OVERFLOW) { 364fcf3ce44SJohn Forte kmem_free(data, data_len); 365fcf3ce44SJohn Forte data_len = rx_data_len; 366fcf3ce44SJohn Forte goto retry_sendtgts; 367fcf3ce44SJohn Forte } 368fcf3ce44SJohn Forte 369fcf3ce44SJohn Forte if (ISCSI_SUCCESS(status)) { 370fcf3ce44SJohn Forte status = iscsi_create_sendtgts_list(icp, data, 371fcf3ce44SJohn Forte rx_data_len, stl); 372fcf3ce44SJohn Forte if (ISCSI_SUCCESS(status)) { 373fcf3ce44SJohn Forte rtn = 0; 374fcf3ce44SJohn Forte } 375fcf3ce44SJohn Forte } else { 376fcf3ce44SJohn Forte rtn = EFAULT; 377fcf3ce44SJohn Forte } 378fcf3ce44SJohn Forte 379fcf3ce44SJohn Forte kmem_free(data, data_len); 380fcf3ce44SJohn Forte } else { 381fcf3ce44SJohn Forte rtn = EFAULT; 382fcf3ce44SJohn Forte } 383fcf3ce44SJohn Forte 384fcf3ce44SJohn Forte /* 385fcf3ce44SJohn Forte * check if session is still alive. It may have been destroyed 386fcf3ce44SJohn Forte * by a driver unload 387fcf3ce44SJohn Forte */ 388fcf3ce44SJohn Forte rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 389fcf3ce44SJohn Forte if (iscsi_sess_get(oid, ihp, &isp) == 0) { 390fcf3ce44SJohn Forte (void) iscsi_sess_destroy(isp); 391fcf3ce44SJohn Forte } 392fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 393fcf3ce44SJohn Forte 394fcf3ce44SJohn Forte return (rtn); 395fcf3ce44SJohn Forte } 396fcf3ce44SJohn Forte 397fcf3ce44SJohn Forte 398fcf3ce44SJohn Forte /* 399fcf3ce44SJohn Forte * iscsi_create_sendtgts_list - Based upon the given data, build a 400fcf3ce44SJohn Forte * linked list of SendTarget information. The data passed into this 401fcf3ce44SJohn Forte * function is expected to be the data portion(s) of SendTarget text 402fcf3ce44SJohn Forte * response. 403fcf3ce44SJohn Forte */ 404fcf3ce44SJohn Forte static iscsi_status_t 405fcf3ce44SJohn Forte iscsi_create_sendtgts_list(iscsi_conn_t *icp, char *data, int data_len, 406fcf3ce44SJohn Forte iscsi_sendtgts_list_t *stl) 407fcf3ce44SJohn Forte { 408fcf3ce44SJohn Forte char *line = NULL; 409fcf3ce44SJohn Forte boolean_t targetname_added = B_FALSE; 410fcf3ce44SJohn Forte iscsi_sendtgts_entry_t *curr_ste = NULL, 411fcf3ce44SJohn Forte *prev_ste = NULL; 412fcf3ce44SJohn Forte struct hostent *hptr; 413fcf3ce44SJohn Forte int error_num; 414fcf3ce44SJohn Forte 415fcf3ce44SJohn Forte /* initialize number of targets found */ 416fcf3ce44SJohn Forte stl->stl_out_cnt = 0; 417fcf3ce44SJohn Forte 418fcf3ce44SJohn Forte if (data_len == 0) 419fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 420fcf3ce44SJohn Forte 421fcf3ce44SJohn Forte while ((line = iscsi_get_next_text(data, data_len, line)) != NULL) { 422fcf3ce44SJohn Forte if (strncmp(TARGETNAME, line, strlen(TARGETNAME)) == 0) { 423fcf3ce44SJohn Forte /* check if this is first targetname */ 424fcf3ce44SJohn Forte if (prev_ste != NULL) { 425fcf3ce44SJohn Forte stl->stl_out_cnt++; 426fcf3ce44SJohn Forte } 427fcf3ce44SJohn Forte if (stl->stl_out_cnt >= stl->stl_in_cnt) { 428fcf3ce44SJohn Forte /* 429fcf3ce44SJohn Forte * continue processing the data so that 430fcf3ce44SJohn Forte * the total number of targets are known 431fcf3ce44SJohn Forte * and the caller can retry with the correct 432fcf3ce44SJohn Forte * number of entries in the list 433fcf3ce44SJohn Forte */ 434fcf3ce44SJohn Forte continue; 435fcf3ce44SJohn Forte } 436fcf3ce44SJohn Forte curr_ste = &(stl->stl_list[stl->stl_out_cnt]); 437fcf3ce44SJohn Forte 438fcf3ce44SJohn Forte /* 439fcf3ce44SJohn Forte * This entry will use the IP address and port 440fcf3ce44SJohn Forte * that was passed into this routine. If the next 441fcf3ce44SJohn Forte * line that we receive is a TargetAddress we will 442fcf3ce44SJohn Forte * know to modify this entry with the new IP address, 443fcf3ce44SJohn Forte * port and portal group tag. If this state flag 444fcf3ce44SJohn Forte * is not set we'll just create a new entry using 445fcf3ce44SJohn Forte * only the previous entries targetname. 446fcf3ce44SJohn Forte */ 447fcf3ce44SJohn Forte (void) strncpy((char *)curr_ste->ste_name, 448fcf3ce44SJohn Forte line + strlen(TARGETNAME), 449fcf3ce44SJohn Forte sizeof (curr_ste->ste_name)); 450fcf3ce44SJohn Forte 451fcf3ce44SJohn Forte if (icp->conn_base_addr.sin.sa_family == AF_INET) { 452fcf3ce44SJohn Forte 453fcf3ce44SJohn Forte struct sockaddr_in *addr_in = 454fcf3ce44SJohn Forte &icp->conn_base_addr.sin4; 455fcf3ce44SJohn Forte curr_ste->ste_ipaddr.a_addr.i_insize = 456fcf3ce44SJohn Forte sizeof (struct in_addr); 457fcf3ce44SJohn Forte bcopy(&addr_in->sin_addr.s_addr, 458fcf3ce44SJohn Forte &curr_ste->ste_ipaddr.a_addr.i_addr, 459fcf3ce44SJohn Forte sizeof (struct in_addr)); 460fcf3ce44SJohn Forte curr_ste->ste_ipaddr.a_port = 461fcf3ce44SJohn Forte htons(addr_in->sin_port); 462fcf3ce44SJohn Forte 463fcf3ce44SJohn Forte } else { 464fcf3ce44SJohn Forte 465fcf3ce44SJohn Forte struct sockaddr_in6 *addr_in6 = 466fcf3ce44SJohn Forte &icp->conn_base_addr.sin6; 467fcf3ce44SJohn Forte curr_ste->ste_ipaddr.a_addr.i_insize = 468fcf3ce44SJohn Forte sizeof (struct in6_addr); 469fcf3ce44SJohn Forte bcopy(&addr_in6->sin6_addr.s6_addr, 470fcf3ce44SJohn Forte &curr_ste->ste_ipaddr.a_addr.i_addr, 471fcf3ce44SJohn Forte sizeof (struct in6_addr)); 472fcf3ce44SJohn Forte curr_ste->ste_ipaddr.a_port = 473fcf3ce44SJohn Forte htons(addr_in6->sin6_port); 474fcf3ce44SJohn Forte } 475fcf3ce44SJohn Forte curr_ste->ste_tpgt = -1; 476fcf3ce44SJohn Forte 477fcf3ce44SJohn Forte targetname_added = B_TRUE; 478fcf3ce44SJohn Forte 479fcf3ce44SJohn Forte } else if (strncmp(TARGETADDRESS, line, 480fcf3ce44SJohn Forte strlen(TARGETADDRESS)) == 0) { 481fcf3ce44SJohn Forte 482fcf3ce44SJohn Forte char *in_str, 483fcf3ce44SJohn Forte *tmp_buf, 484fcf3ce44SJohn Forte *addr_str, 485fcf3ce44SJohn Forte *port_str, 486fcf3ce44SJohn Forte *tpgt_str; 487fcf3ce44SJohn Forte int type, 488fcf3ce44SJohn Forte tmp_buf_len; 489fcf3ce44SJohn Forte long result; 490fcf3ce44SJohn Forte 491fcf3ce44SJohn Forte /* 492fcf3ce44SJohn Forte * If TARGETADDRESS is first line a SendTarget response 493fcf3ce44SJohn Forte * (i.e. no TARGETNAME lines preceding), treat as 494fcf3ce44SJohn Forte * an error. To check this an assumption is made that 495fcf3ce44SJohn Forte * at least one sendtarget_entry_t should exist prior 496fcf3ce44SJohn Forte * to entering this code. 497fcf3ce44SJohn Forte */ 498fcf3ce44SJohn Forte if (prev_ste == NULL) { 499fcf3ce44SJohn Forte cmn_err(CE_NOTE, "SendTargets protocol error: " 500fcf3ce44SJohn Forte "TARGETADDRESS first"); 501fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 502fcf3ce44SJohn Forte } 503fcf3ce44SJohn Forte 504fcf3ce44SJohn Forte /* 505fcf3ce44SJohn Forte * If we can't find an '=' then the sendtargets 506fcf3ce44SJohn Forte * response if invalid per spec. Return empty list. 507fcf3ce44SJohn Forte */ 508fcf3ce44SJohn Forte in_str = strchr(line, '='); 509fcf3ce44SJohn Forte if (in_str == NULL) { 510fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 511fcf3ce44SJohn Forte } 512fcf3ce44SJohn Forte 513fcf3ce44SJohn Forte /* move past the '=' */ 514fcf3ce44SJohn Forte in_str++; 515fcf3ce44SJohn Forte 516fcf3ce44SJohn Forte /* Copy addr, port, and tpgt into temporary buffer */ 517fcf3ce44SJohn Forte tmp_buf_len = strlen(in_str) + 1; 518fcf3ce44SJohn Forte tmp_buf = kmem_zalloc(tmp_buf_len, KM_SLEEP); 519fcf3ce44SJohn Forte (void) strncpy(tmp_buf, in_str, tmp_buf_len); 520fcf3ce44SJohn Forte 521fcf3ce44SJohn Forte /* 522fcf3ce44SJohn Forte * Parse the addr, port, and tpgt from 523fcf3ce44SJohn Forte * sendtarget response 524fcf3ce44SJohn Forte */ 525fcf3ce44SJohn Forte if (parse_addr_port_tpgt(tmp_buf, &addr_str, &type, 526fcf3ce44SJohn Forte &port_str, &tpgt_str) == B_FALSE) { 527fcf3ce44SJohn Forte /* Unable to extract addr */ 528fcf3ce44SJohn Forte kmem_free(tmp_buf, tmp_buf_len); 529fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 530fcf3ce44SJohn Forte } 531fcf3ce44SJohn Forte 532fcf3ce44SJohn Forte /* Now convert string addr to binary */ 533fcf3ce44SJohn Forte hptr = kgetipnodebyname(addr_str, type, 534fcf3ce44SJohn Forte AI_ALL, &error_num); 535fcf3ce44SJohn Forte if (!hptr) { 536fcf3ce44SJohn Forte /* Unable to get valid address */ 537fcf3ce44SJohn Forte kmem_free(tmp_buf, tmp_buf_len); 538fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 539fcf3ce44SJohn Forte } 540fcf3ce44SJohn Forte 541fcf3ce44SJohn Forte /* Check if space for response */ 542fcf3ce44SJohn Forte if (targetname_added == B_FALSE) { 543fcf3ce44SJohn Forte stl->stl_out_cnt++; 544fcf3ce44SJohn Forte if (stl->stl_out_cnt >= stl->stl_in_cnt) { 545fcf3ce44SJohn Forte /* 546fcf3ce44SJohn Forte * continue processing the data so that 547fcf3ce44SJohn Forte * the total number of targets are 548fcf3ce44SJohn Forte * known and the caller can retry with 549fcf3ce44SJohn Forte * the correct number of entries in 550fcf3ce44SJohn Forte * the list 551fcf3ce44SJohn Forte */ 552fcf3ce44SJohn Forte kfreehostent(hptr); 553fcf3ce44SJohn Forte kmem_free(tmp_buf, tmp_buf_len); 554fcf3ce44SJohn Forte continue; 555fcf3ce44SJohn Forte } 556fcf3ce44SJohn Forte curr_ste = &(stl->stl_list[stl->stl_out_cnt]); 557fcf3ce44SJohn Forte (void) strcpy((char *)curr_ste->ste_name, 558fcf3ce44SJohn Forte (char *)prev_ste->ste_name); 559fcf3ce44SJohn Forte } 560fcf3ce44SJohn Forte 561fcf3ce44SJohn Forte curr_ste->ste_ipaddr.a_addr.i_insize = hptr->h_length; 562fcf3ce44SJohn Forte bcopy(*hptr->h_addr_list, 563fcf3ce44SJohn Forte &(curr_ste->ste_ipaddr.a_addr.i_addr), 564fcf3ce44SJohn Forte curr_ste->ste_ipaddr.a_addr.i_insize); 565fcf3ce44SJohn Forte kfreehostent(hptr); 566fcf3ce44SJohn Forte 567fcf3ce44SJohn Forte if (port_str != NULL) { 568fcf3ce44SJohn Forte (void) ddi_strtol(port_str, NULL, 0, &result); 569fcf3ce44SJohn Forte curr_ste->ste_ipaddr.a_port = (short)result; 570fcf3ce44SJohn Forte } else { 571fcf3ce44SJohn Forte curr_ste->ste_ipaddr.a_port = ISCSI_LISTEN_PORT; 572fcf3ce44SJohn Forte } 573fcf3ce44SJohn Forte 574fcf3ce44SJohn Forte if (tpgt_str != NULL) { 575fcf3ce44SJohn Forte (void) ddi_strtol(tpgt_str, NULL, 0, &result); 576fcf3ce44SJohn Forte curr_ste->ste_tpgt = (short)result; 577fcf3ce44SJohn Forte } else { 578fcf3ce44SJohn Forte cmn_err(CE_NOTE, "SendTargets protocol error: " 579fcf3ce44SJohn Forte "TPGT not specified"); 580fcf3ce44SJohn Forte kmem_free(tmp_buf, tmp_buf_len); 581fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 582fcf3ce44SJohn Forte } 583fcf3ce44SJohn Forte 584fcf3ce44SJohn Forte kmem_free(tmp_buf, tmp_buf_len); 585fcf3ce44SJohn Forte 586fcf3ce44SJohn Forte targetname_added = B_FALSE; 587fcf3ce44SJohn Forte 588fcf3ce44SJohn Forte } else if (strlen(line) != 0) { 589fcf3ce44SJohn Forte /* 590fcf3ce44SJohn Forte * Any other string besides an empty string 591fcf3ce44SJohn Forte * is a protocol error 592fcf3ce44SJohn Forte */ 593fcf3ce44SJohn Forte cmn_err(CE_NOTE, "SendTargets protocol error: " 594fcf3ce44SJohn Forte "unexpected response"); 595fcf3ce44SJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR); 596fcf3ce44SJohn Forte } 597fcf3ce44SJohn Forte 598fcf3ce44SJohn Forte prev_ste = curr_ste; 599fcf3ce44SJohn Forte } 600fcf3ce44SJohn Forte 601fcf3ce44SJohn Forte /* 602fcf3ce44SJohn Forte * If target found increment out count one more time because 603fcf3ce44SJohn Forte * this is the total number of entries in the list not an index 604fcf3ce44SJohn Forte * like it was used above 605fcf3ce44SJohn Forte */ 606fcf3ce44SJohn Forte if (prev_ste != NULL) { 607fcf3ce44SJohn Forte stl->stl_out_cnt++; 608fcf3ce44SJohn Forte } 609fcf3ce44SJohn Forte 610fcf3ce44SJohn Forte return (ISCSI_STATUS_SUCCESS); 611fcf3ce44SJohn Forte } 612fcf3ce44SJohn Forte 613fcf3ce44SJohn Forte /* 614fcf3ce44SJohn Forte * iscsi_set_param - This function is a helper to ISCSI_SET_PARAM 615fcf3ce44SJohn Forte * IOCTL 616fcf3ce44SJohn Forte */ 617fcf3ce44SJohn Forte int 618fcf3ce44SJohn Forte iscsi_set_param(iscsi_login_params_t *params, iscsi_param_set_t *ipsp) 619fcf3ce44SJohn Forte { 620fcf3ce44SJohn Forte int rtn = 0; 621fcf3ce44SJohn Forte iscsi_param_get_t *ipgp; 622fcf3ce44SJohn Forte 623fcf3ce44SJohn Forte /* 624fcf3ce44SJohn Forte * Use get param to get the min, max and increment values for the 625fcf3ce44SJohn Forte * given parameter so validation can be done on the new value. 626fcf3ce44SJohn Forte */ 627fcf3ce44SJohn Forte ipgp = (iscsi_param_get_t *)kmem_alloc(sizeof (*ipgp), KM_SLEEP); 628fcf3ce44SJohn Forte ipgp->g_param = ipsp->s_param; 629fcf3ce44SJohn Forte rtn = iscsi_get_param(params, B_TRUE, ipgp); 630fcf3ce44SJohn Forte if (rtn != 0) { 631fcf3ce44SJohn Forte kmem_free(ipgp, sizeof (*ipgp)); 632fcf3ce44SJohn Forte return (rtn); 633fcf3ce44SJohn Forte } 634fcf3ce44SJohn Forte 635fcf3ce44SJohn Forte if (ipsp->s_param == ISCSI_LOGIN_PARAM_HEADER_DIGEST || 636fcf3ce44SJohn Forte ipsp->s_param == ISCSI_LOGIN_PARAM_DATA_DIGEST || 637fcf3ce44SJohn Forte ipsp->s_param == ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN || 638fcf3ce44SJohn Forte ipsp->s_param == ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT || 639fcf3ce44SJohn Forte ipsp->s_param == ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH || 640fcf3ce44SJohn Forte ipsp->s_param == ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH || 641fcf3ce44SJohn Forte ipsp->s_param == ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH) { 642fcf3ce44SJohn Forte 643fcf3ce44SJohn Forte if (ipsp->s_value.v_integer < ipgp->g_value.v_integer.i_min || 644fcf3ce44SJohn Forte ipsp->s_value.v_integer > ipgp->g_value.v_integer.i_max || 645fcf3ce44SJohn Forte (ipsp->s_value.v_integer % 646fcf3ce44SJohn Forte ipgp->g_value.v_integer.i_incr) != 0) { 647fcf3ce44SJohn Forte rtn = EINVAL; 648fcf3ce44SJohn Forte kmem_free(ipgp, sizeof (*ipgp)); 649fcf3ce44SJohn Forte return (rtn); 650fcf3ce44SJohn Forte } 651fcf3ce44SJohn Forte 652fcf3ce44SJohn Forte } 653fcf3ce44SJohn Forte kmem_free(ipgp, sizeof (*ipgp)); 654fcf3ce44SJohn Forte 655fcf3ce44SJohn Forte 656fcf3ce44SJohn Forte switch (ipsp->s_param) { 657fcf3ce44SJohn Forte 658fcf3ce44SJohn Forte /* 659fcf3ce44SJohn Forte * Boolean parameters 660fcf3ce44SJohn Forte */ 661fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER: 662fcf3ce44SJohn Forte params->data_sequence_in_order = ipsp->s_value.v_bool; 663fcf3ce44SJohn Forte break; 664fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_IMMEDIATE_DATA: 665fcf3ce44SJohn Forte params->immediate_data = ipsp->s_value.v_bool; 666fcf3ce44SJohn Forte break; 667fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_INITIAL_R2T: 668fcf3ce44SJohn Forte params->initial_r2t = ipsp->s_value.v_bool; 669fcf3ce44SJohn Forte break; 670fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER: 671fcf3ce44SJohn Forte params->data_pdu_in_order = ipsp->s_value.v_bool; 672fcf3ce44SJohn Forte break; 673fcf3ce44SJohn Forte 674fcf3ce44SJohn Forte /* 675fcf3ce44SJohn Forte * Integer parameters 676fcf3ce44SJohn Forte */ 677fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_HEADER_DIGEST: 678fcf3ce44SJohn Forte params->header_digest = ipsp->s_value.v_integer; 679fcf3ce44SJohn Forte break; 680fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DATA_DIGEST: 681fcf3ce44SJohn Forte params->data_digest = ipsp->s_value.v_integer; 682fcf3ce44SJohn Forte break; 683fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN: 684fcf3ce44SJohn Forte params->default_time_to_retain = ipsp->s_value.v_integer; 685fcf3ce44SJohn Forte break; 686fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT: 687fcf3ce44SJohn Forte params->default_time_to_wait = ipsp->s_value.v_integer; 688fcf3ce44SJohn Forte break; 689fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH: 690fcf3ce44SJohn Forte params->max_recv_data_seg_len = ipsp->s_value.v_integer; 691fcf3ce44SJohn Forte break; 692fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH: 693fcf3ce44SJohn Forte if (ipsp->s_value.v_integer <= params->max_burst_length) { 694fcf3ce44SJohn Forte params->first_burst_length = ipsp->s_value.v_integer; 695fcf3ce44SJohn Forte } else { 696fcf3ce44SJohn Forte rtn = EINVAL; 697fcf3ce44SJohn Forte } 698fcf3ce44SJohn Forte break; 699fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH: 700fcf3ce44SJohn Forte if (ipsp->s_value.v_integer >= params->first_burst_length) { 701fcf3ce44SJohn Forte params->max_burst_length = ipsp->s_value.v_integer; 702fcf3ce44SJohn Forte } else { 703fcf3ce44SJohn Forte rtn = EINVAL; 704fcf3ce44SJohn Forte } 705fcf3ce44SJohn Forte break; 706fcf3ce44SJohn Forte 707fcf3ce44SJohn Forte /* 708fcf3ce44SJohn Forte * Integer parameters which currently are unsettable 709fcf3ce44SJohn Forte */ 710fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_MAX_CONNECTIONS: 711fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_OUTSTANDING_R2T: 712fcf3ce44SJohn Forte case ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL: 713fcf3ce44SJohn Forte rtn = ENOTSUP; 714fcf3ce44SJohn Forte break; 715fcf3ce44SJohn Forte 716fcf3ce44SJohn Forte default: 717fcf3ce44SJohn Forte rtn = EINVAL; 718fcf3ce44SJohn Forte break; 719fcf3ce44SJohn Forte } 720fcf3ce44SJohn Forte return (rtn); 721fcf3ce44SJohn Forte } 722fcf3ce44SJohn Forte 723fcf3ce44SJohn Forte int 724fcf3ce44SJohn Forte iscsi_set_params(iscsi_param_set_t *ils, iscsi_hba_t *ihp, boolean_t persist) 725fcf3ce44SJohn Forte { 726fcf3ce44SJohn Forte iscsi_login_params_t *params = NULL; 727fcf3ce44SJohn Forte uchar_t *name = NULL; 728fcf3ce44SJohn Forte iscsi_sess_t *isp = NULL; 729fcf3ce44SJohn Forte iscsi_param_get_t *ilg; 730fcf3ce44SJohn Forte int rtn = 0; 731fcf3ce44SJohn Forte 732fcf3ce44SJohn Forte /* handle special case for Initiator name */ 733fcf3ce44SJohn Forte if (ils->s_param == ISCSI_LOGIN_PARAM_INITIATOR_NAME) { 734fcf3ce44SJohn Forte (void) strlcpy((char *)ihp->hba_name, 735fcf3ce44SJohn Forte (char *)ils->s_value.v_name, ISCSI_MAX_NAME_LEN); 736fcf3ce44SJohn Forte if (persist) { 737fcf3ce44SJohn Forte char *name; 738fcf3ce44SJohn Forte boolean_t rval; 739fcf3ce44SJohn Forte 740fcf3ce44SJohn Forte /* save off old Initiator name */ 741fcf3ce44SJohn Forte name = kmem_alloc(ISCSI_MAX_NAME_LEN, KM_SLEEP); 742fcf3ce44SJohn Forte rval = persistent_initiator_name_get(name, 743fcf3ce44SJohn Forte ISCSI_MAX_NAME_LEN); 744fcf3ce44SJohn Forte 745fcf3ce44SJohn Forte (void) persistent_initiator_name_set( 746fcf3ce44SJohn Forte (char *)ihp->hba_name); 747fcf3ce44SJohn Forte if (rval == B_TRUE) { 748fcf3ce44SJohn Forte /* 749fcf3ce44SJohn Forte * check to see if we have login param, 750fcf3ce44SJohn Forte * chap param, or authentication params 751fcf3ce44SJohn Forte * loaded in persistent that we have to change 752fcf3ce44SJohn Forte * the name of 753fcf3ce44SJohn Forte */ 754fcf3ce44SJohn Forte persistent_param_t *pp; 755fcf3ce44SJohn Forte iscsi_chap_props_t *chap; 756fcf3ce44SJohn Forte iscsi_auth_props_t *auth; 757fcf3ce44SJohn Forte 758fcf3ce44SJohn Forte /* checking login params */ 759fcf3ce44SJohn Forte pp = kmem_zalloc(sizeof (persistent_param_t), 760fcf3ce44SJohn Forte KM_SLEEP); 761fcf3ce44SJohn Forte if (persistent_param_get(name, pp)) { 762fcf3ce44SJohn Forte rval = persistent_param_clear(name); 763fcf3ce44SJohn Forte if (rval == B_TRUE) { 764fcf3ce44SJohn Forte rval = persistent_param_set( 765fcf3ce44SJohn Forte (char *)ihp->hba_name, pp); 766fcf3ce44SJohn Forte } 767fcf3ce44SJohn Forte if (rval == B_FALSE) { 768fcf3ce44SJohn Forte rtn = EFAULT; 769fcf3ce44SJohn Forte } 770fcf3ce44SJohn Forte } 771fcf3ce44SJohn Forte kmem_free(pp, sizeof (persistent_param_t)); 772fcf3ce44SJohn Forte 773fcf3ce44SJohn Forte /* check chap params */ 774fcf3ce44SJohn Forte chap = kmem_zalloc(sizeof (iscsi_chap_props_t), 775fcf3ce44SJohn Forte KM_SLEEP); 776fcf3ce44SJohn Forte if (persistent_chap_get(name, chap)) { 777fcf3ce44SJohn Forte rval = persistent_chap_clear(name); 778fcf3ce44SJohn Forte if (rval == B_TRUE) { 779fcf3ce44SJohn Forte /* 780fcf3ce44SJohn Forte * Update CHAP user name only if the 781fcf3ce44SJohn Forte * original username was set to the 782fcf3ce44SJohn Forte * initiator node name. Otherwise 783fcf3ce44SJohn Forte * leave it the way it is. 784fcf3ce44SJohn Forte */ 785fcf3ce44SJohn Forte int userSize; 786fcf3ce44SJohn Forte userSize = 787fcf3ce44SJohn Forte sizeof (chap->c_user); 788fcf3ce44SJohn Forte if (strncmp((char *) 789fcf3ce44SJohn Forte chap->c_user, name, 790fcf3ce44SJohn Forte sizeof (chap->c_user)) 791fcf3ce44SJohn Forte == 0) { 792fcf3ce44SJohn Forte bzero(chap->c_user, 793fcf3ce44SJohn Forte userSize); 794fcf3ce44SJohn Forte bcopy((char *) 795fcf3ce44SJohn Forte ihp->hba_name, 796fcf3ce44SJohn Forte chap->c_user, 797fcf3ce44SJohn Forte strlen((char *) 798fcf3ce44SJohn Forte ihp->hba_name)); 799fcf3ce44SJohn Forte chap->c_user_len = 800fcf3ce44SJohn Forte strlen((char *) 801fcf3ce44SJohn Forte ihp->hba_name); 802fcf3ce44SJohn Forte 803fcf3ce44SJohn Forte } 804fcf3ce44SJohn Forte rval = persistent_chap_set( 805fcf3ce44SJohn Forte (char *)ihp->hba_name, chap); 806fcf3ce44SJohn Forte } 807fcf3ce44SJohn Forte if (rval == B_FALSE) { 808fcf3ce44SJohn Forte rtn = EFAULT; 809fcf3ce44SJohn Forte } 810fcf3ce44SJohn Forte } 811fcf3ce44SJohn Forte kmem_free(chap, sizeof (iscsi_chap_props_t)); 812fcf3ce44SJohn Forte 813fcf3ce44SJohn Forte /* check authentication params */ 814fcf3ce44SJohn Forte auth = kmem_zalloc(sizeof (iscsi_auth_props_t), 815fcf3ce44SJohn Forte KM_SLEEP); 816fcf3ce44SJohn Forte if (persistent_auth_get(name, auth)) { 817fcf3ce44SJohn Forte rval = persistent_auth_clear(name); 818fcf3ce44SJohn Forte if (rval == B_TRUE) { 819fcf3ce44SJohn Forte rval = persistent_auth_set( 820fcf3ce44SJohn Forte (char *)ihp->hba_name, 821fcf3ce44SJohn Forte auth); 822fcf3ce44SJohn Forte } 823fcf3ce44SJohn Forte if (rval == B_FALSE) { 824fcf3ce44SJohn Forte rtn = EFAULT; 825fcf3ce44SJohn Forte } 826fcf3ce44SJohn Forte } 827fcf3ce44SJohn Forte kmem_free(auth, sizeof (iscsi_auth_props_t)); 828fcf3ce44SJohn Forte } 829fcf3ce44SJohn Forte kmem_free(name, ISCSI_MAX_NAME_LEN); 830fcf3ce44SJohn Forte } 831fcf3ce44SJohn Forte } else if (ils->s_param == ISCSI_LOGIN_PARAM_INITIATOR_ALIAS) { 832fcf3ce44SJohn Forte (void) strlcpy((char *)ihp->hba_alias, 833fcf3ce44SJohn Forte (char *)ils->s_value.v_name, ISCSI_MAX_NAME_LEN); 834fcf3ce44SJohn Forte ihp->hba_alias_length = 835fcf3ce44SJohn Forte strlen((char *)ils->s_value.v_name); 836fcf3ce44SJohn Forte if (persist) { 837fcf3ce44SJohn Forte (void) persistent_alias_name_set( 838fcf3ce44SJohn Forte (char *)ihp->hba_alias); 839fcf3ce44SJohn Forte } 840fcf3ce44SJohn Forte } else { 841fcf3ce44SJohn Forte /* switch login based if looking for initiator params */ 842fcf3ce44SJohn Forte if (ils->s_oid == ihp->hba_oid) { 843fcf3ce44SJohn Forte /* initiator */ 844fcf3ce44SJohn Forte params = &ihp->hba_params; 845fcf3ce44SJohn Forte name = ihp->hba_name; 846fcf3ce44SJohn Forte rtn = iscsi_set_param(params, ils); 847fcf3ce44SJohn Forte } else { 848fcf3ce44SJohn Forte /* session */ 849fcf3ce44SJohn Forte name = iscsi_targetparam_get_name(ils->s_oid); 850fcf3ce44SJohn Forte 851fcf3ce44SJohn Forte if (persist) { 852fcf3ce44SJohn Forte boolean_t rval; 853fcf3ce44SJohn Forte persistent_param_t *pp; 854fcf3ce44SJohn Forte 855fcf3ce44SJohn Forte pp = (persistent_param_t *) 856fcf3ce44SJohn Forte kmem_zalloc(sizeof (*pp), KM_SLEEP); 857fcf3ce44SJohn Forte if (!persistent_param_get((char *)name, pp)) { 858fcf3ce44SJohn Forte iscsi_set_default_login_params( 859fcf3ce44SJohn Forte &pp->p_params); 860fcf3ce44SJohn Forte } 861fcf3ce44SJohn Forte 862fcf3ce44SJohn Forte pp->p_bitmap |= (1 << ils->s_param); 863fcf3ce44SJohn Forte rtn = iscsi_set_param(&pp->p_params, ils); 864fcf3ce44SJohn Forte if (rtn == 0) { 865fcf3ce44SJohn Forte rval = persistent_param_set( 866fcf3ce44SJohn Forte (char *)name, pp); 867fcf3ce44SJohn Forte if (rval == B_FALSE) { 868fcf3ce44SJohn Forte rtn = EFAULT; 869fcf3ce44SJohn Forte } 870fcf3ce44SJohn Forte } 871fcf3ce44SJohn Forte kmem_free(pp, sizeof (*pp)); 872fcf3ce44SJohn Forte } 873fcf3ce44SJohn Forte 874fcf3ce44SJohn Forte /* 875*6cefaae1SJack Meng * Here may have multiple sessions with different 876*6cefaae1SJack Meng * tpgt values. So it is needed to loop through 877fcf3ce44SJohn Forte * the sessions and update all sessions. 878fcf3ce44SJohn Forte */ 879fcf3ce44SJohn Forte if (rtn == 0) { 880fcf3ce44SJohn Forte rw_enter(&ihp->hba_sess_list_rwlock, RW_READER); 881fcf3ce44SJohn Forte for (isp = ihp->hba_sess_list; isp; 882fcf3ce44SJohn Forte isp = isp->sess_next) { 883*6cefaae1SJack Meng if (iscsiboot_prop && 884*6cefaae1SJack Meng isp->sess_boot && 885*6cefaae1SJack Meng iscsi_chk_bootlun_mpxio(ihp)) { 886*6cefaae1SJack Meng /* 887*6cefaae1SJack Meng * MPxIO is enabled so capable 888*6cefaae1SJack Meng * of changing. All changes 889*6cefaae1SJack Meng * will be applied later, 890*6cefaae1SJack Meng * after this function 891*6cefaae1SJack Meng */ 892*6cefaae1SJack Meng continue; 893*6cefaae1SJack Meng } 894*6cefaae1SJack Meng 895fcf3ce44SJohn Forte if (strncmp((char *)isp->sess_name, 896fcf3ce44SJohn Forte (char *)name, 897fcf3ce44SJohn Forte ISCSI_MAX_NAME_LEN) == 0) { 898fcf3ce44SJohn Forte mutex_enter(&isp->sess_state_mutex); 899fcf3ce44SJohn Forte iscsi_sess_state_machine(isp, ISCSI_SESS_EVENT_N7); 900fcf3ce44SJohn Forte mutex_exit(&isp->sess_state_mutex); 901fcf3ce44SJohn Forte } 902fcf3ce44SJohn Forte } 903fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 904fcf3ce44SJohn Forte } 905fcf3ce44SJohn Forte 906fcf3ce44SJohn Forte } /* end of 'else' */ 907fcf3ce44SJohn Forte 908fcf3ce44SJohn Forte if (params && persist && (rtn == 0)) { 909fcf3ce44SJohn Forte boolean_t rval; 910fcf3ce44SJohn Forte persistent_param_t *pp; 911fcf3ce44SJohn Forte 912fcf3ce44SJohn Forte pp = (persistent_param_t *) 913fcf3ce44SJohn Forte kmem_zalloc(sizeof (*pp), KM_SLEEP); 914fcf3ce44SJohn Forte (void) persistent_param_get((char *)name, pp); 915fcf3ce44SJohn Forte pp->p_bitmap |= (1 << ils->s_param); 916fcf3ce44SJohn Forte bcopy(params, &pp->p_params, sizeof (*params)); 917fcf3ce44SJohn Forte rval = persistent_param_set((char *)name, pp); 918fcf3ce44SJohn Forte if (rval == B_FALSE) { 919fcf3ce44SJohn Forte rtn = EFAULT; 920fcf3ce44SJohn Forte } 921fcf3ce44SJohn Forte kmem_free(pp, sizeof (*pp)); 922fcf3ce44SJohn Forte } 923fcf3ce44SJohn Forte /* 924fcf3ce44SJohn Forte * if initiator parameter set, modify all associated 925fcf3ce44SJohn Forte * sessions that don't already have the parameter 926fcf3ce44SJohn Forte * overriden 927fcf3ce44SJohn Forte */ 928fcf3ce44SJohn Forte if (ils->s_oid == ihp->hba_oid) { 929fcf3ce44SJohn Forte ilg = (iscsi_param_get_t *) 930fcf3ce44SJohn Forte kmem_alloc(sizeof (*ilg), KM_SLEEP); 931fcf3ce44SJohn Forte 932fcf3ce44SJohn Forte rw_enter(&ihp->hba_sess_list_rwlock, RW_READER); 933fcf3ce44SJohn Forte for (isp = ihp->hba_sess_list; isp; 934fcf3ce44SJohn Forte isp = isp->sess_next) { 935fcf3ce44SJohn Forte ilg->g_param = ils->s_param; 936fcf3ce44SJohn Forte params = &isp->sess_params; 937fcf3ce44SJohn Forte if (iscsi_get_persisted_param( 938fcf3ce44SJohn Forte isp->sess_name, ilg, params) != 0) { 939fcf3ce44SJohn Forte rtn = iscsi_set_param(params, ils); 940fcf3ce44SJohn Forte if (rtn != 0) { 941fcf3ce44SJohn Forte break; 942fcf3ce44SJohn Forte } 943*6cefaae1SJack Meng if (iscsiboot_prop && 944*6cefaae1SJack Meng isp->sess_boot && 945*6cefaae1SJack Meng iscsi_chk_bootlun_mpxio(ihp)) { 946*6cefaae1SJack Meng /* 947*6cefaae1SJack Meng * MPxIO is enabled so capable 948*6cefaae1SJack Meng * of changing. Changes will 949*6cefaae1SJack Meng * be applied later, right 950*6cefaae1SJack Meng * after this function 951*6cefaae1SJack Meng */ 952*6cefaae1SJack Meng continue; 953*6cefaae1SJack Meng } 954fcf3ce44SJohn Forte 955fcf3ce44SJohn Forte /* 956fcf3ce44SJohn Forte * Notify the session that 957fcf3ce44SJohn Forte * the login parameters have 958fcf3ce44SJohn Forte * changed. 959fcf3ce44SJohn Forte */ 960fcf3ce44SJohn Forte mutex_enter(&isp-> 961fcf3ce44SJohn Forte sess_state_mutex); 962fcf3ce44SJohn Forte iscsi_sess_state_machine(isp, 963fcf3ce44SJohn Forte ISCSI_SESS_EVENT_N7); 964fcf3ce44SJohn Forte mutex_exit(&isp-> 965fcf3ce44SJohn Forte sess_state_mutex); 966fcf3ce44SJohn Forte } 967fcf3ce44SJohn Forte } 968fcf3ce44SJohn Forte kmem_free(ilg, sizeof (*ilg)); 969fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 970fcf3ce44SJohn Forte } 971fcf3ce44SJohn Forte } 972fcf3ce44SJohn Forte return (rtn); 973fcf3ce44SJohn Forte } 974fcf3ce44SJohn Forte 975fcf3ce44SJohn Forte int 976fcf3ce44SJohn Forte iscsi_target_prop_mod(iscsi_hba_t *ihp, iscsi_property_t *ipp, int cmd) 977fcf3ce44SJohn Forte { 978fcf3ce44SJohn Forte iscsi_sess_t *isp = NULL; 979fcf3ce44SJohn Forte iscsi_conn_t *icp; 980fcf3ce44SJohn Forte int rtn; 981fcf3ce44SJohn Forte char *name; 982fcf3ce44SJohn Forte 983fcf3ce44SJohn Forte /* 984fcf3ce44SJohn Forte * If we're just attempting to get the target properties don't 985fcf3ce44SJohn Forte * create the session if it doesn't already exist. If we setting 986fcf3ce44SJohn Forte * the property then create the session if needed because we'll 987fcf3ce44SJohn Forte * most likely see an ISCSI_LOGIN in a few. 988fcf3ce44SJohn Forte */ 989fcf3ce44SJohn Forte rw_enter(&ihp->hba_sess_list_rwlock, RW_READER); 990fcf3ce44SJohn Forte 991fcf3ce44SJohn Forte /* 992fcf3ce44SJohn Forte * If the oid does represent a session check to see 993fcf3ce44SJohn Forte * if it is a target oid. If so, return the target's 994fcf3ce44SJohn Forte * associated session. 995fcf3ce44SJohn Forte */ 996fcf3ce44SJohn Forte rtn = iscsi_sess_get(ipp->p_oid, ihp, &isp); 997fcf3ce44SJohn Forte if (rtn != 0) { 998fcf3ce44SJohn Forte rtn = iscsi_sess_get_by_target(ipp->p_oid, ihp, &isp); 999fcf3ce44SJohn Forte } 1000fcf3ce44SJohn Forte 1001fcf3ce44SJohn Forte /* 1002fcf3ce44SJohn Forte * If rtn is zero then we have found an existing session. 1003fcf3ce44SJohn Forte * Use the session name for database lookup. If rtn is 1004fcf3ce44SJohn Forte * non-zero then create a targetparam object and use 1005fcf3ce44SJohn Forte * its name for database lookup. 1006fcf3ce44SJohn Forte */ 1007fcf3ce44SJohn Forte if (rtn == 0) { 1008fcf3ce44SJohn Forte name = (char *)isp->sess_name; 1009fcf3ce44SJohn Forte } else { 1010fcf3ce44SJohn Forte name = (char *)iscsi_targetparam_get_name(ipp->p_oid); 1011fcf3ce44SJohn Forte isp = NULL; 1012fcf3ce44SJohn Forte } 1013fcf3ce44SJohn Forte 1014fcf3ce44SJohn Forte if (name == NULL) { 1015fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 1016fcf3ce44SJohn Forte rtn = EFAULT; 1017fcf3ce44SJohn Forte return (rtn); 1018fcf3ce44SJohn Forte } 1019fcf3ce44SJohn Forte 1020fcf3ce44SJohn Forte rtn = 0; 1021fcf3ce44SJohn Forte if (cmd == ISCSI_TARGET_PROPS_GET) { 1022fcf3ce44SJohn Forte /* 1023fcf3ce44SJohn Forte * If isp is not null get the session's parameters, otherwise 1024fcf3ce44SJohn Forte * the get is for a target-param object so defaults need to 1025fcf3ce44SJohn Forte * be returned. 1026fcf3ce44SJohn Forte */ 1027fcf3ce44SJohn Forte if (isp != NULL) { 1028fcf3ce44SJohn Forte int conn_count = 0; 1029fcf3ce44SJohn Forte 1030fcf3ce44SJohn Forte bcopy(isp->sess_alias, ipp->p_alias, 1031fcf3ce44SJohn Forte isp->sess_alias_length); 1032fcf3ce44SJohn Forte bcopy(isp->sess_name, ipp->p_name, 1033fcf3ce44SJohn Forte isp->sess_name_length); 1034fcf3ce44SJohn Forte ipp->p_alias_len = isp->sess_alias_length; 1035fcf3ce44SJohn Forte ipp->p_name_len = isp->sess_name_length; 1036fcf3ce44SJohn Forte ipp->p_discovery = isp->sess_discovered_by; 1037fcf3ce44SJohn Forte ipp->p_last_err = isp->sess_last_err; 1038fcf3ce44SJohn Forte ipp->p_tpgt_conf = isp->sess_tpgt_conf; 1039fcf3ce44SJohn Forte ipp->p_tpgt_nego = isp->sess_tpgt_nego; 1040fcf3ce44SJohn Forte bcopy(isp->sess_isid, ipp->p_isid, ISCSI_ISID_LEN); 1041fcf3ce44SJohn Forte 1042fcf3ce44SJohn Forte rw_enter(&isp->sess_conn_list_rwlock, RW_READER); 1043fcf3ce44SJohn Forte for (icp = isp->sess_conn_list; icp; 1044fcf3ce44SJohn Forte icp = icp->conn_next) { 1045fcf3ce44SJohn Forte if (icp->conn_state == 1046fcf3ce44SJohn Forte ISCSI_CONN_STATE_LOGGED_IN) { 1047fcf3ce44SJohn Forte conn_count++; 1048fcf3ce44SJohn Forte } 1049fcf3ce44SJohn Forte } 1050fcf3ce44SJohn Forte rw_exit(&isp->sess_conn_list_rwlock); 1051fcf3ce44SJohn Forte ipp->p_num_of_connections = conn_count; 1052fcf3ce44SJohn Forte ipp->p_connected = (conn_count > 0) ? B_TRUE : B_FALSE; 1053fcf3ce44SJohn Forte } else { 1054fcf3ce44SJohn Forte bcopy(name, ipp->p_name, strlen(name)); 1055fcf3ce44SJohn Forte ipp->p_name_len = strlen(name); 1056fcf3ce44SJohn Forte bcopy("", ipp->p_alias, strlen("")); 1057fcf3ce44SJohn Forte ipp->p_alias_len = strlen(""); 1058fcf3ce44SJohn Forte ipp->p_discovery = iSCSIDiscoveryMethodUnknown; 1059fcf3ce44SJohn Forte ipp->p_last_err = NoError; 1060fcf3ce44SJohn Forte ipp->p_tpgt_conf = ISCSI_DEFAULT_TPGT; 1061fcf3ce44SJohn Forte ipp->p_tpgt_nego = ISCSI_DEFAULT_TPGT; 1062fcf3ce44SJohn Forte ipp->p_num_of_connections = 0; 1063fcf3ce44SJohn Forte ipp->p_connected = B_FALSE; 1064fcf3ce44SJohn Forte } 1065fcf3ce44SJohn Forte } else { 1066fcf3ce44SJohn Forte if (isp == NULL) { 1067fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 1068fcf3ce44SJohn Forte rtn = EFAULT; 1069fcf3ce44SJohn Forte return (rtn); 1070fcf3ce44SJohn Forte } 1071fcf3ce44SJohn Forte 1072fcf3ce44SJohn Forte /* ISCSI_TARGET_PROPS_SET */ 1073fcf3ce44SJohn Forte /* 1074fcf3ce44SJohn Forte * only update if new, otherwise could clear out alias 1075fcf3ce44SJohn Forte * if just updating the discovery. 1076fcf3ce44SJohn Forte */ 1077fcf3ce44SJohn Forte if (ipp->p_alias_len != 0) { 1078fcf3ce44SJohn Forte bcopy(ipp->p_alias, isp->sess_alias, 1079fcf3ce44SJohn Forte ipp->p_alias_len); 1080fcf3ce44SJohn Forte isp->sess_alias_length = ipp->p_alias_len; 1081fcf3ce44SJohn Forte } 1082fcf3ce44SJohn Forte isp->sess_discovered_by = ipp->p_discovery; 1083fcf3ce44SJohn Forte } 1084fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 1085fcf3ce44SJohn Forte return (rtn); 1086fcf3ce44SJohn Forte } 1087fcf3ce44SJohn Forte 1088fcf3ce44SJohn Forte /* 1089fcf3ce44SJohn Forte * iscsi_ioctl_get_config_sess - gets configured session information 1090fcf3ce44SJohn Forte * 1091fcf3ce44SJohn Forte * This function is an ioctl helper function to get the 1092fcf3ce44SJohn Forte * configured session information from the persistent store. 1093fcf3ce44SJohn Forte */ 1094fcf3ce44SJohn Forte int 1095fcf3ce44SJohn Forte iscsi_ioctl_get_config_sess(iscsi_hba_t *ihp, iscsi_config_sess_t *ics) 1096fcf3ce44SJohn Forte { 1097fcf3ce44SJohn Forte uchar_t *name; 1098fcf3ce44SJohn Forte 1099fcf3ce44SJohn Forte /* Get the matching iscsi node name for the oid */ 1100fcf3ce44SJohn Forte if (ics->ics_oid == ISCSI_INITIATOR_OID) { 1101fcf3ce44SJohn Forte /* initiator name */ 1102fcf3ce44SJohn Forte name = ihp->hba_name; 1103fcf3ce44SJohn Forte } else { 1104fcf3ce44SJohn Forte /* target name */ 1105fcf3ce44SJohn Forte name = iscsi_targetparam_get_name(ics->ics_oid); 1106fcf3ce44SJohn Forte if (name == NULL) { 1107fcf3ce44SJohn Forte /* invalid node name */ 1108fcf3ce44SJohn Forte return (EINVAL); 1109fcf3ce44SJohn Forte } 1110fcf3ce44SJohn Forte } 1111fcf3ce44SJohn Forte 1112fcf3ce44SJohn Forte /* get configured session information */ 1113fcf3ce44SJohn Forte if (persistent_get_config_session((char *)name, ics) == B_FALSE) { 1114fcf3ce44SJohn Forte /* 1115fcf3ce44SJohn Forte * There might not be anything in the database yet. If 1116fcf3ce44SJohn Forte * this is a request for the target check the initiator 1117fcf3ce44SJohn Forte * value. If neither is set return the default value. 1118fcf3ce44SJohn Forte */ 1119fcf3ce44SJohn Forte if (ics->ics_oid != ISCSI_INITIATOR_OID) { 1120fcf3ce44SJohn Forte if (persistent_get_config_session( 1121fcf3ce44SJohn Forte (char *)ihp->hba_name, ics) == B_FALSE) { 1122fcf3ce44SJohn Forte /* 1123fcf3ce44SJohn Forte * No initiator value is set. 1124fcf3ce44SJohn Forte * Return the defaults. 1125fcf3ce44SJohn Forte */ 1126fcf3ce44SJohn Forte ics->ics_out = ISCSI_DEFAULT_SESS_NUM; 1127fcf3ce44SJohn Forte ics->ics_bound = ISCSI_DEFAULT_SESS_BOUND; 1128fcf3ce44SJohn Forte } 1129fcf3ce44SJohn Forte } else { 1130fcf3ce44SJohn Forte ics->ics_out = ISCSI_DEFAULT_SESS_NUM; 1131fcf3ce44SJohn Forte ics->ics_bound = ISCSI_DEFAULT_SESS_BOUND; 1132fcf3ce44SJohn Forte } 1133fcf3ce44SJohn Forte } 1134fcf3ce44SJohn Forte 1135fcf3ce44SJohn Forte return (0); 1136fcf3ce44SJohn Forte } 1137fcf3ce44SJohn Forte 1138fcf3ce44SJohn Forte /* 1139fcf3ce44SJohn Forte * iscsi_ioctl_set_config_sess - sets configured session information 1140fcf3ce44SJohn Forte * 1141fcf3ce44SJohn Forte * This function is an ioctl helper function to set the 1142fcf3ce44SJohn Forte * configured session information in the persistent store. 1143fcf3ce44SJohn Forte * In addition it will notify any active sessions of the 1144fcf3ce44SJohn Forte * changed so this can update binding information. It 1145fcf3ce44SJohn Forte * will also destroy sessions that were removed and add 1146fcf3ce44SJohn Forte * new sessions. 1147fcf3ce44SJohn Forte */ 1148fcf3ce44SJohn Forte int 1149fcf3ce44SJohn Forte iscsi_ioctl_set_config_sess(iscsi_hba_t *ihp, iscsi_config_sess_t *ics) 1150fcf3ce44SJohn Forte { 1151fcf3ce44SJohn Forte uchar_t *name; 1152fcf3ce44SJohn Forte iscsi_sess_t *isp; 1153fcf3ce44SJohn Forte 1154fcf3ce44SJohn Forte /* check range infomration */ 1155fcf3ce44SJohn Forte if ((ics->ics_in < ISCSI_MIN_CONFIG_SESSIONS) || 1156fcf3ce44SJohn Forte (ics->ics_in > ISCSI_MAX_CONFIG_SESSIONS)) { 1157fcf3ce44SJohn Forte /* invalid range information */ 1158fcf3ce44SJohn Forte return (EINVAL); 1159fcf3ce44SJohn Forte } 1160fcf3ce44SJohn Forte 1161fcf3ce44SJohn Forte if (ics->ics_oid == ISCSI_INITIATOR_OID) { 1162fcf3ce44SJohn Forte name = ihp->hba_name; 1163fcf3ce44SJohn Forte } else { 1164fcf3ce44SJohn Forte /* get target name */ 1165fcf3ce44SJohn Forte name = iscsi_targetparam_get_name(ics->ics_oid); 1166fcf3ce44SJohn Forte if (name == NULL) { 1167fcf3ce44SJohn Forte /* invalid node name */ 1168fcf3ce44SJohn Forte return (EINVAL); 1169fcf3ce44SJohn Forte } 1170fcf3ce44SJohn Forte } 1171fcf3ce44SJohn Forte 1172fcf3ce44SJohn Forte /* store the new information */ 1173fcf3ce44SJohn Forte if (persistent_set_config_session((char *)name, ics) == B_FALSE) { 1174fcf3ce44SJohn Forte /* failed to store new information */ 1175fcf3ce44SJohn Forte return (EINVAL); 1176fcf3ce44SJohn Forte } 1177fcf3ce44SJohn Forte 1178fcf3ce44SJohn Forte /* notify existing sessions of change */ 1179fcf3ce44SJohn Forte rw_enter(&ihp->hba_sess_list_rwlock, RW_READER); 1180fcf3ce44SJohn Forte isp = ihp->hba_sess_list; 1181fcf3ce44SJohn Forte while (isp != NULL) { 1182fcf3ce44SJohn Forte 1183fcf3ce44SJohn Forte if ((ics->ics_oid == ISCSI_INITIATOR_OID) || 1184fcf3ce44SJohn Forte (strncmp((char *)isp->sess_name, (char *)name, 1185fcf3ce44SJohn Forte ISCSI_MAX_NAME_LEN) == 0)) { 1186fcf3ce44SJohn Forte 1187fcf3ce44SJohn Forte /* 1188fcf3ce44SJohn Forte * If this sessions least signficant byte 1189fcf3ce44SJohn Forte * of the isid is less than or equal to 1190fcf3ce44SJohn Forte * the the number of configured sessions 1191fcf3ce44SJohn Forte * then we need to tear down this session. 1192fcf3ce44SJohn Forte */ 1193fcf3ce44SJohn Forte if (ics->ics_in <= isp->sess_isid[5]) { 1194fcf3ce44SJohn Forte /* First attempt to destory the session */ 1195fcf3ce44SJohn Forte if (ISCSI_SUCCESS(iscsi_sess_destroy(isp))) { 1196fcf3ce44SJohn Forte isp = ihp->hba_sess_list; 1197fcf3ce44SJohn Forte } else { 1198fcf3ce44SJohn Forte /* 1199fcf3ce44SJohn Forte * If we can't destroy it then 1200fcf3ce44SJohn Forte * atleast poke it to disconnect 1201fcf3ce44SJohn Forte * it. 1202fcf3ce44SJohn Forte */ 1203fcf3ce44SJohn Forte mutex_enter(&isp->sess_state_mutex); 1204fcf3ce44SJohn Forte iscsi_sess_state_machine(isp, 1205fcf3ce44SJohn Forte ISCSI_SESS_EVENT_N7); 1206fcf3ce44SJohn Forte mutex_exit(&isp->sess_state_mutex); 1207fcf3ce44SJohn Forte isp = isp->sess_next; 1208fcf3ce44SJohn Forte } 1209fcf3ce44SJohn Forte } else { 1210fcf3ce44SJohn Forte isp = isp->sess_next; 1211fcf3ce44SJohn Forte } 1212fcf3ce44SJohn Forte } else { 1213fcf3ce44SJohn Forte isp = isp->sess_next; 1214fcf3ce44SJohn Forte } 1215fcf3ce44SJohn Forte } 1216fcf3ce44SJohn Forte rw_exit(&ihp->hba_sess_list_rwlock); 1217fcf3ce44SJohn Forte 1218fcf3ce44SJohn Forte /* 1219fcf3ce44SJohn Forte * The number of targets has changed. Since we don't expect 1220fcf3ce44SJohn Forte * this to be a common operation lets keep the code simple and 1221fcf3ce44SJohn Forte * just use a slightly larger hammer and poke discovery. This 1222fcf3ce44SJohn Forte * force the reevaulation of this target and all other targets. 1223fcf3ce44SJohn Forte */ 1224fcf3ce44SJohn Forte iscsid_poke_discovery(ihp, iSCSIDiscoveryMethodUnknown); 1225fcf3ce44SJohn Forte /* lock so only one config operation occrs */ 1226fcf3ce44SJohn Forte sema_p(&iscsid_config_semaphore); 1227fcf3ce44SJohn Forte iscsid_config_all(ihp, B_FALSE); 1228fcf3ce44SJohn Forte sema_v(&iscsid_config_semaphore); 1229fcf3ce44SJohn Forte 1230fcf3ce44SJohn Forte return (0); 1231fcf3ce44SJohn Forte } 1232