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