17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM * CDDL HEADER START
37836SJohn.Forte@Sun.COM *
47836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM *
87836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM * and limitations under the License.
127836SJohn.Forte@Sun.COM *
137836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM *
197836SJohn.Forte@Sun.COM * CDDL HEADER END
207836SJohn.Forte@Sun.COM */
217836SJohn.Forte@Sun.COM /*
227836SJohn.Forte@Sun.COM *
23*12161SJack.Meng@Sun.COM * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
247836SJohn.Forte@Sun.COM * iSCSI Software Initiator
257836SJohn.Forte@Sun.COM */
267836SJohn.Forte@Sun.COM
277836SJohn.Forte@Sun.COM /*
287836SJohn.Forte@Sun.COM * Framework interface routines for iSCSI
297836SJohn.Forte@Sun.COM */
309162SPeter.Dunlap@Sun.COM #include "iscsi.h" /* main header */
319162SPeter.Dunlap@Sun.COM #include <sys/idm/idm_text.h> /* main header */
329162SPeter.Dunlap@Sun.COM #include <sys/iscsi_protocol.h> /* protocol structs */
337836SJohn.Forte@Sun.COM #include <sys/scsi/adapters/iscsi_if.h> /* ioctl interfaces */
347836SJohn.Forte@Sun.COM #include "persistent.h"
357836SJohn.Forte@Sun.COM #include <sys/scsi/adapters/iscsi_door.h>
367836SJohn.Forte@Sun.COM #include "iscsi_targetparam.h"
377836SJohn.Forte@Sun.COM #include <sys/strsubr.h>
387836SJohn.Forte@Sun.COM #include <sys/socketvar.h>
398194SJack.Meng@Sun.COM #include <sys/bootprops.h>
408194SJack.Meng@Sun.COM
418194SJack.Meng@Sun.COM extern ib_boot_prop_t *iscsiboot_prop;
427836SJohn.Forte@Sun.COM
437836SJohn.Forte@Sun.COM static iscsi_status_t iscsi_create_sendtgts_list(iscsi_conn_t *icp,
447836SJohn.Forte@Sun.COM char *data, int data_len, iscsi_sendtgts_list_t *stl);
457836SJohn.Forte@Sun.COM
467836SJohn.Forte@Sun.COM /*
477836SJohn.Forte@Sun.COM * iscsi_ioctl_copyin -
487836SJohn.Forte@Sun.COM */
497836SJohn.Forte@Sun.COM void *
iscsi_ioctl_copyin(caddr_t arg,int mode,size_t size)507836SJohn.Forte@Sun.COM iscsi_ioctl_copyin(caddr_t arg, int mode, size_t size)
517836SJohn.Forte@Sun.COM {
527836SJohn.Forte@Sun.COM void *data = NULL;
537836SJohn.Forte@Sun.COM
547836SJohn.Forte@Sun.COM ASSERT(arg != NULL);
557836SJohn.Forte@Sun.COM ASSERT(size != 0);
567836SJohn.Forte@Sun.COM
577836SJohn.Forte@Sun.COM data = kmem_alloc(size, KM_SLEEP);
587836SJohn.Forte@Sun.COM
597836SJohn.Forte@Sun.COM if (ddi_copyin(arg, data, size, mode) != 0) {
607836SJohn.Forte@Sun.COM kmem_free(data, size);
617836SJohn.Forte@Sun.COM data = NULL;
627836SJohn.Forte@Sun.COM }
637836SJohn.Forte@Sun.COM return (data);
647836SJohn.Forte@Sun.COM }
657836SJohn.Forte@Sun.COM
667836SJohn.Forte@Sun.COM /*
677836SJohn.Forte@Sun.COM * iscsi_ioctl_copyout -
687836SJohn.Forte@Sun.COM */
697836SJohn.Forte@Sun.COM int
iscsi_ioctl_copyout(void * data,size_t size,caddr_t arg,int mode)707836SJohn.Forte@Sun.COM iscsi_ioctl_copyout(void *data, size_t size, caddr_t arg, int mode)
717836SJohn.Forte@Sun.COM {
727836SJohn.Forte@Sun.COM int rtn;
737836SJohn.Forte@Sun.COM
747836SJohn.Forte@Sun.COM rtn = EFAULT;
757836SJohn.Forte@Sun.COM if (ddi_copyout(data, arg, size, mode) == 0) {
767836SJohn.Forte@Sun.COM rtn = 0;
777836SJohn.Forte@Sun.COM }
787836SJohn.Forte@Sun.COM kmem_free(data, size);
797836SJohn.Forte@Sun.COM return (rtn);
807836SJohn.Forte@Sun.COM }
817836SJohn.Forte@Sun.COM
827836SJohn.Forte@Sun.COM /*
837836SJohn.Forte@Sun.COM * iscsi_conn_list_get_copyin -
847836SJohn.Forte@Sun.COM */
857836SJohn.Forte@Sun.COM iscsi_conn_list_t *
iscsi_ioctl_conn_oid_list_get_copyin(caddr_t arg,int mode)867836SJohn.Forte@Sun.COM iscsi_ioctl_conn_oid_list_get_copyin(caddr_t arg, int mode)
877836SJohn.Forte@Sun.COM {
887836SJohn.Forte@Sun.COM iscsi_conn_list_t *cl_tmp;
897836SJohn.Forte@Sun.COM iscsi_conn_list_t *cl = NULL;
907836SJohn.Forte@Sun.COM size_t alloc_len;
917836SJohn.Forte@Sun.COM
927836SJohn.Forte@Sun.COM ASSERT(arg != NULL);
937836SJohn.Forte@Sun.COM
947836SJohn.Forte@Sun.COM cl_tmp = (iscsi_conn_list_t *)kmem_zalloc(sizeof (*cl_tmp), KM_SLEEP);
957836SJohn.Forte@Sun.COM
967836SJohn.Forte@Sun.COM if (ddi_copyin(arg, cl_tmp, sizeof (*cl_tmp), mode) == 0) {
977836SJohn.Forte@Sun.COM
987836SJohn.Forte@Sun.COM if (cl_tmp->cl_vers == ISCSI_INTERFACE_VERSION) {
997836SJohn.Forte@Sun.COM alloc_len = sizeof (*cl);
1007836SJohn.Forte@Sun.COM if (cl_tmp->cl_in_cnt != 0) {
1017836SJohn.Forte@Sun.COM alloc_len += ((cl_tmp->cl_in_cnt - 1) *
1027836SJohn.Forte@Sun.COM sizeof (iscsi_if_conn_t));
1037836SJohn.Forte@Sun.COM }
1047836SJohn.Forte@Sun.COM
1057836SJohn.Forte@Sun.COM cl = (iscsi_conn_list_t *)kmem_zalloc(alloc_len,
1067836SJohn.Forte@Sun.COM KM_SLEEP);
1077836SJohn.Forte@Sun.COM bcopy(cl_tmp, cl, sizeof (*cl_tmp));
1087836SJohn.Forte@Sun.COM }
1097836SJohn.Forte@Sun.COM }
1107836SJohn.Forte@Sun.COM kmem_free(cl_tmp, sizeof (*cl_tmp));
1117836SJohn.Forte@Sun.COM return (cl);
1127836SJohn.Forte@Sun.COM }
1137836SJohn.Forte@Sun.COM
1147836SJohn.Forte@Sun.COM /*
1157836SJohn.Forte@Sun.COM * iscsi_conn_list_get_copyout -
1167836SJohn.Forte@Sun.COM */
1177836SJohn.Forte@Sun.COM int
iscsi_ioctl_conn_oid_list_get_copyout(iscsi_conn_list_t * cl,caddr_t arg,int mode)1187836SJohn.Forte@Sun.COM iscsi_ioctl_conn_oid_list_get_copyout(iscsi_conn_list_t *cl, caddr_t arg,
1197836SJohn.Forte@Sun.COM int mode)
1207836SJohn.Forte@Sun.COM {
1217836SJohn.Forte@Sun.COM size_t alloc_len;
1227836SJohn.Forte@Sun.COM int rtn;
1237836SJohn.Forte@Sun.COM
1247836SJohn.Forte@Sun.COM ASSERT(cl != NULL);
1257836SJohn.Forte@Sun.COM ASSERT(arg != NULL);
1267836SJohn.Forte@Sun.COM
1277836SJohn.Forte@Sun.COM rtn = EFAULT;
1287836SJohn.Forte@Sun.COM alloc_len = sizeof (*cl);
1297836SJohn.Forte@Sun.COM if (cl->cl_in_cnt != 0) {
1307836SJohn.Forte@Sun.COM alloc_len += ((cl->cl_in_cnt - 1) * sizeof (iscsi_if_conn_t));
1317836SJohn.Forte@Sun.COM }
1327836SJohn.Forte@Sun.COM
1337836SJohn.Forte@Sun.COM if (ddi_copyout(cl, arg, alloc_len, mode) == 0) {
1347836SJohn.Forte@Sun.COM rtn = 0;
1357836SJohn.Forte@Sun.COM }
1367836SJohn.Forte@Sun.COM kmem_free(cl, alloc_len);
1377836SJohn.Forte@Sun.COM return (rtn);
1387836SJohn.Forte@Sun.COM }
1397836SJohn.Forte@Sun.COM
1407836SJohn.Forte@Sun.COM /*
1417836SJohn.Forte@Sun.COM * iscsi_conn_oid_list_get -
1427836SJohn.Forte@Sun.COM */
1437836SJohn.Forte@Sun.COM boolean_t
iscsi_ioctl_conn_oid_list_get(iscsi_hba_t * ihp,iscsi_conn_list_t * cl)1447836SJohn.Forte@Sun.COM iscsi_ioctl_conn_oid_list_get(iscsi_hba_t *ihp, iscsi_conn_list_t *cl)
1457836SJohn.Forte@Sun.COM {
1467836SJohn.Forte@Sun.COM iscsi_sess_t *isp;
1477836SJohn.Forte@Sun.COM iscsi_conn_t *icp;
1487836SJohn.Forte@Sun.COM iscsi_if_conn_t *cnx;
1497836SJohn.Forte@Sun.COM uint32_t target_oid;
1507836SJohn.Forte@Sun.COM
1517836SJohn.Forte@Sun.COM /* Let's check the version. */
1527836SJohn.Forte@Sun.COM if (cl->cl_vers != ISCSI_INTERFACE_VERSION) {
1537836SJohn.Forte@Sun.COM return (B_FALSE);
1547836SJohn.Forte@Sun.COM }
1557836SJohn.Forte@Sun.COM
1567836SJohn.Forte@Sun.COM /* We preinitialize the output connection counter. */
1577836SJohn.Forte@Sun.COM cl->cl_out_cnt = 0;
1587836SJohn.Forte@Sun.COM
1597836SJohn.Forte@Sun.COM /* The list of sessions is walked holding the HBA mutex. */
1607836SJohn.Forte@Sun.COM rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
1617836SJohn.Forte@Sun.COM isp = ihp->hba_sess_list;
1627836SJohn.Forte@Sun.COM
1637836SJohn.Forte@Sun.COM /*
1647836SJohn.Forte@Sun.COM * Check to see if oid references a target-param oid. If so,
1657836SJohn.Forte@Sun.COM * find the associated session oid before getting lu list.
1667836SJohn.Forte@Sun.COM */
1677836SJohn.Forte@Sun.COM if (iscsi_targetparam_get_name(cl->cl_sess_oid) != NULL) {
1687836SJohn.Forte@Sun.COM for (isp = ihp->hba_sess_list; isp; isp = isp->sess_next) {
1697836SJohn.Forte@Sun.COM if (isp->sess_target_oid == cl->cl_sess_oid) {
1707836SJohn.Forte@Sun.COM target_oid = isp->sess_oid;
1717836SJohn.Forte@Sun.COM break;
1727836SJohn.Forte@Sun.COM }
1737836SJohn.Forte@Sun.COM }
1747836SJohn.Forte@Sun.COM } else {
1757836SJohn.Forte@Sun.COM target_oid = cl->cl_sess_oid;
1767836SJohn.Forte@Sun.COM }
1777836SJohn.Forte@Sun.COM
1787836SJohn.Forte@Sun.COM while (isp != NULL) {
1797836SJohn.Forte@Sun.COM ASSERT(isp->sess_sig == ISCSI_SIG_SESS);
1807836SJohn.Forte@Sun.COM
1817836SJohn.Forte@Sun.COM /* return connections for NORMAL sessions only */
1827836SJohn.Forte@Sun.COM if ((isp->sess_type == ISCSI_SESS_TYPE_NORMAL) &&
1837836SJohn.Forte@Sun.COM ((cl->cl_all_sess == B_TRUE) ||
1847836SJohn.Forte@Sun.COM (target_oid == isp->sess_oid))) {
1857836SJohn.Forte@Sun.COM /*
1867836SJohn.Forte@Sun.COM * The list of connections is walked holding
1877836SJohn.Forte@Sun.COM * the session mutex.
1887836SJohn.Forte@Sun.COM */
1897836SJohn.Forte@Sun.COM rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
1907836SJohn.Forte@Sun.COM icp = isp->sess_conn_list;
1917836SJohn.Forte@Sun.COM
1927836SJohn.Forte@Sun.COM while (icp != NULL) {
1937836SJohn.Forte@Sun.COM ASSERT(icp->conn_sig == ISCSI_SIG_CONN);
1947836SJohn.Forte@Sun.COM
1957836SJohn.Forte@Sun.COM if (icp->conn_state ==
1967836SJohn.Forte@Sun.COM ISCSI_CONN_STATE_LOGGED_IN) {
1977836SJohn.Forte@Sun.COM
1987836SJohn.Forte@Sun.COM if (cl->cl_out_cnt < cl->cl_in_cnt) {
1997836SJohn.Forte@Sun.COM /* There's still room. */
2007836SJohn.Forte@Sun.COM cnx =
2017836SJohn.Forte@Sun.COM &cl->cl_list[
2027836SJohn.Forte@Sun.COM cl->cl_out_cnt];
2037836SJohn.Forte@Sun.COM
2047836SJohn.Forte@Sun.COM bzero(cnx, sizeof (*cnx));
2057836SJohn.Forte@Sun.COM
2067836SJohn.Forte@Sun.COM cnx->c_cid = icp->conn_cid;
2077836SJohn.Forte@Sun.COM cnx->c_oid = icp->conn_oid;
2087836SJohn.Forte@Sun.COM cnx->c_sess_oid = isp->sess_oid;
2097836SJohn.Forte@Sun.COM }
2107836SJohn.Forte@Sun.COM ++cl->cl_out_cnt;
2117836SJohn.Forte@Sun.COM }
2127836SJohn.Forte@Sun.COM icp = icp->conn_next;
2137836SJohn.Forte@Sun.COM }
2147836SJohn.Forte@Sun.COM rw_exit(&isp->sess_conn_list_rwlock);
2157836SJohn.Forte@Sun.COM
2167836SJohn.Forte@Sun.COM if (cl->cl_all_sess == B_FALSE) {
2177836SJohn.Forte@Sun.COM /*
2187836SJohn.Forte@Sun.COM * We got here because it was the only session
2197836SJohn.Forte@Sun.COM * we were looking for. We can exit now.
2207836SJohn.Forte@Sun.COM */
2217836SJohn.Forte@Sun.COM break;
2227836SJohn.Forte@Sun.COM }
2237836SJohn.Forte@Sun.COM }
2247836SJohn.Forte@Sun.COM isp = isp->sess_next;
2257836SJohn.Forte@Sun.COM }
2267836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
2277836SJohn.Forte@Sun.COM return (B_TRUE);
2287836SJohn.Forte@Sun.COM }
2297836SJohn.Forte@Sun.COM
2307836SJohn.Forte@Sun.COM /*
2317836SJohn.Forte@Sun.COM * iscsi_ioctl_conn_props_get -
2327836SJohn.Forte@Sun.COM */
2337836SJohn.Forte@Sun.COM boolean_t
iscsi_ioctl_conn_props_get(iscsi_hba_t * ihp,iscsi_conn_props_t * cp)2347836SJohn.Forte@Sun.COM iscsi_ioctl_conn_props_get(iscsi_hba_t *ihp, iscsi_conn_props_t *cp)
2357836SJohn.Forte@Sun.COM {
2367836SJohn.Forte@Sun.COM iscsi_sess_t *isp;
2377836SJohn.Forte@Sun.COM iscsi_conn_t *icp;
2387836SJohn.Forte@Sun.COM boolean_t rtn;
2399162SPeter.Dunlap@Sun.COM idm_conn_t *idm_conn;
2407836SJohn.Forte@Sun.COM
2417836SJohn.Forte@Sun.COM /* Let's check the version. */
2427836SJohn.Forte@Sun.COM if (cp->cp_vers != ISCSI_INTERFACE_VERSION) {
2437836SJohn.Forte@Sun.COM return (B_FALSE);
2447836SJohn.Forte@Sun.COM }
2457836SJohn.Forte@Sun.COM
2467836SJohn.Forte@Sun.COM /* Let's find the session. */
2477836SJohn.Forte@Sun.COM rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
2487836SJohn.Forte@Sun.COM if (iscsi_sess_get(cp->cp_sess_oid, ihp, &isp) != 0) {
2497836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
2507836SJohn.Forte@Sun.COM return (B_FALSE);
2517836SJohn.Forte@Sun.COM }
2527836SJohn.Forte@Sun.COM
2537836SJohn.Forte@Sun.COM ASSERT(isp->sess_sig == ISCSI_SIG_SESS);
2547836SJohn.Forte@Sun.COM
2557836SJohn.Forte@Sun.COM rtn = B_FALSE;
2567836SJohn.Forte@Sun.COM
2577836SJohn.Forte@Sun.COM rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
2587836SJohn.Forte@Sun.COM icp = isp->sess_conn_list;
2597836SJohn.Forte@Sun.COM cp->cp_params_valid = B_FALSE;
2607836SJohn.Forte@Sun.COM
2617836SJohn.Forte@Sun.COM while (icp != NULL) {
2627836SJohn.Forte@Sun.COM
2637836SJohn.Forte@Sun.COM ASSERT(icp->conn_sig == ISCSI_SIG_CONN);
2647836SJohn.Forte@Sun.COM
2657836SJohn.Forte@Sun.COM if (icp->conn_oid == cp->cp_oid) {
2669162SPeter.Dunlap@Sun.COM struct sockaddr_storage *sal;
2679162SPeter.Dunlap@Sun.COM struct sockaddr_storage *sar;
2689162SPeter.Dunlap@Sun.COM
2699162SPeter.Dunlap@Sun.COM idm_conn =
2709162SPeter.Dunlap@Sun.COM (idm_conn_t *)icp->conn_ic;
2719162SPeter.Dunlap@Sun.COM
2729162SPeter.Dunlap@Sun.COM sal = &idm_conn->ic_laddr;
2739162SPeter.Dunlap@Sun.COM sar = &idm_conn->ic_raddr;
2749162SPeter.Dunlap@Sun.COM
2759162SPeter.Dunlap@Sun.COM /* Local Address */
2769162SPeter.Dunlap@Sun.COM if (sal->ss_family == AF_INET) {
2779162SPeter.Dunlap@Sun.COM bcopy(&idm_conn->ic_laddr,
2789162SPeter.Dunlap@Sun.COM &cp->cp_local,
2799162SPeter.Dunlap@Sun.COM sizeof (struct sockaddr_in));
2809162SPeter.Dunlap@Sun.COM } else {
2819162SPeter.Dunlap@Sun.COM bcopy(&idm_conn->ic_laddr,
2829162SPeter.Dunlap@Sun.COM &cp->cp_local,
2839162SPeter.Dunlap@Sun.COM sizeof (struct sockaddr_in6));
2847836SJohn.Forte@Sun.COM }
2859162SPeter.Dunlap@Sun.COM
2869162SPeter.Dunlap@Sun.COM /* Peer Address */
2879162SPeter.Dunlap@Sun.COM if (sar->ss_family == AF_INET) {
2889162SPeter.Dunlap@Sun.COM bcopy(&idm_conn->ic_raddr,
2899162SPeter.Dunlap@Sun.COM &cp->cp_peer,
2909162SPeter.Dunlap@Sun.COM sizeof (struct sockaddr_in));
2919162SPeter.Dunlap@Sun.COM } else {
2929162SPeter.Dunlap@Sun.COM bcopy(&idm_conn->ic_raddr,
2939162SPeter.Dunlap@Sun.COM &cp->cp_peer,
2949162SPeter.Dunlap@Sun.COM sizeof (struct sockaddr_in6));
2957836SJohn.Forte@Sun.COM }
2967836SJohn.Forte@Sun.COM
2977836SJohn.Forte@Sun.COM if (icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN) {
2987836SJohn.Forte@Sun.COM cp->cp_params_valid = B_TRUE;
2997836SJohn.Forte@Sun.COM bcopy(&icp->conn_params, &cp->cp_params,
3007836SJohn.Forte@Sun.COM sizeof (icp->conn_params));
3017836SJohn.Forte@Sun.COM }
3027836SJohn.Forte@Sun.COM
3037836SJohn.Forte@Sun.COM rtn = B_TRUE;
3047836SJohn.Forte@Sun.COM break;
3057836SJohn.Forte@Sun.COM }
3067836SJohn.Forte@Sun.COM icp = icp->conn_next;
3077836SJohn.Forte@Sun.COM }
3087836SJohn.Forte@Sun.COM rw_exit(&isp->sess_conn_list_rwlock);
3097836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
3107836SJohn.Forte@Sun.COM return (rtn);
3117836SJohn.Forte@Sun.COM }
3127836SJohn.Forte@Sun.COM
3137836SJohn.Forte@Sun.COM
3147836SJohn.Forte@Sun.COM /*
3157836SJohn.Forte@Sun.COM * iscsi_ioctl_sendtgts_get - 0 on success; errno on failure
3167836SJohn.Forte@Sun.COM *
3177836SJohn.Forte@Sun.COM */
3187836SJohn.Forte@Sun.COM int
iscsi_ioctl_sendtgts_get(iscsi_hba_t * ihp,iscsi_sendtgts_list_t * stl)3197836SJohn.Forte@Sun.COM iscsi_ioctl_sendtgts_get(iscsi_hba_t *ihp, iscsi_sendtgts_list_t *stl)
3207836SJohn.Forte@Sun.COM {
3217836SJohn.Forte@Sun.COM #define ISCSI_SENDTGTS_REQ_STR "SendTargets=All"
3227836SJohn.Forte@Sun.COM
3237836SJohn.Forte@Sun.COM int rtn = EFAULT;
3247836SJohn.Forte@Sun.COM iscsi_status_t status;
3257836SJohn.Forte@Sun.COM iscsi_sess_t *isp;
3267836SJohn.Forte@Sun.COM iscsi_conn_t *icp;
3277836SJohn.Forte@Sun.COM uint32_t oid;
3287836SJohn.Forte@Sun.COM char *data;
3297836SJohn.Forte@Sun.COM uint32_t data_len;
3307836SJohn.Forte@Sun.COM uint32_t rx_data_len;
3317836SJohn.Forte@Sun.COM iscsi_sockaddr_t addr_snd;
3327836SJohn.Forte@Sun.COM
3337836SJohn.Forte@Sun.COM ASSERT(ihp != NULL);
3347836SJohn.Forte@Sun.COM ASSERT(stl != NULL);
3357836SJohn.Forte@Sun.COM
3367836SJohn.Forte@Sun.COM iscsid_addr_to_sockaddr(stl->stl_entry.e_insize,
3377836SJohn.Forte@Sun.COM &stl->stl_entry.e_u, stl->stl_entry.e_port,
3387836SJohn.Forte@Sun.COM &addr_snd.sin);
3397836SJohn.Forte@Sun.COM
3407836SJohn.Forte@Sun.COM /* create discovery session */
3417836SJohn.Forte@Sun.COM rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
3427836SJohn.Forte@Sun.COM isp = iscsi_sess_create(ihp, iSCSIDiscoveryMethodSendTargets,
3437836SJohn.Forte@Sun.COM NULL, SENDTARGETS_DISCOVERY, ISCSI_DEFAULT_TPGT,
3447836SJohn.Forte@Sun.COM ISCSI_SUN_ISID_5, ISCSI_SESS_TYPE_DISCOVERY, &oid);
3457836SJohn.Forte@Sun.COM if (isp == NULL) {
3467836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
3477836SJohn.Forte@Sun.COM return (1);
3487836SJohn.Forte@Sun.COM }
3497836SJohn.Forte@Sun.COM
3507836SJohn.Forte@Sun.COM /* create connection */
3517836SJohn.Forte@Sun.COM rw_enter(&isp->sess_conn_list_rwlock, RW_WRITER);
3527836SJohn.Forte@Sun.COM status = iscsi_conn_create(&addr_snd.sin, isp, &icp);
3537836SJohn.Forte@Sun.COM rw_exit(&isp->sess_conn_list_rwlock);
3547836SJohn.Forte@Sun.COM
3557836SJohn.Forte@Sun.COM if (!ISCSI_SUCCESS(status)) {
3567836SJohn.Forte@Sun.COM (void) iscsi_sess_destroy(isp);
3577836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
3587836SJohn.Forte@Sun.COM return (1);
3597836SJohn.Forte@Sun.COM }
3607836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
3617836SJohn.Forte@Sun.COM
3627836SJohn.Forte@Sun.COM /* start login */
3637836SJohn.Forte@Sun.COM mutex_enter(&icp->conn_state_mutex);
3649162SPeter.Dunlap@Sun.COM status = iscsi_conn_online(icp);
3657836SJohn.Forte@Sun.COM mutex_exit(&icp->conn_state_mutex);
3667836SJohn.Forte@Sun.COM
3679162SPeter.Dunlap@Sun.COM if (status == ISCSI_STATUS_SUCCESS) {
3687836SJohn.Forte@Sun.COM data_len = icp->conn_params.max_xmit_data_seg_len;
3697836SJohn.Forte@Sun.COM retry_sendtgts:
3707836SJohn.Forte@Sun.COM /* alloc/init buffer for SendTargets req/resp */
3717836SJohn.Forte@Sun.COM data = kmem_zalloc(data_len, KM_SLEEP);
3727836SJohn.Forte@Sun.COM bcopy(ISCSI_SENDTGTS_REQ_STR, data,
3737836SJohn.Forte@Sun.COM sizeof (ISCSI_SENDTGTS_REQ_STR));
3747836SJohn.Forte@Sun.COM
3757836SJohn.Forte@Sun.COM /* execute SendTargets operation */
3767836SJohn.Forte@Sun.COM status = iscsi_handle_text(icp, data, data_len,
3777836SJohn.Forte@Sun.COM sizeof (ISCSI_SENDTGTS_REQ_STR), &rx_data_len);
3787836SJohn.Forte@Sun.COM
3797836SJohn.Forte@Sun.COM /* check if allocated buffer is too small for response */
3807836SJohn.Forte@Sun.COM if (status == ISCSI_STATUS_DATA_OVERFLOW) {
3817836SJohn.Forte@Sun.COM kmem_free(data, data_len);
3827836SJohn.Forte@Sun.COM data_len = rx_data_len;
3837836SJohn.Forte@Sun.COM goto retry_sendtgts;
3847836SJohn.Forte@Sun.COM }
3857836SJohn.Forte@Sun.COM
3867836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(status)) {
3877836SJohn.Forte@Sun.COM status = iscsi_create_sendtgts_list(icp, data,
3887836SJohn.Forte@Sun.COM rx_data_len, stl);
3897836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(status)) {
3907836SJohn.Forte@Sun.COM rtn = 0;
3917836SJohn.Forte@Sun.COM }
3927836SJohn.Forte@Sun.COM } else {
3937836SJohn.Forte@Sun.COM rtn = EFAULT;
3947836SJohn.Forte@Sun.COM }
3957836SJohn.Forte@Sun.COM
3967836SJohn.Forte@Sun.COM kmem_free(data, data_len);
3977836SJohn.Forte@Sun.COM } else {
3987836SJohn.Forte@Sun.COM rtn = EFAULT;
3997836SJohn.Forte@Sun.COM }
4007836SJohn.Forte@Sun.COM
4017836SJohn.Forte@Sun.COM /*
4027836SJohn.Forte@Sun.COM * check if session is still alive. It may have been destroyed
4037836SJohn.Forte@Sun.COM * by a driver unload
4047836SJohn.Forte@Sun.COM */
4057836SJohn.Forte@Sun.COM rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
4067836SJohn.Forte@Sun.COM if (iscsi_sess_get(oid, ihp, &isp) == 0) {
4077836SJohn.Forte@Sun.COM (void) iscsi_sess_destroy(isp);
4087836SJohn.Forte@Sun.COM }
4097836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
4107836SJohn.Forte@Sun.COM
4117836SJohn.Forte@Sun.COM return (rtn);
4127836SJohn.Forte@Sun.COM }
4137836SJohn.Forte@Sun.COM
4147836SJohn.Forte@Sun.COM
4157836SJohn.Forte@Sun.COM /*
4167836SJohn.Forte@Sun.COM * iscsi_create_sendtgts_list - Based upon the given data, build a
4177836SJohn.Forte@Sun.COM * linked list of SendTarget information. The data passed into this
4187836SJohn.Forte@Sun.COM * function is expected to be the data portion(s) of SendTarget text
4197836SJohn.Forte@Sun.COM * response.
4207836SJohn.Forte@Sun.COM */
4217836SJohn.Forte@Sun.COM static iscsi_status_t
iscsi_create_sendtgts_list(iscsi_conn_t * icp,char * data,int data_len,iscsi_sendtgts_list_t * stl)4227836SJohn.Forte@Sun.COM iscsi_create_sendtgts_list(iscsi_conn_t *icp, char *data, int data_len,
4237836SJohn.Forte@Sun.COM iscsi_sendtgts_list_t *stl)
4247836SJohn.Forte@Sun.COM {
4257836SJohn.Forte@Sun.COM char *line = NULL;
4267836SJohn.Forte@Sun.COM boolean_t targetname_added = B_FALSE;
4277836SJohn.Forte@Sun.COM iscsi_sendtgts_entry_t *curr_ste = NULL,
4287836SJohn.Forte@Sun.COM *prev_ste = NULL;
4297836SJohn.Forte@Sun.COM struct hostent *hptr;
4307836SJohn.Forte@Sun.COM int error_num;
4317836SJohn.Forte@Sun.COM
4327836SJohn.Forte@Sun.COM /* initialize number of targets found */
4337836SJohn.Forte@Sun.COM stl->stl_out_cnt = 0;
4347836SJohn.Forte@Sun.COM
4357836SJohn.Forte@Sun.COM if (data_len == 0)
4367836SJohn.Forte@Sun.COM return (ISCSI_STATUS_SUCCESS);
4377836SJohn.Forte@Sun.COM
4387836SJohn.Forte@Sun.COM while ((line = iscsi_get_next_text(data, data_len, line)) != NULL) {
4397836SJohn.Forte@Sun.COM if (strncmp(TARGETNAME, line, strlen(TARGETNAME)) == 0) {
4407836SJohn.Forte@Sun.COM /* check if this is first targetname */
4417836SJohn.Forte@Sun.COM if (prev_ste != NULL) {
4427836SJohn.Forte@Sun.COM stl->stl_out_cnt++;
4437836SJohn.Forte@Sun.COM }
4447836SJohn.Forte@Sun.COM if (stl->stl_out_cnt >= stl->stl_in_cnt) {
4457836SJohn.Forte@Sun.COM /*
4467836SJohn.Forte@Sun.COM * continue processing the data so that
4477836SJohn.Forte@Sun.COM * the total number of targets are known
4487836SJohn.Forte@Sun.COM * and the caller can retry with the correct
4497836SJohn.Forte@Sun.COM * number of entries in the list
4507836SJohn.Forte@Sun.COM */
4517836SJohn.Forte@Sun.COM continue;
4527836SJohn.Forte@Sun.COM }
4537836SJohn.Forte@Sun.COM curr_ste = &(stl->stl_list[stl->stl_out_cnt]);
4547836SJohn.Forte@Sun.COM
4557836SJohn.Forte@Sun.COM /*
4567836SJohn.Forte@Sun.COM * This entry will use the IP address and port
4577836SJohn.Forte@Sun.COM * that was passed into this routine. If the next
4587836SJohn.Forte@Sun.COM * line that we receive is a TargetAddress we will
4597836SJohn.Forte@Sun.COM * know to modify this entry with the new IP address,
4607836SJohn.Forte@Sun.COM * port and portal group tag. If this state flag
4617836SJohn.Forte@Sun.COM * is not set we'll just create a new entry using
4627836SJohn.Forte@Sun.COM * only the previous entries targetname.
4637836SJohn.Forte@Sun.COM */
4647836SJohn.Forte@Sun.COM (void) strncpy((char *)curr_ste->ste_name,
4657836SJohn.Forte@Sun.COM line + strlen(TARGETNAME),
4667836SJohn.Forte@Sun.COM sizeof (curr_ste->ste_name));
4677836SJohn.Forte@Sun.COM
4687836SJohn.Forte@Sun.COM if (icp->conn_base_addr.sin.sa_family == AF_INET) {
4697836SJohn.Forte@Sun.COM
4707836SJohn.Forte@Sun.COM struct sockaddr_in *addr_in =
4717836SJohn.Forte@Sun.COM &icp->conn_base_addr.sin4;
4727836SJohn.Forte@Sun.COM curr_ste->ste_ipaddr.a_addr.i_insize =
4737836SJohn.Forte@Sun.COM sizeof (struct in_addr);
4747836SJohn.Forte@Sun.COM bcopy(&addr_in->sin_addr.s_addr,
4757836SJohn.Forte@Sun.COM &curr_ste->ste_ipaddr.a_addr.i_addr,
4767836SJohn.Forte@Sun.COM sizeof (struct in_addr));
4777836SJohn.Forte@Sun.COM curr_ste->ste_ipaddr.a_port =
4787836SJohn.Forte@Sun.COM htons(addr_in->sin_port);
4797836SJohn.Forte@Sun.COM
4807836SJohn.Forte@Sun.COM } else {
4817836SJohn.Forte@Sun.COM
4827836SJohn.Forte@Sun.COM struct sockaddr_in6 *addr_in6 =
4837836SJohn.Forte@Sun.COM &icp->conn_base_addr.sin6;
4847836SJohn.Forte@Sun.COM curr_ste->ste_ipaddr.a_addr.i_insize =
4857836SJohn.Forte@Sun.COM sizeof (struct in6_addr);
4867836SJohn.Forte@Sun.COM bcopy(&addr_in6->sin6_addr.s6_addr,
4877836SJohn.Forte@Sun.COM &curr_ste->ste_ipaddr.a_addr.i_addr,
4887836SJohn.Forte@Sun.COM sizeof (struct in6_addr));
4897836SJohn.Forte@Sun.COM curr_ste->ste_ipaddr.a_port =
4907836SJohn.Forte@Sun.COM htons(addr_in6->sin6_port);
4917836SJohn.Forte@Sun.COM }
4927836SJohn.Forte@Sun.COM curr_ste->ste_tpgt = -1;
4937836SJohn.Forte@Sun.COM
4947836SJohn.Forte@Sun.COM targetname_added = B_TRUE;
4957836SJohn.Forte@Sun.COM
4967836SJohn.Forte@Sun.COM } else if (strncmp(TARGETADDRESS, line,
4977836SJohn.Forte@Sun.COM strlen(TARGETADDRESS)) == 0) {
4987836SJohn.Forte@Sun.COM
4997836SJohn.Forte@Sun.COM char *in_str,
5007836SJohn.Forte@Sun.COM *tmp_buf,
5017836SJohn.Forte@Sun.COM *addr_str,
5027836SJohn.Forte@Sun.COM *port_str,
5037836SJohn.Forte@Sun.COM *tpgt_str;
5047836SJohn.Forte@Sun.COM int type,
5057836SJohn.Forte@Sun.COM tmp_buf_len;
5067836SJohn.Forte@Sun.COM long result;
5077836SJohn.Forte@Sun.COM
5087836SJohn.Forte@Sun.COM /*
5097836SJohn.Forte@Sun.COM * If TARGETADDRESS is first line a SendTarget response
5107836SJohn.Forte@Sun.COM * (i.e. no TARGETNAME lines preceding), treat as
5117836SJohn.Forte@Sun.COM * an error. To check this an assumption is made that
5127836SJohn.Forte@Sun.COM * at least one sendtarget_entry_t should exist prior
5137836SJohn.Forte@Sun.COM * to entering this code.
5147836SJohn.Forte@Sun.COM */
5157836SJohn.Forte@Sun.COM if (prev_ste == NULL) {
5167836SJohn.Forte@Sun.COM cmn_err(CE_NOTE, "SendTargets protocol error: "
5177836SJohn.Forte@Sun.COM "TARGETADDRESS first");
5187836SJohn.Forte@Sun.COM return (ISCSI_STATUS_PROTOCOL_ERROR);
5197836SJohn.Forte@Sun.COM }
5207836SJohn.Forte@Sun.COM
5217836SJohn.Forte@Sun.COM /*
5227836SJohn.Forte@Sun.COM * If we can't find an '=' then the sendtargets
5237836SJohn.Forte@Sun.COM * response if invalid per spec. Return empty list.
5247836SJohn.Forte@Sun.COM */
5257836SJohn.Forte@Sun.COM in_str = strchr(line, '=');
5267836SJohn.Forte@Sun.COM if (in_str == NULL) {
5277836SJohn.Forte@Sun.COM return (ISCSI_STATUS_PROTOCOL_ERROR);
5287836SJohn.Forte@Sun.COM }
5297836SJohn.Forte@Sun.COM
5307836SJohn.Forte@Sun.COM /* move past the '=' */
5317836SJohn.Forte@Sun.COM in_str++;
5327836SJohn.Forte@Sun.COM
5337836SJohn.Forte@Sun.COM /* Copy addr, port, and tpgt into temporary buffer */
5347836SJohn.Forte@Sun.COM tmp_buf_len = strlen(in_str) + 1;
5357836SJohn.Forte@Sun.COM tmp_buf = kmem_zalloc(tmp_buf_len, KM_SLEEP);
5367836SJohn.Forte@Sun.COM (void) strncpy(tmp_buf, in_str, tmp_buf_len);
5377836SJohn.Forte@Sun.COM
5387836SJohn.Forte@Sun.COM /*
5397836SJohn.Forte@Sun.COM * Parse the addr, port, and tpgt from
5407836SJohn.Forte@Sun.COM * sendtarget response
5417836SJohn.Forte@Sun.COM */
5427836SJohn.Forte@Sun.COM if (parse_addr_port_tpgt(tmp_buf, &addr_str, &type,
5437836SJohn.Forte@Sun.COM &port_str, &tpgt_str) == B_FALSE) {
5447836SJohn.Forte@Sun.COM /* Unable to extract addr */
5457836SJohn.Forte@Sun.COM kmem_free(tmp_buf, tmp_buf_len);
5467836SJohn.Forte@Sun.COM return (ISCSI_STATUS_PROTOCOL_ERROR);
5477836SJohn.Forte@Sun.COM }
5487836SJohn.Forte@Sun.COM
5497836SJohn.Forte@Sun.COM /* Now convert string addr to binary */
5507836SJohn.Forte@Sun.COM hptr = kgetipnodebyname(addr_str, type,
5517836SJohn.Forte@Sun.COM AI_ALL, &error_num);
5527836SJohn.Forte@Sun.COM if (!hptr) {
5537836SJohn.Forte@Sun.COM /* Unable to get valid address */
5547836SJohn.Forte@Sun.COM kmem_free(tmp_buf, tmp_buf_len);
5557836SJohn.Forte@Sun.COM return (ISCSI_STATUS_PROTOCOL_ERROR);
5567836SJohn.Forte@Sun.COM }
5577836SJohn.Forte@Sun.COM
5587836SJohn.Forte@Sun.COM /* Check if space for response */
5597836SJohn.Forte@Sun.COM if (targetname_added == B_FALSE) {
5607836SJohn.Forte@Sun.COM stl->stl_out_cnt++;
5617836SJohn.Forte@Sun.COM if (stl->stl_out_cnt >= stl->stl_in_cnt) {
5627836SJohn.Forte@Sun.COM /*
5637836SJohn.Forte@Sun.COM * continue processing the data so that
5647836SJohn.Forte@Sun.COM * the total number of targets are
5657836SJohn.Forte@Sun.COM * known and the caller can retry with
5667836SJohn.Forte@Sun.COM * the correct number of entries in
5677836SJohn.Forte@Sun.COM * the list
5687836SJohn.Forte@Sun.COM */
5697836SJohn.Forte@Sun.COM kfreehostent(hptr);
5707836SJohn.Forte@Sun.COM kmem_free(tmp_buf, tmp_buf_len);
5717836SJohn.Forte@Sun.COM continue;
5727836SJohn.Forte@Sun.COM }
5737836SJohn.Forte@Sun.COM curr_ste = &(stl->stl_list[stl->stl_out_cnt]);
5747836SJohn.Forte@Sun.COM (void) strcpy((char *)curr_ste->ste_name,
5757836SJohn.Forte@Sun.COM (char *)prev_ste->ste_name);
5767836SJohn.Forte@Sun.COM }
5777836SJohn.Forte@Sun.COM
5787836SJohn.Forte@Sun.COM curr_ste->ste_ipaddr.a_addr.i_insize = hptr->h_length;
5797836SJohn.Forte@Sun.COM bcopy(*hptr->h_addr_list,
5807836SJohn.Forte@Sun.COM &(curr_ste->ste_ipaddr.a_addr.i_addr),
5817836SJohn.Forte@Sun.COM curr_ste->ste_ipaddr.a_addr.i_insize);
5827836SJohn.Forte@Sun.COM kfreehostent(hptr);
5837836SJohn.Forte@Sun.COM
5847836SJohn.Forte@Sun.COM if (port_str != NULL) {
5857836SJohn.Forte@Sun.COM (void) ddi_strtol(port_str, NULL, 0, &result);
5867836SJohn.Forte@Sun.COM curr_ste->ste_ipaddr.a_port = (short)result;
5877836SJohn.Forte@Sun.COM } else {
5887836SJohn.Forte@Sun.COM curr_ste->ste_ipaddr.a_port = ISCSI_LISTEN_PORT;
5897836SJohn.Forte@Sun.COM }
5907836SJohn.Forte@Sun.COM
5917836SJohn.Forte@Sun.COM if (tpgt_str != NULL) {
5927836SJohn.Forte@Sun.COM (void) ddi_strtol(tpgt_str, NULL, 0, &result);
5937836SJohn.Forte@Sun.COM curr_ste->ste_tpgt = (short)result;
5947836SJohn.Forte@Sun.COM } else {
5957836SJohn.Forte@Sun.COM cmn_err(CE_NOTE, "SendTargets protocol error: "
5967836SJohn.Forte@Sun.COM "TPGT not specified");
5977836SJohn.Forte@Sun.COM kmem_free(tmp_buf, tmp_buf_len);
5987836SJohn.Forte@Sun.COM return (ISCSI_STATUS_PROTOCOL_ERROR);
5997836SJohn.Forte@Sun.COM }
6007836SJohn.Forte@Sun.COM
6017836SJohn.Forte@Sun.COM kmem_free(tmp_buf, tmp_buf_len);
6027836SJohn.Forte@Sun.COM
6037836SJohn.Forte@Sun.COM targetname_added = B_FALSE;
6047836SJohn.Forte@Sun.COM
6057836SJohn.Forte@Sun.COM } else if (strlen(line) != 0) {
6067836SJohn.Forte@Sun.COM /*
6077836SJohn.Forte@Sun.COM * Any other string besides an empty string
6087836SJohn.Forte@Sun.COM * is a protocol error
6097836SJohn.Forte@Sun.COM */
6107836SJohn.Forte@Sun.COM cmn_err(CE_NOTE, "SendTargets protocol error: "
6117836SJohn.Forte@Sun.COM "unexpected response");
6127836SJohn.Forte@Sun.COM return (ISCSI_STATUS_PROTOCOL_ERROR);
6137836SJohn.Forte@Sun.COM }
6147836SJohn.Forte@Sun.COM
6157836SJohn.Forte@Sun.COM prev_ste = curr_ste;
6167836SJohn.Forte@Sun.COM }
6177836SJohn.Forte@Sun.COM
6187836SJohn.Forte@Sun.COM /*
6197836SJohn.Forte@Sun.COM * If target found increment out count one more time because
6207836SJohn.Forte@Sun.COM * this is the total number of entries in the list not an index
6217836SJohn.Forte@Sun.COM * like it was used above
6227836SJohn.Forte@Sun.COM */
6237836SJohn.Forte@Sun.COM if (prev_ste != NULL) {
6247836SJohn.Forte@Sun.COM stl->stl_out_cnt++;
6257836SJohn.Forte@Sun.COM }
6267836SJohn.Forte@Sun.COM
6277836SJohn.Forte@Sun.COM return (ISCSI_STATUS_SUCCESS);
6287836SJohn.Forte@Sun.COM }
6297836SJohn.Forte@Sun.COM
6307836SJohn.Forte@Sun.COM /*
6317836SJohn.Forte@Sun.COM * iscsi_set_param - This function is a helper to ISCSI_SET_PARAM
6327836SJohn.Forte@Sun.COM * IOCTL
6337836SJohn.Forte@Sun.COM */
6347836SJohn.Forte@Sun.COM int
iscsi_set_param(iscsi_login_params_t * params,iscsi_param_set_t * ipsp)6357836SJohn.Forte@Sun.COM iscsi_set_param(iscsi_login_params_t *params, iscsi_param_set_t *ipsp)
6367836SJohn.Forte@Sun.COM {
6377836SJohn.Forte@Sun.COM int rtn = 0;
6387836SJohn.Forte@Sun.COM iscsi_param_get_t *ipgp;
6397836SJohn.Forte@Sun.COM
6407836SJohn.Forte@Sun.COM /*
6417836SJohn.Forte@Sun.COM * Use get param to get the min, max and increment values for the
6427836SJohn.Forte@Sun.COM * given parameter so validation can be done on the new value.
6437836SJohn.Forte@Sun.COM */
6447836SJohn.Forte@Sun.COM ipgp = (iscsi_param_get_t *)kmem_alloc(sizeof (*ipgp), KM_SLEEP);
6457836SJohn.Forte@Sun.COM ipgp->g_param = ipsp->s_param;
6467836SJohn.Forte@Sun.COM rtn = iscsi_get_param(params, B_TRUE, ipgp);
6477836SJohn.Forte@Sun.COM if (rtn != 0) {
6487836SJohn.Forte@Sun.COM kmem_free(ipgp, sizeof (*ipgp));
6497836SJohn.Forte@Sun.COM return (rtn);
6507836SJohn.Forte@Sun.COM }
6517836SJohn.Forte@Sun.COM
6527836SJohn.Forte@Sun.COM if (ipsp->s_param == ISCSI_LOGIN_PARAM_HEADER_DIGEST ||
6537836SJohn.Forte@Sun.COM ipsp->s_param == ISCSI_LOGIN_PARAM_DATA_DIGEST ||
6547836SJohn.Forte@Sun.COM ipsp->s_param == ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN ||
6557836SJohn.Forte@Sun.COM ipsp->s_param == ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT ||
6567836SJohn.Forte@Sun.COM ipsp->s_param == ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH ||
6577836SJohn.Forte@Sun.COM ipsp->s_param == ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH ||
6587836SJohn.Forte@Sun.COM ipsp->s_param == ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH) {
6597836SJohn.Forte@Sun.COM
6607836SJohn.Forte@Sun.COM if (ipsp->s_value.v_integer < ipgp->g_value.v_integer.i_min ||
6617836SJohn.Forte@Sun.COM ipsp->s_value.v_integer > ipgp->g_value.v_integer.i_max ||
6627836SJohn.Forte@Sun.COM (ipsp->s_value.v_integer %
6637836SJohn.Forte@Sun.COM ipgp->g_value.v_integer.i_incr) != 0) {
6647836SJohn.Forte@Sun.COM rtn = EINVAL;
6657836SJohn.Forte@Sun.COM kmem_free(ipgp, sizeof (*ipgp));
6667836SJohn.Forte@Sun.COM return (rtn);
6677836SJohn.Forte@Sun.COM }
6687836SJohn.Forte@Sun.COM
6697836SJohn.Forte@Sun.COM }
6707836SJohn.Forte@Sun.COM kmem_free(ipgp, sizeof (*ipgp));
6717836SJohn.Forte@Sun.COM
6727836SJohn.Forte@Sun.COM
6737836SJohn.Forte@Sun.COM switch (ipsp->s_param) {
6747836SJohn.Forte@Sun.COM
6757836SJohn.Forte@Sun.COM /*
6767836SJohn.Forte@Sun.COM * Boolean parameters
6777836SJohn.Forte@Sun.COM */
6787836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER:
6797836SJohn.Forte@Sun.COM params->data_sequence_in_order = ipsp->s_value.v_bool;
6807836SJohn.Forte@Sun.COM break;
6817836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_IMMEDIATE_DATA:
6827836SJohn.Forte@Sun.COM params->immediate_data = ipsp->s_value.v_bool;
6837836SJohn.Forte@Sun.COM break;
6847836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_INITIAL_R2T:
6857836SJohn.Forte@Sun.COM params->initial_r2t = ipsp->s_value.v_bool;
6867836SJohn.Forte@Sun.COM break;
6877836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER:
6887836SJohn.Forte@Sun.COM params->data_pdu_in_order = ipsp->s_value.v_bool;
6897836SJohn.Forte@Sun.COM break;
6907836SJohn.Forte@Sun.COM
6917836SJohn.Forte@Sun.COM /*
6927836SJohn.Forte@Sun.COM * Integer parameters
6937836SJohn.Forte@Sun.COM */
6947836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_HEADER_DIGEST:
6957836SJohn.Forte@Sun.COM params->header_digest = ipsp->s_value.v_integer;
6967836SJohn.Forte@Sun.COM break;
6977836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_DATA_DIGEST:
6987836SJohn.Forte@Sun.COM params->data_digest = ipsp->s_value.v_integer;
6997836SJohn.Forte@Sun.COM break;
7007836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN:
7017836SJohn.Forte@Sun.COM params->default_time_to_retain = ipsp->s_value.v_integer;
7027836SJohn.Forte@Sun.COM break;
7037836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT:
7047836SJohn.Forte@Sun.COM params->default_time_to_wait = ipsp->s_value.v_integer;
7057836SJohn.Forte@Sun.COM break;
7067836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH:
7077836SJohn.Forte@Sun.COM params->max_recv_data_seg_len = ipsp->s_value.v_integer;
7087836SJohn.Forte@Sun.COM break;
7097836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH:
7107836SJohn.Forte@Sun.COM if (ipsp->s_value.v_integer <= params->max_burst_length) {
7117836SJohn.Forte@Sun.COM params->first_burst_length = ipsp->s_value.v_integer;
7127836SJohn.Forte@Sun.COM } else {
7137836SJohn.Forte@Sun.COM rtn = EINVAL;
7147836SJohn.Forte@Sun.COM }
7157836SJohn.Forte@Sun.COM break;
7167836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH:
7177836SJohn.Forte@Sun.COM if (ipsp->s_value.v_integer >= params->first_burst_length) {
7187836SJohn.Forte@Sun.COM params->max_burst_length = ipsp->s_value.v_integer;
7197836SJohn.Forte@Sun.COM } else {
7207836SJohn.Forte@Sun.COM rtn = EINVAL;
7217836SJohn.Forte@Sun.COM }
7227836SJohn.Forte@Sun.COM break;
7237836SJohn.Forte@Sun.COM
7247836SJohn.Forte@Sun.COM /*
7257836SJohn.Forte@Sun.COM * Integer parameters which currently are unsettable
7267836SJohn.Forte@Sun.COM */
7277836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_MAX_CONNECTIONS:
7287836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_OUTSTANDING_R2T:
7297836SJohn.Forte@Sun.COM case ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL:
7307836SJohn.Forte@Sun.COM rtn = ENOTSUP;
7317836SJohn.Forte@Sun.COM break;
7327836SJohn.Forte@Sun.COM
7337836SJohn.Forte@Sun.COM default:
7347836SJohn.Forte@Sun.COM rtn = EINVAL;
7357836SJohn.Forte@Sun.COM break;
7367836SJohn.Forte@Sun.COM }
7377836SJohn.Forte@Sun.COM return (rtn);
7387836SJohn.Forte@Sun.COM }
7397836SJohn.Forte@Sun.COM
7407836SJohn.Forte@Sun.COM int
iscsi_set_params(iscsi_param_set_t * ils,iscsi_hba_t * ihp,boolean_t persist)7417836SJohn.Forte@Sun.COM iscsi_set_params(iscsi_param_set_t *ils, iscsi_hba_t *ihp, boolean_t persist)
7427836SJohn.Forte@Sun.COM {
7437836SJohn.Forte@Sun.COM iscsi_login_params_t *params = NULL;
7447836SJohn.Forte@Sun.COM uchar_t *name = NULL;
7457836SJohn.Forte@Sun.COM iscsi_sess_t *isp = NULL;
7467836SJohn.Forte@Sun.COM iscsi_param_get_t *ilg;
7477836SJohn.Forte@Sun.COM int rtn = 0;
748*12161SJack.Meng@Sun.COM uint32_t event_count;
7497836SJohn.Forte@Sun.COM
7507836SJohn.Forte@Sun.COM /* handle special case for Initiator name */
7517836SJohn.Forte@Sun.COM if (ils->s_param == ISCSI_LOGIN_PARAM_INITIATOR_NAME) {
7527836SJohn.Forte@Sun.COM (void) strlcpy((char *)ihp->hba_name,
7537836SJohn.Forte@Sun.COM (char *)ils->s_value.v_name, ISCSI_MAX_NAME_LEN);
7547836SJohn.Forte@Sun.COM if (persist) {
7557836SJohn.Forte@Sun.COM char *name;
7567836SJohn.Forte@Sun.COM boolean_t rval;
7577836SJohn.Forte@Sun.COM
7587836SJohn.Forte@Sun.COM /* save off old Initiator name */
7597836SJohn.Forte@Sun.COM name = kmem_alloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
7607836SJohn.Forte@Sun.COM rval = persistent_initiator_name_get(name,
7617836SJohn.Forte@Sun.COM ISCSI_MAX_NAME_LEN);
7627836SJohn.Forte@Sun.COM
7637836SJohn.Forte@Sun.COM (void) persistent_initiator_name_set(
7647836SJohn.Forte@Sun.COM (char *)ihp->hba_name);
7657836SJohn.Forte@Sun.COM if (rval == B_TRUE) {
7667836SJohn.Forte@Sun.COM /*
7677836SJohn.Forte@Sun.COM * check to see if we have login param,
7687836SJohn.Forte@Sun.COM * chap param, or authentication params
7697836SJohn.Forte@Sun.COM * loaded in persistent that we have to change
7707836SJohn.Forte@Sun.COM * the name of
7717836SJohn.Forte@Sun.COM */
7727836SJohn.Forte@Sun.COM persistent_param_t *pp;
7737836SJohn.Forte@Sun.COM iscsi_chap_props_t *chap;
7747836SJohn.Forte@Sun.COM iscsi_auth_props_t *auth;
7757836SJohn.Forte@Sun.COM
7767836SJohn.Forte@Sun.COM /* checking login params */
7777836SJohn.Forte@Sun.COM pp = kmem_zalloc(sizeof (persistent_param_t),
7787836SJohn.Forte@Sun.COM KM_SLEEP);
7797836SJohn.Forte@Sun.COM if (persistent_param_get(name, pp)) {
7807836SJohn.Forte@Sun.COM rval = persistent_param_clear(name);
7817836SJohn.Forte@Sun.COM if (rval == B_TRUE) {
7827836SJohn.Forte@Sun.COM rval = persistent_param_set(
7837836SJohn.Forte@Sun.COM (char *)ihp->hba_name, pp);
7847836SJohn.Forte@Sun.COM }
7857836SJohn.Forte@Sun.COM if (rval == B_FALSE) {
7867836SJohn.Forte@Sun.COM rtn = EFAULT;
7877836SJohn.Forte@Sun.COM }
7887836SJohn.Forte@Sun.COM }
7897836SJohn.Forte@Sun.COM kmem_free(pp, sizeof (persistent_param_t));
7907836SJohn.Forte@Sun.COM
7917836SJohn.Forte@Sun.COM /* check chap params */
7927836SJohn.Forte@Sun.COM chap = kmem_zalloc(sizeof (iscsi_chap_props_t),
7937836SJohn.Forte@Sun.COM KM_SLEEP);
7947836SJohn.Forte@Sun.COM if (persistent_chap_get(name, chap)) {
7957836SJohn.Forte@Sun.COM rval = persistent_chap_clear(name);
7967836SJohn.Forte@Sun.COM if (rval == B_TRUE) {
7977836SJohn.Forte@Sun.COM /*
7987836SJohn.Forte@Sun.COM * Update CHAP user name only if the
7997836SJohn.Forte@Sun.COM * original username was set to the
8007836SJohn.Forte@Sun.COM * initiator node name. Otherwise
8017836SJohn.Forte@Sun.COM * leave it the way it is.
8027836SJohn.Forte@Sun.COM */
8037836SJohn.Forte@Sun.COM int userSize;
8047836SJohn.Forte@Sun.COM userSize =
8057836SJohn.Forte@Sun.COM sizeof (chap->c_user);
8067836SJohn.Forte@Sun.COM if (strncmp((char *)
8077836SJohn.Forte@Sun.COM chap->c_user, name,
8087836SJohn.Forte@Sun.COM sizeof (chap->c_user))
8097836SJohn.Forte@Sun.COM == 0) {
8107836SJohn.Forte@Sun.COM bzero(chap->c_user,
8117836SJohn.Forte@Sun.COM userSize);
8127836SJohn.Forte@Sun.COM bcopy((char *)
8137836SJohn.Forte@Sun.COM ihp->hba_name,
8147836SJohn.Forte@Sun.COM chap->c_user,
8157836SJohn.Forte@Sun.COM strlen((char *)
8167836SJohn.Forte@Sun.COM ihp->hba_name));
8177836SJohn.Forte@Sun.COM chap->c_user_len =
8187836SJohn.Forte@Sun.COM strlen((char *)
8197836SJohn.Forte@Sun.COM ihp->hba_name);
8207836SJohn.Forte@Sun.COM
8217836SJohn.Forte@Sun.COM }
8227836SJohn.Forte@Sun.COM rval = persistent_chap_set(
8237836SJohn.Forte@Sun.COM (char *)ihp->hba_name, chap);
8247836SJohn.Forte@Sun.COM }
8257836SJohn.Forte@Sun.COM if (rval == B_FALSE) {
8267836SJohn.Forte@Sun.COM rtn = EFAULT;
8277836SJohn.Forte@Sun.COM }
8287836SJohn.Forte@Sun.COM }
8297836SJohn.Forte@Sun.COM kmem_free(chap, sizeof (iscsi_chap_props_t));
8307836SJohn.Forte@Sun.COM
8317836SJohn.Forte@Sun.COM /* check authentication params */
8327836SJohn.Forte@Sun.COM auth = kmem_zalloc(sizeof (iscsi_auth_props_t),
8337836SJohn.Forte@Sun.COM KM_SLEEP);
8347836SJohn.Forte@Sun.COM if (persistent_auth_get(name, auth)) {
8357836SJohn.Forte@Sun.COM rval = persistent_auth_clear(name);
8367836SJohn.Forte@Sun.COM if (rval == B_TRUE) {
8377836SJohn.Forte@Sun.COM rval = persistent_auth_set(
8387836SJohn.Forte@Sun.COM (char *)ihp->hba_name,
8397836SJohn.Forte@Sun.COM auth);
8407836SJohn.Forte@Sun.COM }
8417836SJohn.Forte@Sun.COM if (rval == B_FALSE) {
8427836SJohn.Forte@Sun.COM rtn = EFAULT;
8437836SJohn.Forte@Sun.COM }
8447836SJohn.Forte@Sun.COM }
8457836SJohn.Forte@Sun.COM kmem_free(auth, sizeof (iscsi_auth_props_t));
8467836SJohn.Forte@Sun.COM }
8477836SJohn.Forte@Sun.COM kmem_free(name, ISCSI_MAX_NAME_LEN);
8487836SJohn.Forte@Sun.COM }
8497836SJohn.Forte@Sun.COM } else if (ils->s_param == ISCSI_LOGIN_PARAM_INITIATOR_ALIAS) {
8507836SJohn.Forte@Sun.COM (void) strlcpy((char *)ihp->hba_alias,
8517836SJohn.Forte@Sun.COM (char *)ils->s_value.v_name, ISCSI_MAX_NAME_LEN);
8527836SJohn.Forte@Sun.COM ihp->hba_alias_length =
8537836SJohn.Forte@Sun.COM strlen((char *)ils->s_value.v_name);
8547836SJohn.Forte@Sun.COM if (persist) {
8557836SJohn.Forte@Sun.COM (void) persistent_alias_name_set(
8567836SJohn.Forte@Sun.COM (char *)ihp->hba_alias);
8577836SJohn.Forte@Sun.COM }
8587836SJohn.Forte@Sun.COM } else {
8597836SJohn.Forte@Sun.COM /* switch login based if looking for initiator params */
8607836SJohn.Forte@Sun.COM if (ils->s_oid == ihp->hba_oid) {
8617836SJohn.Forte@Sun.COM /* initiator */
8627836SJohn.Forte@Sun.COM params = &ihp->hba_params;
8637836SJohn.Forte@Sun.COM name = ihp->hba_name;
8647836SJohn.Forte@Sun.COM rtn = iscsi_set_param(params, ils);
8657836SJohn.Forte@Sun.COM } else {
8667836SJohn.Forte@Sun.COM /* session */
8677836SJohn.Forte@Sun.COM name = iscsi_targetparam_get_name(ils->s_oid);
8688389SJack.Meng@Sun.COM if (name == NULL)
8698389SJack.Meng@Sun.COM rtn = EFAULT;
8707836SJohn.Forte@Sun.COM
8718389SJack.Meng@Sun.COM if (persist && (rtn == 0)) {
8727836SJohn.Forte@Sun.COM boolean_t rval;
8737836SJohn.Forte@Sun.COM persistent_param_t *pp;
8747836SJohn.Forte@Sun.COM
8757836SJohn.Forte@Sun.COM pp = (persistent_param_t *)
8767836SJohn.Forte@Sun.COM kmem_zalloc(sizeof (*pp), KM_SLEEP);
8777836SJohn.Forte@Sun.COM if (!persistent_param_get((char *)name, pp)) {
8787836SJohn.Forte@Sun.COM iscsi_set_default_login_params(
8797836SJohn.Forte@Sun.COM &pp->p_params);
8807836SJohn.Forte@Sun.COM }
8817836SJohn.Forte@Sun.COM
8827836SJohn.Forte@Sun.COM pp->p_bitmap |= (1 << ils->s_param);
8837836SJohn.Forte@Sun.COM rtn = iscsi_set_param(&pp->p_params, ils);
8847836SJohn.Forte@Sun.COM if (rtn == 0) {
8857836SJohn.Forte@Sun.COM rval = persistent_param_set(
8867836SJohn.Forte@Sun.COM (char *)name, pp);
8877836SJohn.Forte@Sun.COM if (rval == B_FALSE) {
8887836SJohn.Forte@Sun.COM rtn = EFAULT;
8897836SJohn.Forte@Sun.COM }
8907836SJohn.Forte@Sun.COM }
8917836SJohn.Forte@Sun.COM kmem_free(pp, sizeof (*pp));
8927836SJohn.Forte@Sun.COM }
8937836SJohn.Forte@Sun.COM
8947836SJohn.Forte@Sun.COM /*
8958194SJack.Meng@Sun.COM * Here may have multiple sessions with different
8968194SJack.Meng@Sun.COM * tpgt values. So it is needed to loop through
8977836SJohn.Forte@Sun.COM * the sessions and update all sessions.
8987836SJohn.Forte@Sun.COM */
8997836SJohn.Forte@Sun.COM if (rtn == 0) {
9007836SJohn.Forte@Sun.COM rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
9017836SJohn.Forte@Sun.COM for (isp = ihp->hba_sess_list; isp;
9027836SJohn.Forte@Sun.COM isp = isp->sess_next) {
9038194SJack.Meng@Sun.COM if (iscsiboot_prop &&
9048194SJack.Meng@Sun.COM isp->sess_boot &&
9058194SJack.Meng@Sun.COM iscsi_chk_bootlun_mpxio(ihp)) {
9068194SJack.Meng@Sun.COM /*
9078194SJack.Meng@Sun.COM * MPxIO is enabled so capable
9088194SJack.Meng@Sun.COM * of changing. All changes
9098194SJack.Meng@Sun.COM * will be applied later,
9108194SJack.Meng@Sun.COM * after this function
9118194SJack.Meng@Sun.COM */
9128194SJack.Meng@Sun.COM continue;
9138194SJack.Meng@Sun.COM }
9148194SJack.Meng@Sun.COM
9157836SJohn.Forte@Sun.COM if (strncmp((char *)isp->sess_name,
9167836SJohn.Forte@Sun.COM (char *)name,
9177836SJohn.Forte@Sun.COM ISCSI_MAX_NAME_LEN) == 0) {
918*12161SJack.Meng@Sun.COM event_count = atomic_inc_32_nv(&isp->sess_state_event_count);
919*12161SJack.Meng@Sun.COM iscsi_sess_enter_state_zone(isp);
920*12161SJack.Meng@Sun.COM iscsi_sess_state_machine(isp, ISCSI_SESS_EVENT_N7, event_count);
921*12161SJack.Meng@Sun.COM iscsi_sess_exit_state_zone(isp);
9227836SJohn.Forte@Sun.COM }
9237836SJohn.Forte@Sun.COM }
9247836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
9257836SJohn.Forte@Sun.COM }
9267836SJohn.Forte@Sun.COM
9277836SJohn.Forte@Sun.COM } /* end of 'else' */
9287836SJohn.Forte@Sun.COM
9297836SJohn.Forte@Sun.COM if (params && persist && (rtn == 0)) {
9307836SJohn.Forte@Sun.COM boolean_t rval;
9317836SJohn.Forte@Sun.COM persistent_param_t *pp;
9327836SJohn.Forte@Sun.COM
9337836SJohn.Forte@Sun.COM pp = (persistent_param_t *)
9347836SJohn.Forte@Sun.COM kmem_zalloc(sizeof (*pp), KM_SLEEP);
9357836SJohn.Forte@Sun.COM (void) persistent_param_get((char *)name, pp);
9367836SJohn.Forte@Sun.COM pp->p_bitmap |= (1 << ils->s_param);
9377836SJohn.Forte@Sun.COM bcopy(params, &pp->p_params, sizeof (*params));
9387836SJohn.Forte@Sun.COM rval = persistent_param_set((char *)name, pp);
9397836SJohn.Forte@Sun.COM if (rval == B_FALSE) {
9407836SJohn.Forte@Sun.COM rtn = EFAULT;
9417836SJohn.Forte@Sun.COM }
9427836SJohn.Forte@Sun.COM kmem_free(pp, sizeof (*pp));
9437836SJohn.Forte@Sun.COM }
9447836SJohn.Forte@Sun.COM /*
9457836SJohn.Forte@Sun.COM * if initiator parameter set, modify all associated
9467836SJohn.Forte@Sun.COM * sessions that don't already have the parameter
9477836SJohn.Forte@Sun.COM * overriden
9487836SJohn.Forte@Sun.COM */
9498389SJack.Meng@Sun.COM if ((ils->s_oid == ihp->hba_oid) && (rtn == 0)) {
9507836SJohn.Forte@Sun.COM ilg = (iscsi_param_get_t *)
9517836SJohn.Forte@Sun.COM kmem_alloc(sizeof (*ilg), KM_SLEEP);
9527836SJohn.Forte@Sun.COM
9537836SJohn.Forte@Sun.COM rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
9547836SJohn.Forte@Sun.COM for (isp = ihp->hba_sess_list; isp;
9557836SJohn.Forte@Sun.COM isp = isp->sess_next) {
9567836SJohn.Forte@Sun.COM ilg->g_param = ils->s_param;
9577836SJohn.Forte@Sun.COM params = &isp->sess_params;
9587836SJohn.Forte@Sun.COM if (iscsi_get_persisted_param(
9597836SJohn.Forte@Sun.COM isp->sess_name, ilg, params) != 0) {
9607836SJohn.Forte@Sun.COM rtn = iscsi_set_param(params, ils);
9617836SJohn.Forte@Sun.COM if (rtn != 0) {
9627836SJohn.Forte@Sun.COM break;
9637836SJohn.Forte@Sun.COM }
9648194SJack.Meng@Sun.COM if (iscsiboot_prop &&
9658194SJack.Meng@Sun.COM isp->sess_boot &&
9668194SJack.Meng@Sun.COM iscsi_chk_bootlun_mpxio(ihp)) {
9678194SJack.Meng@Sun.COM /*
9688194SJack.Meng@Sun.COM * MPxIO is enabled so capable
9698194SJack.Meng@Sun.COM * of changing. Changes will
9708194SJack.Meng@Sun.COM * be applied later, right
9718194SJack.Meng@Sun.COM * after this function
9728194SJack.Meng@Sun.COM */
9738194SJack.Meng@Sun.COM continue;
9748194SJack.Meng@Sun.COM }
9757836SJohn.Forte@Sun.COM
9767836SJohn.Forte@Sun.COM /*
9777836SJohn.Forte@Sun.COM * Notify the session that
9787836SJohn.Forte@Sun.COM * the login parameters have
9797836SJohn.Forte@Sun.COM * changed.
9807836SJohn.Forte@Sun.COM */
981*12161SJack.Meng@Sun.COM event_count = atomic_inc_32_nv(
982*12161SJack.Meng@Sun.COM &isp->sess_state_event_count);
983*12161SJack.Meng@Sun.COM iscsi_sess_enter_state_zone(isp);
9847836SJohn.Forte@Sun.COM iscsi_sess_state_machine(isp,
985*12161SJack.Meng@Sun.COM ISCSI_SESS_EVENT_N7, event_count);
986*12161SJack.Meng@Sun.COM iscsi_sess_exit_state_zone(isp);
9877836SJohn.Forte@Sun.COM }
9887836SJohn.Forte@Sun.COM }
9897836SJohn.Forte@Sun.COM kmem_free(ilg, sizeof (*ilg));
9907836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
9917836SJohn.Forte@Sun.COM }
9927836SJohn.Forte@Sun.COM }
9937836SJohn.Forte@Sun.COM return (rtn);
9947836SJohn.Forte@Sun.COM }
9957836SJohn.Forte@Sun.COM
9967836SJohn.Forte@Sun.COM int
iscsi_target_prop_mod(iscsi_hba_t * ihp,iscsi_property_t * ipp,int cmd)9977836SJohn.Forte@Sun.COM iscsi_target_prop_mod(iscsi_hba_t *ihp, iscsi_property_t *ipp, int cmd)
9987836SJohn.Forte@Sun.COM {
9997836SJohn.Forte@Sun.COM iscsi_sess_t *isp = NULL;
10007836SJohn.Forte@Sun.COM iscsi_conn_t *icp;
10017836SJohn.Forte@Sun.COM int rtn;
10027836SJohn.Forte@Sun.COM char *name;
10037836SJohn.Forte@Sun.COM
10047836SJohn.Forte@Sun.COM /*
10057836SJohn.Forte@Sun.COM * If we're just attempting to get the target properties don't
10067836SJohn.Forte@Sun.COM * create the session if it doesn't already exist. If we setting
10077836SJohn.Forte@Sun.COM * the property then create the session if needed because we'll
10087836SJohn.Forte@Sun.COM * most likely see an ISCSI_LOGIN in a few.
10097836SJohn.Forte@Sun.COM */
10107836SJohn.Forte@Sun.COM rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
10117836SJohn.Forte@Sun.COM
10127836SJohn.Forte@Sun.COM /*
10137836SJohn.Forte@Sun.COM * If the oid does represent a session check to see
10147836SJohn.Forte@Sun.COM * if it is a target oid. If so, return the target's
10157836SJohn.Forte@Sun.COM * associated session.
10167836SJohn.Forte@Sun.COM */
10177836SJohn.Forte@Sun.COM rtn = iscsi_sess_get(ipp->p_oid, ihp, &isp);
10187836SJohn.Forte@Sun.COM if (rtn != 0) {
10197836SJohn.Forte@Sun.COM rtn = iscsi_sess_get_by_target(ipp->p_oid, ihp, &isp);
10207836SJohn.Forte@Sun.COM }
10217836SJohn.Forte@Sun.COM
10227836SJohn.Forte@Sun.COM /*
10237836SJohn.Forte@Sun.COM * If rtn is zero then we have found an existing session.
10247836SJohn.Forte@Sun.COM * Use the session name for database lookup. If rtn is
10257836SJohn.Forte@Sun.COM * non-zero then create a targetparam object and use
10267836SJohn.Forte@Sun.COM * its name for database lookup.
10277836SJohn.Forte@Sun.COM */
10287836SJohn.Forte@Sun.COM if (rtn == 0) {
10297836SJohn.Forte@Sun.COM name = (char *)isp->sess_name;
10307836SJohn.Forte@Sun.COM } else {
10317836SJohn.Forte@Sun.COM name = (char *)iscsi_targetparam_get_name(ipp->p_oid);
10327836SJohn.Forte@Sun.COM isp = NULL;
10337836SJohn.Forte@Sun.COM }
10347836SJohn.Forte@Sun.COM
10357836SJohn.Forte@Sun.COM if (name == NULL) {
10367836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
10377836SJohn.Forte@Sun.COM rtn = EFAULT;
10387836SJohn.Forte@Sun.COM return (rtn);
10397836SJohn.Forte@Sun.COM }
10407836SJohn.Forte@Sun.COM
10417836SJohn.Forte@Sun.COM rtn = 0;
10427836SJohn.Forte@Sun.COM if (cmd == ISCSI_TARGET_PROPS_GET) {
10437836SJohn.Forte@Sun.COM /*
10447836SJohn.Forte@Sun.COM * If isp is not null get the session's parameters, otherwise
10457836SJohn.Forte@Sun.COM * the get is for a target-param object so defaults need to
10467836SJohn.Forte@Sun.COM * be returned.
10477836SJohn.Forte@Sun.COM */
10487836SJohn.Forte@Sun.COM if (isp != NULL) {
10497836SJohn.Forte@Sun.COM int conn_count = 0;
10507836SJohn.Forte@Sun.COM
10517836SJohn.Forte@Sun.COM bcopy(isp->sess_alias, ipp->p_alias,
10527836SJohn.Forte@Sun.COM isp->sess_alias_length);
10537836SJohn.Forte@Sun.COM bcopy(isp->sess_name, ipp->p_name,
10547836SJohn.Forte@Sun.COM isp->sess_name_length);
10557836SJohn.Forte@Sun.COM ipp->p_alias_len = isp->sess_alias_length;
10567836SJohn.Forte@Sun.COM ipp->p_name_len = isp->sess_name_length;
10577836SJohn.Forte@Sun.COM ipp->p_discovery = isp->sess_discovered_by;
10587836SJohn.Forte@Sun.COM ipp->p_last_err = isp->sess_last_err;
10597836SJohn.Forte@Sun.COM ipp->p_tpgt_conf = isp->sess_tpgt_conf;
10607836SJohn.Forte@Sun.COM ipp->p_tpgt_nego = isp->sess_tpgt_nego;
10617836SJohn.Forte@Sun.COM bcopy(isp->sess_isid, ipp->p_isid, ISCSI_ISID_LEN);
10627836SJohn.Forte@Sun.COM
10637836SJohn.Forte@Sun.COM rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
10647836SJohn.Forte@Sun.COM for (icp = isp->sess_conn_list; icp;
10657836SJohn.Forte@Sun.COM icp = icp->conn_next) {
10667836SJohn.Forte@Sun.COM if (icp->conn_state ==
10677836SJohn.Forte@Sun.COM ISCSI_CONN_STATE_LOGGED_IN) {
10687836SJohn.Forte@Sun.COM conn_count++;
10697836SJohn.Forte@Sun.COM }
10707836SJohn.Forte@Sun.COM }
10717836SJohn.Forte@Sun.COM rw_exit(&isp->sess_conn_list_rwlock);
10727836SJohn.Forte@Sun.COM ipp->p_num_of_connections = conn_count;
10737836SJohn.Forte@Sun.COM ipp->p_connected = (conn_count > 0) ? B_TRUE : B_FALSE;
10747836SJohn.Forte@Sun.COM } else {
10757836SJohn.Forte@Sun.COM bcopy(name, ipp->p_name, strlen(name));
10767836SJohn.Forte@Sun.COM ipp->p_name_len = strlen(name);
10777836SJohn.Forte@Sun.COM bcopy("", ipp->p_alias, strlen(""));
10787836SJohn.Forte@Sun.COM ipp->p_alias_len = strlen("");
10797836SJohn.Forte@Sun.COM ipp->p_discovery = iSCSIDiscoveryMethodUnknown;
10807836SJohn.Forte@Sun.COM ipp->p_last_err = NoError;
10817836SJohn.Forte@Sun.COM ipp->p_tpgt_conf = ISCSI_DEFAULT_TPGT;
10827836SJohn.Forte@Sun.COM ipp->p_tpgt_nego = ISCSI_DEFAULT_TPGT;
10837836SJohn.Forte@Sun.COM ipp->p_num_of_connections = 0;
10847836SJohn.Forte@Sun.COM ipp->p_connected = B_FALSE;
10857836SJohn.Forte@Sun.COM }
10867836SJohn.Forte@Sun.COM } else {
10877836SJohn.Forte@Sun.COM if (isp == NULL) {
10887836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
10897836SJohn.Forte@Sun.COM rtn = EFAULT;
10907836SJohn.Forte@Sun.COM return (rtn);
10917836SJohn.Forte@Sun.COM }
10927836SJohn.Forte@Sun.COM
10937836SJohn.Forte@Sun.COM /* ISCSI_TARGET_PROPS_SET */
10947836SJohn.Forte@Sun.COM /*
10957836SJohn.Forte@Sun.COM * only update if new, otherwise could clear out alias
10967836SJohn.Forte@Sun.COM * if just updating the discovery.
10977836SJohn.Forte@Sun.COM */
10987836SJohn.Forte@Sun.COM if (ipp->p_alias_len != 0) {
10997836SJohn.Forte@Sun.COM bcopy(ipp->p_alias, isp->sess_alias,
11007836SJohn.Forte@Sun.COM ipp->p_alias_len);
11017836SJohn.Forte@Sun.COM isp->sess_alias_length = ipp->p_alias_len;
11027836SJohn.Forte@Sun.COM }
11037836SJohn.Forte@Sun.COM isp->sess_discovered_by = ipp->p_discovery;
11047836SJohn.Forte@Sun.COM }
11057836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
11067836SJohn.Forte@Sun.COM return (rtn);
11077836SJohn.Forte@Sun.COM }
11087836SJohn.Forte@Sun.COM
11097836SJohn.Forte@Sun.COM /*
11107836SJohn.Forte@Sun.COM * iscsi_ioctl_get_config_sess - gets configured session information
11117836SJohn.Forte@Sun.COM *
11127836SJohn.Forte@Sun.COM * This function is an ioctl helper function to get the
11137836SJohn.Forte@Sun.COM * configured session information from the persistent store.
11147836SJohn.Forte@Sun.COM */
11157836SJohn.Forte@Sun.COM int
iscsi_ioctl_get_config_sess(iscsi_hba_t * ihp,iscsi_config_sess_t * ics)11167836SJohn.Forte@Sun.COM iscsi_ioctl_get_config_sess(iscsi_hba_t *ihp, iscsi_config_sess_t *ics)
11177836SJohn.Forte@Sun.COM {
11187836SJohn.Forte@Sun.COM uchar_t *name;
11197836SJohn.Forte@Sun.COM
11207836SJohn.Forte@Sun.COM /* Get the matching iscsi node name for the oid */
11217836SJohn.Forte@Sun.COM if (ics->ics_oid == ISCSI_INITIATOR_OID) {
11227836SJohn.Forte@Sun.COM /* initiator name */
11237836SJohn.Forte@Sun.COM name = ihp->hba_name;
11247836SJohn.Forte@Sun.COM } else {
11257836SJohn.Forte@Sun.COM /* target name */
11267836SJohn.Forte@Sun.COM name = iscsi_targetparam_get_name(ics->ics_oid);
11277836SJohn.Forte@Sun.COM if (name == NULL) {
11287836SJohn.Forte@Sun.COM /* invalid node name */
11297836SJohn.Forte@Sun.COM return (EINVAL);
11307836SJohn.Forte@Sun.COM }
11317836SJohn.Forte@Sun.COM }
11327836SJohn.Forte@Sun.COM
11337836SJohn.Forte@Sun.COM /* get configured session information */
11347836SJohn.Forte@Sun.COM if (persistent_get_config_session((char *)name, ics) == B_FALSE) {
11357836SJohn.Forte@Sun.COM /*
11367836SJohn.Forte@Sun.COM * There might not be anything in the database yet. If
11377836SJohn.Forte@Sun.COM * this is a request for the target check the initiator
11387836SJohn.Forte@Sun.COM * value. If neither is set return the default value.
11397836SJohn.Forte@Sun.COM */
11407836SJohn.Forte@Sun.COM if (ics->ics_oid != ISCSI_INITIATOR_OID) {
11417836SJohn.Forte@Sun.COM if (persistent_get_config_session(
11427836SJohn.Forte@Sun.COM (char *)ihp->hba_name, ics) == B_FALSE) {
11437836SJohn.Forte@Sun.COM /*
11447836SJohn.Forte@Sun.COM * No initiator value is set.
11457836SJohn.Forte@Sun.COM * Return the defaults.
11467836SJohn.Forte@Sun.COM */
11477836SJohn.Forte@Sun.COM ics->ics_out = ISCSI_DEFAULT_SESS_NUM;
11487836SJohn.Forte@Sun.COM ics->ics_bound = ISCSI_DEFAULT_SESS_BOUND;
11497836SJohn.Forte@Sun.COM }
11507836SJohn.Forte@Sun.COM } else {
11517836SJohn.Forte@Sun.COM ics->ics_out = ISCSI_DEFAULT_SESS_NUM;
11527836SJohn.Forte@Sun.COM ics->ics_bound = ISCSI_DEFAULT_SESS_BOUND;
11537836SJohn.Forte@Sun.COM }
11547836SJohn.Forte@Sun.COM }
11557836SJohn.Forte@Sun.COM
11567836SJohn.Forte@Sun.COM return (0);
11577836SJohn.Forte@Sun.COM }
11587836SJohn.Forte@Sun.COM
11597836SJohn.Forte@Sun.COM /*
11607836SJohn.Forte@Sun.COM * iscsi_ioctl_set_config_sess - sets configured session information
11617836SJohn.Forte@Sun.COM *
11627836SJohn.Forte@Sun.COM * This function is an ioctl helper function to set the
11637836SJohn.Forte@Sun.COM * configured session information in the persistent store.
11647836SJohn.Forte@Sun.COM * In addition it will notify any active sessions of the
11657836SJohn.Forte@Sun.COM * changed so this can update binding information. It
11667836SJohn.Forte@Sun.COM * will also destroy sessions that were removed and add
11677836SJohn.Forte@Sun.COM * new sessions.
11687836SJohn.Forte@Sun.COM */
11697836SJohn.Forte@Sun.COM int
iscsi_ioctl_set_config_sess(iscsi_hba_t * ihp,iscsi_config_sess_t * ics)11707836SJohn.Forte@Sun.COM iscsi_ioctl_set_config_sess(iscsi_hba_t *ihp, iscsi_config_sess_t *ics)
11717836SJohn.Forte@Sun.COM {
11727836SJohn.Forte@Sun.COM uchar_t *name;
11737836SJohn.Forte@Sun.COM iscsi_sess_t *isp;
1174*12161SJack.Meng@Sun.COM uint32_t event_count;
11757836SJohn.Forte@Sun.COM
11767836SJohn.Forte@Sun.COM /* check range infomration */
11777836SJohn.Forte@Sun.COM if ((ics->ics_in < ISCSI_MIN_CONFIG_SESSIONS) ||
11787836SJohn.Forte@Sun.COM (ics->ics_in > ISCSI_MAX_CONFIG_SESSIONS)) {
11797836SJohn.Forte@Sun.COM /* invalid range information */
11807836SJohn.Forte@Sun.COM return (EINVAL);
11817836SJohn.Forte@Sun.COM }
11827836SJohn.Forte@Sun.COM
11837836SJohn.Forte@Sun.COM if (ics->ics_oid == ISCSI_INITIATOR_OID) {
11847836SJohn.Forte@Sun.COM name = ihp->hba_name;
11857836SJohn.Forte@Sun.COM } else {
11867836SJohn.Forte@Sun.COM /* get target name */
11877836SJohn.Forte@Sun.COM name = iscsi_targetparam_get_name(ics->ics_oid);
11887836SJohn.Forte@Sun.COM if (name == NULL) {
11897836SJohn.Forte@Sun.COM /* invalid node name */
11907836SJohn.Forte@Sun.COM return (EINVAL);
11917836SJohn.Forte@Sun.COM }
11927836SJohn.Forte@Sun.COM }
11937836SJohn.Forte@Sun.COM
11947836SJohn.Forte@Sun.COM /* store the new information */
11957836SJohn.Forte@Sun.COM if (persistent_set_config_session((char *)name, ics) == B_FALSE) {
11967836SJohn.Forte@Sun.COM /* failed to store new information */
11977836SJohn.Forte@Sun.COM return (EINVAL);
11987836SJohn.Forte@Sun.COM }
11997836SJohn.Forte@Sun.COM
12007836SJohn.Forte@Sun.COM /* notify existing sessions of change */
12017836SJohn.Forte@Sun.COM rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
12027836SJohn.Forte@Sun.COM isp = ihp->hba_sess_list;
12037836SJohn.Forte@Sun.COM while (isp != NULL) {
12047836SJohn.Forte@Sun.COM
12057836SJohn.Forte@Sun.COM if ((ics->ics_oid == ISCSI_INITIATOR_OID) ||
12067836SJohn.Forte@Sun.COM (strncmp((char *)isp->sess_name, (char *)name,
12077836SJohn.Forte@Sun.COM ISCSI_MAX_NAME_LEN) == 0)) {
12087836SJohn.Forte@Sun.COM
12097836SJohn.Forte@Sun.COM /*
12107836SJohn.Forte@Sun.COM * If this sessions least signficant byte
12117836SJohn.Forte@Sun.COM * of the isid is less than or equal to
12127836SJohn.Forte@Sun.COM * the the number of configured sessions
12137836SJohn.Forte@Sun.COM * then we need to tear down this session.
12147836SJohn.Forte@Sun.COM */
12157836SJohn.Forte@Sun.COM if (ics->ics_in <= isp->sess_isid[5]) {
12167836SJohn.Forte@Sun.COM /* First attempt to destory the session */
12177836SJohn.Forte@Sun.COM if (ISCSI_SUCCESS(iscsi_sess_destroy(isp))) {
12187836SJohn.Forte@Sun.COM isp = ihp->hba_sess_list;
12197836SJohn.Forte@Sun.COM } else {
12207836SJohn.Forte@Sun.COM /*
12217836SJohn.Forte@Sun.COM * If we can't destroy it then
12227836SJohn.Forte@Sun.COM * atleast poke it to disconnect
12237836SJohn.Forte@Sun.COM * it.
12247836SJohn.Forte@Sun.COM */
1225*12161SJack.Meng@Sun.COM event_count = atomic_inc_32_nv(
1226*12161SJack.Meng@Sun.COM &isp->sess_state_event_count);
1227*12161SJack.Meng@Sun.COM iscsi_sess_enter_state_zone(isp);
12287836SJohn.Forte@Sun.COM iscsi_sess_state_machine(isp,
1229*12161SJack.Meng@Sun.COM ISCSI_SESS_EVENT_N7, event_count);
1230*12161SJack.Meng@Sun.COM iscsi_sess_exit_state_zone(isp);
1231*12161SJack.Meng@Sun.COM
12327836SJohn.Forte@Sun.COM isp = isp->sess_next;
12337836SJohn.Forte@Sun.COM }
12347836SJohn.Forte@Sun.COM } else {
12357836SJohn.Forte@Sun.COM isp = isp->sess_next;
12367836SJohn.Forte@Sun.COM }
12377836SJohn.Forte@Sun.COM } else {
12387836SJohn.Forte@Sun.COM isp = isp->sess_next;
12397836SJohn.Forte@Sun.COM }
12407836SJohn.Forte@Sun.COM }
12417836SJohn.Forte@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
12427836SJohn.Forte@Sun.COM
12437836SJohn.Forte@Sun.COM /*
12447836SJohn.Forte@Sun.COM * The number of targets has changed. Since we don't expect
12457836SJohn.Forte@Sun.COM * this to be a common operation lets keep the code simple and
12467836SJohn.Forte@Sun.COM * just use a slightly larger hammer and poke discovery. This
12477836SJohn.Forte@Sun.COM * force the reevaulation of this target and all other targets.
12487836SJohn.Forte@Sun.COM */
12497836SJohn.Forte@Sun.COM iscsid_poke_discovery(ihp, iSCSIDiscoveryMethodUnknown);
12507836SJohn.Forte@Sun.COM /* lock so only one config operation occrs */
12517836SJohn.Forte@Sun.COM sema_p(&iscsid_config_semaphore);
12527836SJohn.Forte@Sun.COM iscsid_config_all(ihp, B_FALSE);
12537836SJohn.Forte@Sun.COM sema_v(&iscsid_config_semaphore);
12547836SJohn.Forte@Sun.COM
12557836SJohn.Forte@Sun.COM return (0);
12567836SJohn.Forte@Sun.COM }
125710156SZhang.Yi@Sun.COM
125810156SZhang.Yi@Sun.COM int
iscsi_ioctl_set_tunable_param(iscsi_hba_t * ihp,iscsi_tunable_object_t * tpss)125910156SZhang.Yi@Sun.COM iscsi_ioctl_set_tunable_param(iscsi_hba_t *ihp, iscsi_tunable_object_t *tpss)
126010156SZhang.Yi@Sun.COM {
126110156SZhang.Yi@Sun.COM uchar_t *name;
126210156SZhang.Yi@Sun.COM iscsi_sess_t *isp;
126310156SZhang.Yi@Sun.COM iscsi_conn_t *icp;
126410156SZhang.Yi@Sun.COM int param_id = 0;
126510156SZhang.Yi@Sun.COM persistent_tunable_param_t *pparam;
126610156SZhang.Yi@Sun.COM
126710156SZhang.Yi@Sun.COM if (tpss->t_oid == ihp->hba_oid) {
126810156SZhang.Yi@Sun.COM name = ihp->hba_name;
126910156SZhang.Yi@Sun.COM } else {
127010156SZhang.Yi@Sun.COM /* get target name */
127110156SZhang.Yi@Sun.COM name = iscsi_targetparam_get_name(tpss->t_oid);
127210156SZhang.Yi@Sun.COM if (name == NULL) {
127310156SZhang.Yi@Sun.COM /* invalid node name */
127410156SZhang.Yi@Sun.COM return (EINVAL);
127510156SZhang.Yi@Sun.COM }
127610156SZhang.Yi@Sun.COM }
127710156SZhang.Yi@Sun.COM
127810156SZhang.Yi@Sun.COM pparam = (persistent_tunable_param_t *)kmem_zalloc(sizeof (*pparam),
127910156SZhang.Yi@Sun.COM KM_SLEEP);
128010156SZhang.Yi@Sun.COM if (persistent_get_tunable_param((char *)name, pparam) == B_FALSE) {
128110156SZhang.Yi@Sun.COM /* use default value */
128210156SZhang.Yi@Sun.COM pparam->p_params.recv_login_rsp_timeout =
128310156SZhang.Yi@Sun.COM ISCSI_DEFAULT_RX_TIMEOUT_VALUE;
128410156SZhang.Yi@Sun.COM pparam->p_params.polling_login_delay =
128510156SZhang.Yi@Sun.COM ISCSI_DEFAULT_LOGIN_POLLING_DELAY;
128610156SZhang.Yi@Sun.COM pparam->p_params.conn_login_max =
128710156SZhang.Yi@Sun.COM ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX;
128810156SZhang.Yi@Sun.COM }
128910156SZhang.Yi@Sun.COM
129010156SZhang.Yi@Sun.COM pparam->p_bitmap |= (1 << (tpss->t_param -1));
129110156SZhang.Yi@Sun.COM param_id = 1 << (tpss->t_param -1);
129210156SZhang.Yi@Sun.COM switch (param_id) {
129310156SZhang.Yi@Sun.COM case ISCSI_TUNABLE_PARAM_RX_TIMEOUT_VALUE:
129410156SZhang.Yi@Sun.COM pparam->p_params.recv_login_rsp_timeout =
129510156SZhang.Yi@Sun.COM tpss->t_value.v_integer;
129610156SZhang.Yi@Sun.COM break;
129710156SZhang.Yi@Sun.COM case ISCSI_TUNABLE_PARAM_LOGIN_POLLING_DELAY:
129810156SZhang.Yi@Sun.COM pparam->p_params.polling_login_delay =
129910156SZhang.Yi@Sun.COM tpss->t_value.v_integer;
130010156SZhang.Yi@Sun.COM break;
130110156SZhang.Yi@Sun.COM case ISCSI_TUNABLE_PARAM_CONN_LOGIN_MAX:
130210156SZhang.Yi@Sun.COM pparam->p_params.conn_login_max =
130310156SZhang.Yi@Sun.COM tpss->t_value.v_integer;
130410156SZhang.Yi@Sun.COM break;
130510156SZhang.Yi@Sun.COM default:
130610156SZhang.Yi@Sun.COM break;
130710156SZhang.Yi@Sun.COM }
130810156SZhang.Yi@Sun.COM if (persistent_set_tunable_param((char *)name,
130910156SZhang.Yi@Sun.COM pparam) == B_FALSE) {
131010156SZhang.Yi@Sun.COM kmem_free(pparam, sizeof (*pparam));
131110156SZhang.Yi@Sun.COM return (EINVAL);
131210156SZhang.Yi@Sun.COM }
131310156SZhang.Yi@Sun.COM
131410156SZhang.Yi@Sun.COM if (tpss->t_oid == ihp->hba_oid) {
131510156SZhang.Yi@Sun.COM bcopy(&pparam->p_params, &ihp->hba_tunable_params,
131610156SZhang.Yi@Sun.COM sizeof (iscsi_tunable_params_t));
131710156SZhang.Yi@Sun.COM }
131810156SZhang.Yi@Sun.COM
131910156SZhang.Yi@Sun.COM rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
132010156SZhang.Yi@Sun.COM for (isp = ihp->hba_sess_list; isp; isp = isp->sess_next) {
132110156SZhang.Yi@Sun.COM if (isp->sess_type != ISCSI_SESS_TYPE_NORMAL) {
132210156SZhang.Yi@Sun.COM continue;
132310156SZhang.Yi@Sun.COM }
132410156SZhang.Yi@Sun.COM rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
132510156SZhang.Yi@Sun.COM icp = isp->sess_conn_list;
132610156SZhang.Yi@Sun.COM while (icp != NULL) {
132710156SZhang.Yi@Sun.COM if (strcmp((const char *)name,
132810156SZhang.Yi@Sun.COM (const char *)isp->sess_name) == 0) {
132910156SZhang.Yi@Sun.COM bcopy(&pparam->p_params,
133010156SZhang.Yi@Sun.COM &icp->conn_tunable_params,
133110156SZhang.Yi@Sun.COM sizeof (iscsi_tunable_params_t));
133210156SZhang.Yi@Sun.COM } else {
133310156SZhang.Yi@Sun.COM /*
133410156SZhang.Yi@Sun.COM * this session connected target
133510156SZhang.Yi@Sun.COM * tunable parameters not set,
133610156SZhang.Yi@Sun.COM * use initiator's default
133710156SZhang.Yi@Sun.COM */
133810156SZhang.Yi@Sun.COM bcopy(&ihp->hba_tunable_params,
133910156SZhang.Yi@Sun.COM &icp->conn_tunable_params,
134010156SZhang.Yi@Sun.COM sizeof (iscsi_tunable_params_t));
134110156SZhang.Yi@Sun.COM }
134210156SZhang.Yi@Sun.COM icp = icp->conn_next;
134310156SZhang.Yi@Sun.COM }
134410156SZhang.Yi@Sun.COM rw_exit(&isp->sess_conn_list_rwlock);
134510156SZhang.Yi@Sun.COM }
134610156SZhang.Yi@Sun.COM rw_exit(&ihp->hba_sess_list_rwlock);
134710156SZhang.Yi@Sun.COM kmem_free(pparam, sizeof (*pparam));
134810156SZhang.Yi@Sun.COM return (0);
134910156SZhang.Yi@Sun.COM }
1350