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