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