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 /*
2249311b35SJack Meng  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23fcf3ce44SJohn Forte  * Use is subject to license terms.
24fcf3ce44SJohn Forte  *
25fcf3ce44SJohn Forte  * iSNS Client
26fcf3ce44SJohn Forte  */
27fcf3ce44SJohn Forte 
28fcf3ce44SJohn Forte #include "iscsi.h"		/* For ISCSI_MAX_IOVEC */
29fcf3ce44SJohn Forte #include "isns_protocol.h"
30fcf3ce44SJohn Forte #include "isns_client.h"
31fcf3ce44SJohn Forte #include "persistent.h"
32fcf3ce44SJohn Forte 
33fcf3ce44SJohn Forte #ifdef _KERNEL
34fcf3ce44SJohn Forte #include <sys/sunddi.h>
35fcf3ce44SJohn Forte #else
36fcf3ce44SJohn Forte #include <stdlib.h>
37fcf3ce44SJohn Forte #endif
38fcf3ce44SJohn Forte #include <netinet/tcp.h>
39fcf3ce44SJohn Forte #include <sys/types.h>
40fcf3ce44SJohn Forte 
41fcf3ce44SJohn Forte /* For local use */
42fcf3ce44SJohn Forte #define	ISNS_MAX_IOVEC		5
43fcf3ce44SJohn Forte #define	MAX_XID			(2^16)
44fcf3ce44SJohn Forte #define	MAX_RCV_RSP_COUNT	10	/* Maximum number of unmatched xid */
45fcf3ce44SJohn Forte #define	ISNS_RCV_TIMEOUT	5
46fcf3ce44SJohn Forte #define	ISNS_RCV_RETRY_MAX	2
47fcf3ce44SJohn Forte #define	IPV4_RSVD_BYTES		10
48fcf3ce44SJohn Forte 
49fcf3ce44SJohn Forte typedef struct isns_reg_arg {
50fcf3ce44SJohn Forte 	iscsi_addr_t *isns_server_addr;
51fcf3ce44SJohn Forte 	uint8_t *node_name;
52fcf3ce44SJohn Forte 	size_t node_name_len;
53fcf3ce44SJohn Forte 	uint8_t *node_alias;
54fcf3ce44SJohn Forte 	size_t node_alias_len;
55fcf3ce44SJohn Forte 	uint32_t node_type;
56fcf3ce44SJohn Forte 	uint8_t *lhba_handle;
57fcf3ce44SJohn Forte } isns_reg_arg_t;
58fcf3ce44SJohn Forte 
59fcf3ce44SJohn Forte typedef struct isns_async_thread_arg {
60fcf3ce44SJohn Forte 	uint8_t *lhba_handle;
61fcf3ce44SJohn Forte 	void *listening_so;
62fcf3ce44SJohn Forte } isns_async_thread_arg_t;
63fcf3ce44SJohn Forte 
64fcf3ce44SJohn Forte /* One global queue to serve all LHBA instances. */
65fcf3ce44SJohn Forte static ddi_taskq_t *reg_query_taskq;
66fcf3ce44SJohn Forte static kmutex_t reg_query_taskq_mutex;
67fcf3ce44SJohn Forte 
68fcf3ce44SJohn Forte /* One global queue to serve all LHBA instances. */
69fcf3ce44SJohn Forte static ddi_taskq_t *scn_taskq;
70fcf3ce44SJohn Forte static kmutex_t scn_taskq_mutex;
71fcf3ce44SJohn Forte 
72fcf3ce44SJohn Forte /* One globally maintained transaction ID. */
73fcf3ce44SJohn Forte static uint16_t xid = 0;
74fcf3ce44SJohn Forte 
75fcf3ce44SJohn Forte /*
76fcf3ce44SJohn Forte  * One SCN callback registration per LHBA instance. For now, since we
77fcf3ce44SJohn Forte  * support only one instance, we create one place holder for the
78fcf3ce44SJohn Forte  * callback.
79fcf3ce44SJohn Forte  */
80fcf3ce44SJohn Forte void (*scn_callback_p)(void *);
81fcf3ce44SJohn Forte 
82fcf3ce44SJohn Forte /*
83fcf3ce44SJohn Forte  * One thread, port, local address, and listening socket per LHBA instance.
84fcf3ce44SJohn Forte  * For now, since we support only one instance, we create one set of place
85fcf3ce44SJohn Forte  * holder for these data.
86fcf3ce44SJohn Forte  */
87fcf3ce44SJohn Forte static boolean_t esi_scn_thr_to_shutdown = B_FALSE;
88fcf3ce44SJohn Forte static iscsi_thread_t *esi_scn_thr_id = NULL;
89fcf3ce44SJohn Forte static void *instance_listening_so = NULL;
90fcf3ce44SJohn Forte /*
91fcf3ce44SJohn Forte  * This mutex protects all the per LHBA instance variables, i.e.,
926362598eSbing zhao - Sun Microsystems - Beijing China  * esi_scn_thr_to_shutdown, esi_scn_thr_id, and instance_listening_so.
93fcf3ce44SJohn Forte  */
94fcf3ce44SJohn Forte static kmutex_t esi_scn_thr_mutex;
95fcf3ce44SJohn Forte 
96fcf3ce44SJohn Forte /* iSNS related helpers */
97fcf3ce44SJohn Forte /* Return status */
98fcf3ce44SJohn Forte #define	ISNS_OK				0
99fcf3ce44SJohn Forte #define	ISNS_BAD_SVR_ADDR		1
100fcf3ce44SJohn Forte #define	ISNS_INTERNAL_ERR		2
101fcf3ce44SJohn Forte #define	ISNS_CANNOT_FIND_LOCAL_ADDR	3
102fcf3ce44SJohn Forte static int discover_isns_server(uint8_t *lhba_handle,
103fcf3ce44SJohn Forte     iscsi_addr_list_t **isns_server_addrs);
104fcf3ce44SJohn Forte static int create_esi_scn_thr(uint8_t *lhba_handle,
105fcf3ce44SJohn Forte     iscsi_addr_t *isns_server_addr);
106fcf3ce44SJohn Forte static void esi_scn_thr_cleanup(void);
107fcf3ce44SJohn Forte static void register_isns_client(void *arg);
108fcf3ce44SJohn Forte static isns_status_t do_isns_dev_attr_reg(iscsi_addr_t *isns_server_addr,
109fcf3ce44SJohn Forte     uint8_t *node_name, uint8_t *node_alias, uint32_t node_type);
110fcf3ce44SJohn Forte static isns_status_t do_isns_dev_dereg(iscsi_addr_t *isns_server_addr,
111fcf3ce44SJohn Forte     uint8_t *node_name);
112fcf3ce44SJohn Forte 
113fcf3ce44SJohn Forte /*
114fcf3ce44SJohn Forte  * Make query to all iSNS servers visible to the specified LHBA.
115fcf3ce44SJohn Forte  * The query could be made for all target nodes or for a specific target
116fcf3ce44SJohn Forte  * node.
117fcf3ce44SJohn Forte  */
118fcf3ce44SJohn Forte static isns_status_t do_isns_query(boolean_t is_query_all_nodes_b,
119fcf3ce44SJohn Forte     uint8_t *lhba_handle, uint8_t *target_node_name,
120fcf3ce44SJohn Forte     uint8_t *source_node_name, uint8_t *source_node_alias,
121fcf3ce44SJohn Forte     uint32_t source_node_type, isns_portal_group_list_t **pg_list);
122fcf3ce44SJohn Forte 
123fcf3ce44SJohn Forte /*
124fcf3ce44SJohn Forte  * Create DevAttrQuery message requesting portal group information for all
125fcf3ce44SJohn Forte  * target nodes. Send it to the specified iSNS server. Parse the
126fcf3ce44SJohn Forte  * DevAttrQueryRsp PDU and translate the results into a portal group list
127fcf3ce44SJohn Forte  * object.
128fcf3ce44SJohn Forte  */
129fcf3ce44SJohn Forte static isns_status_t do_isns_dev_attr_query_all_nodes(
130fcf3ce44SJohn Forte     iscsi_addr_t *isns_server_addr, uint8_t *node_name,
131fcf3ce44SJohn Forte     uint8_t *node_alias, isns_portal_group_list_t **pg_list);
132fcf3ce44SJohn Forte 
133fcf3ce44SJohn Forte /*
134fcf3ce44SJohn Forte  * Create DevAttrQuery message requesting portal group information for the
135fcf3ce44SJohn Forte  * specified target node. Send it to the specified iSNS server. Parse the
136fcf3ce44SJohn Forte  * DevAttrQueryRsp PDU and translate the results into a portal group list
137fcf3ce44SJohn Forte  * object.
138fcf3ce44SJohn Forte  */
139fcf3ce44SJohn Forte static isns_status_t do_isns_dev_attr_query_one_node(
140fcf3ce44SJohn Forte     iscsi_addr_t *isns_server_addr, uint8_t *target_node_name,
141fcf3ce44SJohn Forte     uint8_t *source_node_name, uint8_t *source_node_alias,
142fcf3ce44SJohn Forte     uint32_t source_node_type, isns_portal_group_list_t **pg_list);
143fcf3ce44SJohn Forte 
144fcf3ce44SJohn Forte static void isns_service_esi_scn(iscsi_thread_t *thread, void* arg);
145fcf3ce44SJohn Forte static void (*scn_callback_lookup(uint8_t *lhba_handle))(void *);
146fcf3ce44SJohn Forte 
147fcf3ce44SJohn Forte /* Transport related helpers */
148fcf3ce44SJohn Forte static void *isns_open(iscsi_addr_t *isns_server_addr);
149fcf3ce44SJohn Forte static ssize_t isns_send_pdu(void *socket, isns_pdu_t *pdu);
150fcf3ce44SJohn Forte static size_t isns_rcv_pdu(void *so, isns_pdu_t **pdu, size_t *pdu_size);
1516362598eSbing zhao - Sun Microsystems - Beijing China static boolean_t find_listening_addr(iscsi_addr_t *local_addr,
1526362598eSbing zhao - Sun Microsystems - Beijing China     void *listening_so);
153fcf3ce44SJohn Forte static boolean_t find_local_portal(iscsi_addr_t *isns_server_addr,
154fcf3ce44SJohn Forte     iscsi_addr_t **local_addr, void **listening_so);
155fcf3ce44SJohn Forte 
156fcf3ce44SJohn Forte /* iSNS protocol related helpers */
157fcf3ce44SJohn Forte static size_t isns_create_pdu_header(uint16_t func_id,
158fcf3ce44SJohn Forte     uint16_t flags, isns_pdu_t **pdu);
159fcf3ce44SJohn Forte static int isns_add_attr(isns_pdu_t *pdu,
160fcf3ce44SJohn Forte     size_t max_pdu_size, uint32_t attr_id, uint32_t attr_len,
161fcf3ce44SJohn Forte     void *attr_data, uint32_t attr_numeric_data);
162fcf3ce44SJohn Forte static uint16_t create_xid(void);
163fcf3ce44SJohn Forte static size_t isns_create_dev_attr_reg_pdu(
164fcf3ce44SJohn Forte     uint8_t *node_name, uint8_t *node_alias, uint32_t node_type,
165fcf3ce44SJohn Forte     uint16_t *xid, isns_pdu_t **out_pdu);
166fcf3ce44SJohn Forte static size_t isns_create_dev_dereg_pdu(uint8_t *node_name,
167fcf3ce44SJohn Forte     uint16_t *xid_p, isns_pdu_t **out_pdu);
168fcf3ce44SJohn Forte static size_t isns_create_dev_attr_qry_target_nodes_pdu(
169fcf3ce44SJohn Forte     uint8_t *node_name, uint8_t *node_alias, uint16_t *xid,
170fcf3ce44SJohn Forte     isns_pdu_t **out_pdu);
171fcf3ce44SJohn Forte static size_t isns_create_dev_attr_qry_one_pg_pdu(
172fcf3ce44SJohn Forte     uint8_t *target_node_name, uint8_t *source_node_name,
173fcf3ce44SJohn Forte     uint16_t *xid, isns_pdu_t **out_pdu);
174fcf3ce44SJohn Forte static size_t isns_create_esi_rsp_pdu(uint32_t rsp_status_code,
175fcf3ce44SJohn Forte     isns_pdu_t *pdu, uint16_t *xid, isns_pdu_t **out_pdu);
176fcf3ce44SJohn Forte static size_t isns_create_scn_reg_pdu(uint8_t *node_name,
177fcf3ce44SJohn Forte     uint8_t *node_alias, uint16_t *xid, isns_pdu_t **out_pdu);
178fcf3ce44SJohn Forte static size_t isns_create_scn_dereg_pdu(uint8_t *node_name,
179fcf3ce44SJohn Forte     uint16_t *xid_p, isns_pdu_t **out_pdu);
180fcf3ce44SJohn Forte static size_t isns_create_scn_rsp_pdu(uint32_t rsp_status_code,
181fcf3ce44SJohn Forte     isns_pdu_t *pdu, uint16_t *xid, isns_pdu_t **out_pdu);
182fcf3ce44SJohn Forte static uint32_t isns_process_dev_attr_reg_rsp(isns_pdu_t *resp_pdu_p);
183fcf3ce44SJohn Forte static uint32_t isns_process_dev_attr_dereg_rsp(isns_pdu_t *resp_pdu_p);
184fcf3ce44SJohn Forte 
185fcf3ce44SJohn Forte /*
186fcf3ce44SJohn Forte  * Process and parse a DevAttrQryRsp message. The routine creates a list
187fcf3ce44SJohn Forte  * of Portal Group objects if the message is parasable without any issue.
188fcf3ce44SJohn Forte  * If the parsing is not successful, the pg_list will be set to NULL.
189fcf3ce44SJohn Forte  */
190fcf3ce44SJohn Forte static uint32_t isns_process_dev_attr_qry_target_nodes_pdu(
191fcf3ce44SJohn Forte     iscsi_addr_t *isns_server_addr, uint16_t payload_funcId,
192fcf3ce44SJohn Forte     isns_resp_t *resp_p, size_t resp_len,
193fcf3ce44SJohn Forte     isns_portal_group_list_t **pg_list);
194fcf3ce44SJohn Forte static uint32_t isns_process_scn_reg_rsp(isns_pdu_t *resp_pdu_p);
195fcf3ce44SJohn Forte static uint32_t isns_process_scn_dereg_rsp(isns_pdu_t *resp_pdu_p);
196fcf3ce44SJohn Forte static uint32_t isns_process_esi(isns_pdu_t *esi_pdu_p);
197fcf3ce44SJohn Forte static uint32_t isns_process_scn(isns_pdu_t *scn_pdu_p, uint8_t *lhba_handle);
198fcf3ce44SJohn Forte 
199fcf3ce44SJohn Forte void
isns_client_init()200fcf3ce44SJohn Forte isns_client_init()
201fcf3ce44SJohn Forte {
202fcf3ce44SJohn Forte 	mutex_init(&reg_query_taskq_mutex, NULL, MUTEX_DRIVER, NULL);
203fcf3ce44SJohn Forte 	mutex_enter(&reg_query_taskq_mutex);
204fcf3ce44SJohn Forte 	reg_query_taskq = ddi_taskq_create(NULL, "isns_reg_query_taskq",
205fcf3ce44SJohn Forte 	    1, TASKQ_DEFAULTPRI, 0);
206fcf3ce44SJohn Forte 	mutex_exit(&reg_query_taskq_mutex);
207fcf3ce44SJohn Forte 
208fcf3ce44SJohn Forte 	mutex_init(&scn_taskq_mutex, NULL, MUTEX_DRIVER, NULL);
209fcf3ce44SJohn Forte 	mutex_enter(&scn_taskq_mutex);
210fcf3ce44SJohn Forte 	scn_taskq = ddi_taskq_create(NULL, "isns_scn_taskq",
211fcf3ce44SJohn Forte 	    1, TASKQ_DEFAULTPRI, 0);
212fcf3ce44SJohn Forte 	mutex_exit(&scn_taskq_mutex);
213fcf3ce44SJohn Forte 
214fcf3ce44SJohn Forte 	mutex_init(&esi_scn_thr_mutex, NULL, MUTEX_DRIVER, NULL);
215fcf3ce44SJohn Forte 
216fcf3ce44SJohn Forte 	/* MISC initializations. */
217fcf3ce44SJohn Forte 	scn_callback_p = NULL;
218fcf3ce44SJohn Forte 	esi_scn_thr_id = NULL;
219fcf3ce44SJohn Forte 	instance_listening_so = NULL;
220fcf3ce44SJohn Forte 	esi_scn_thr_to_shutdown = B_FALSE;
221fcf3ce44SJohn Forte 	xid = 0;
222fcf3ce44SJohn Forte }
223fcf3ce44SJohn Forte 
224fcf3ce44SJohn Forte void
isns_client_cleanup()225fcf3ce44SJohn Forte isns_client_cleanup()
226fcf3ce44SJohn Forte {
227fcf3ce44SJohn Forte 	ddi_taskq_t *tmp_taskq_p;
228fcf3ce44SJohn Forte 
229fcf3ce44SJohn Forte 	mutex_enter(&scn_taskq_mutex);
230fcf3ce44SJohn Forte 	tmp_taskq_p = scn_taskq;
231fcf3ce44SJohn Forte 	scn_taskq = NULL;
232fcf3ce44SJohn Forte 	mutex_exit(&scn_taskq_mutex);
233fcf3ce44SJohn Forte 	ddi_taskq_destroy(tmp_taskq_p);
234fcf3ce44SJohn Forte 
235fcf3ce44SJohn Forte 	mutex_enter(&reg_query_taskq_mutex);
236fcf3ce44SJohn Forte 	tmp_taskq_p = reg_query_taskq;
237fcf3ce44SJohn Forte 	reg_query_taskq = NULL;
238fcf3ce44SJohn Forte 	mutex_exit(&reg_query_taskq_mutex);
239fcf3ce44SJohn Forte 	ddi_taskq_destroy(tmp_taskq_p);
240fcf3ce44SJohn Forte 
241fcf3ce44SJohn Forte 	mutex_destroy(&reg_query_taskq_mutex);
242fcf3ce44SJohn Forte 	mutex_destroy(&scn_taskq_mutex);
243fcf3ce44SJohn Forte 
244fcf3ce44SJohn Forte 	esi_scn_thr_cleanup();
245fcf3ce44SJohn Forte 
246fcf3ce44SJohn Forte 	mutex_destroy(&esi_scn_thr_mutex);
247fcf3ce44SJohn Forte }
248fcf3ce44SJohn Forte 
249fcf3ce44SJohn Forte isns_status_t
isns_reg(uint8_t * lhba_handle,uint8_t * node_name,size_t node_name_len,uint8_t * node_alias,size_t node_alias_len,uint32_t node_type,void (* scn_callback)(void *))250fcf3ce44SJohn Forte isns_reg(uint8_t *lhba_handle,
251fcf3ce44SJohn Forte 	uint8_t *node_name,
252fcf3ce44SJohn Forte 	size_t node_name_len,
253fcf3ce44SJohn Forte 	uint8_t *node_alias,
254fcf3ce44SJohn Forte 	size_t node_alias_len,
255fcf3ce44SJohn Forte 	uint32_t node_type,
256fcf3ce44SJohn Forte 	void (*scn_callback)(void *))
257fcf3ce44SJohn Forte {
258fcf3ce44SJohn Forte 	int i;
259fcf3ce44SJohn Forte 	int list_space;
260fcf3ce44SJohn Forte 	iscsi_addr_list_t *isns_server_addr_list;
261fcf3ce44SJohn Forte 	isns_reg_arg_t *reg_args_p;
262fcf3ce44SJohn Forte 
263fcf3ce44SJohn Forte 	/* Look up the iSNS Server address(es) based on the specified ISID */
264fcf3ce44SJohn Forte 	if (discover_isns_server(lhba_handle, &isns_server_addr_list) !=
265fcf3ce44SJohn Forte 	    ISNS_OK) {
266fcf3ce44SJohn Forte 		return (isns_no_svr_found);
267fcf3ce44SJohn Forte 	}
268fcf3ce44SJohn Forte 
269fcf3ce44SJohn Forte 	/* No iSNS server discovered - no registration needed. */
270fcf3ce44SJohn Forte 	if (isns_server_addr_list->al_out_cnt == 0) {
271fcf3ce44SJohn Forte 		list_space = sizeof (iscsi_addr_list_t);
272fcf3ce44SJohn Forte 		kmem_free(isns_server_addr_list, list_space);
273fcf3ce44SJohn Forte 		isns_server_addr_list = NULL;
274fcf3ce44SJohn Forte 		return (isns_no_svr_found);
275fcf3ce44SJohn Forte 	}
276fcf3ce44SJohn Forte 
277fcf3ce44SJohn Forte 	/* Check and create ESI/SCN threads and populate local address */
278fcf3ce44SJohn Forte 	for (i = 0; i < isns_server_addr_list->al_out_cnt; i++) {
279fcf3ce44SJohn Forte 		if (create_esi_scn_thr(lhba_handle,
280fcf3ce44SJohn Forte 		    &(isns_server_addr_list->al_addrs[i])) == ISNS_OK) {
281fcf3ce44SJohn Forte 			break;
282fcf3ce44SJohn Forte 		}
283fcf3ce44SJohn Forte 	}
284fcf3ce44SJohn Forte 	if (i == isns_server_addr_list->al_out_cnt) {
285fcf3ce44SJohn Forte 		/*
286fcf3ce44SJohn Forte 		 * Problem creating ESI/SCN thread
287fcf3ce44SJohn Forte 		 * Free the server list
288fcf3ce44SJohn Forte 		 */
289fcf3ce44SJohn Forte 		list_space = sizeof (iscsi_addr_list_t);
290fcf3ce44SJohn Forte 		if (isns_server_addr_list->al_out_cnt > 0) {
291fcf3ce44SJohn Forte 			list_space += (sizeof (iscsi_addr_t) *
292fcf3ce44SJohn Forte 			    (isns_server_addr_list->al_out_cnt - 1));
293fcf3ce44SJohn Forte 		}
294fcf3ce44SJohn Forte 		kmem_free(isns_server_addr_list, list_space);
295fcf3ce44SJohn Forte 		isns_server_addr_list = NULL;
296fcf3ce44SJohn Forte 		return (isns_internal_err);
297fcf3ce44SJohn Forte 	}
298fcf3ce44SJohn Forte 
299fcf3ce44SJohn Forte 	/* Register against all iSNS servers discovered. */
300fcf3ce44SJohn Forte 	for (i = 0; i < isns_server_addr_list->al_out_cnt; i++) {
301fcf3ce44SJohn Forte 		reg_args_p = kmem_zalloc(sizeof (isns_reg_arg_t), KM_SLEEP);
302fcf3ce44SJohn Forte 		reg_args_p->isns_server_addr =
303fcf3ce44SJohn Forte 		    kmem_zalloc(sizeof (iscsi_addr_t), KM_SLEEP);
304fcf3ce44SJohn Forte 		bcopy(&isns_server_addr_list->al_addrs[i],
305fcf3ce44SJohn Forte 		    reg_args_p->isns_server_addr, sizeof (iscsi_addr_t));
306fcf3ce44SJohn Forte 		reg_args_p->node_name = kmem_zalloc(node_name_len, KM_SLEEP);
307fcf3ce44SJohn Forte 		bcopy(node_name, reg_args_p->node_name, node_name_len);
308fcf3ce44SJohn Forte 		reg_args_p->node_name_len = node_name_len;
309fcf3ce44SJohn Forte 		reg_args_p->node_alias = kmem_zalloc(node_alias_len, KM_SLEEP);
310fcf3ce44SJohn Forte 		bcopy(node_alias, reg_args_p->node_alias, node_alias_len);
311fcf3ce44SJohn Forte 		reg_args_p->node_alias_len = node_alias_len;
312fcf3ce44SJohn Forte 		reg_args_p->node_type = node_type;
313fcf3ce44SJohn Forte 
314fcf3ce44SJohn Forte 		/* Dispatch the registration request */
315fcf3ce44SJohn Forte 		register_isns_client(reg_args_p);
316fcf3ce44SJohn Forte 	}
317fcf3ce44SJohn Forte 
318fcf3ce44SJohn Forte 	/* Free the server list */
319fcf3ce44SJohn Forte 	list_space = sizeof (iscsi_addr_list_t);
320fcf3ce44SJohn Forte 	if (isns_server_addr_list->al_out_cnt > 0) {
321fcf3ce44SJohn Forte 		list_space += (sizeof (iscsi_addr_t) *
322fcf3ce44SJohn Forte 		    (isns_server_addr_list->al_out_cnt - 1));
323fcf3ce44SJohn Forte 	}
324fcf3ce44SJohn Forte 	kmem_free(isns_server_addr_list, list_space);
325fcf3ce44SJohn Forte 	isns_server_addr_list = NULL;
326fcf3ce44SJohn Forte 
327fcf3ce44SJohn Forte 	/* Register the scn_callback. */
328fcf3ce44SJohn Forte 	scn_callback_p = scn_callback;
329fcf3ce44SJohn Forte 
330fcf3ce44SJohn Forte 	return (isns_ok);
331fcf3ce44SJohn Forte }
332fcf3ce44SJohn Forte 
333fcf3ce44SJohn Forte isns_status_t
isns_reg_one_server(entry_t * isns_server,uint8_t * lhba_handle,uint8_t * node_name,size_t node_name_len,uint8_t * node_alias,size_t node_alias_len,uint32_t node_type,void (* scn_callback)(void *))334fcf3ce44SJohn Forte isns_reg_one_server(entry_t *isns_server,
335fcf3ce44SJohn Forte 	uint8_t *lhba_handle,
336fcf3ce44SJohn Forte 	uint8_t *node_name,
337fcf3ce44SJohn Forte 	size_t node_name_len,
338fcf3ce44SJohn Forte 	uint8_t *node_alias,
339fcf3ce44SJohn Forte 	size_t node_alias_len,
340fcf3ce44SJohn Forte 	uint32_t node_type,
341fcf3ce44SJohn Forte 	void (*scn_callback)(void *))
342fcf3ce44SJohn Forte {
343fcf3ce44SJohn Forte 	int status;
344fcf3ce44SJohn Forte 	iscsi_addr_t *ap;
345fcf3ce44SJohn Forte 	isns_reg_arg_t *reg_args_p;
346fcf3ce44SJohn Forte 
347fcf3ce44SJohn Forte 	ap = (iscsi_addr_t *)kmem_zalloc(sizeof (iscsi_addr_t), KM_SLEEP);
348fcf3ce44SJohn Forte 	ap->a_port = isns_server->e_port;
349fcf3ce44SJohn Forte 	ap->a_addr.i_insize = isns_server->e_insize;
350fcf3ce44SJohn Forte 	if (isns_server->e_insize == sizeof (struct in_addr)) {
351fcf3ce44SJohn Forte 		ap->a_addr.i_addr.in4.s_addr = (isns_server->e_u.u_in4.s_addr);
352fcf3ce44SJohn Forte 	} else if (isns_server->e_insize == sizeof (struct in6_addr)) {
353fcf3ce44SJohn Forte 		bcopy(&(isns_server->e_u.u_in6.s6_addr),
354fcf3ce44SJohn Forte 		    ap->a_addr.i_addr.in6.s6_addr,
355fcf3ce44SJohn Forte 		    sizeof (struct in6_addr));
356fcf3ce44SJohn Forte 	} else {
357fcf3ce44SJohn Forte 		kmem_free(ap, sizeof (iscsi_addr_t));
358fcf3ce44SJohn Forte 		return (isns_op_failed);
359fcf3ce44SJohn Forte 	}
360fcf3ce44SJohn Forte 
361fcf3ce44SJohn Forte 	/* Check and create ESI/SCN threads and populate local address */
362fcf3ce44SJohn Forte 	if ((status = create_esi_scn_thr(lhba_handle, ap))
363fcf3ce44SJohn Forte 	    != ISNS_OK) {
364fcf3ce44SJohn Forte 		/* Problem creating ESI/SCN thread */
365fcf3ce44SJohn Forte 		DTRACE_PROBE1(isns_reg_one_server_create_esi_scn_thr,
366fcf3ce44SJohn Forte 		    int, status);
367fcf3ce44SJohn Forte 		kmem_free(ap, sizeof (iscsi_addr_t));
368fcf3ce44SJohn Forte 		return (isns_internal_err);
369fcf3ce44SJohn Forte 	}
370fcf3ce44SJohn Forte 
371fcf3ce44SJohn Forte 	reg_args_p = kmem_zalloc(sizeof (isns_reg_arg_t), KM_SLEEP);
372fcf3ce44SJohn Forte 	reg_args_p->isns_server_addr =
373fcf3ce44SJohn Forte 	    kmem_zalloc(sizeof (iscsi_addr_t), KM_SLEEP);
374fcf3ce44SJohn Forte 	bcopy(ap, reg_args_p->isns_server_addr, sizeof (iscsi_addr_t));
375fcf3ce44SJohn Forte 	reg_args_p->node_name = kmem_zalloc(node_name_len, KM_SLEEP);
376fcf3ce44SJohn Forte 	bcopy(node_name, reg_args_p->node_name, node_name_len);
377fcf3ce44SJohn Forte 	reg_args_p->node_name_len = node_name_len;
378fcf3ce44SJohn Forte 	reg_args_p->node_alias = kmem_zalloc(node_alias_len, KM_SLEEP);
379fcf3ce44SJohn Forte 	bcopy(node_alias, reg_args_p->node_alias, node_alias_len);
380fcf3ce44SJohn Forte 	reg_args_p->node_alias_len = node_alias_len;
381fcf3ce44SJohn Forte 	reg_args_p->node_type = node_type;
382fcf3ce44SJohn Forte 
383fcf3ce44SJohn Forte 	/* Dispatch the registration request */
384fcf3ce44SJohn Forte 	register_isns_client(reg_args_p);
385fcf3ce44SJohn Forte 
386fcf3ce44SJohn Forte 	/* Register the scn_callback. */
387fcf3ce44SJohn Forte 	scn_callback_p = scn_callback;
388fcf3ce44SJohn Forte 
389fcf3ce44SJohn Forte 	kmem_free(ap, sizeof (iscsi_addr_t));
390fcf3ce44SJohn Forte 	return (isns_ok);
391fcf3ce44SJohn Forte }
392fcf3ce44SJohn Forte 
393fcf3ce44SJohn Forte isns_status_t
isns_dereg(uint8_t * lhba_handle,uint8_t * node_name)394fcf3ce44SJohn Forte isns_dereg(uint8_t *lhba_handle,
395fcf3ce44SJohn Forte 	uint8_t *node_name)
396fcf3ce44SJohn Forte {
397fcf3ce44SJohn Forte 	int i;
398fcf3ce44SJohn Forte 	int isns_svr_lst_sz;
399fcf3ce44SJohn Forte 	int list_space;
400fcf3ce44SJohn Forte 	iscsi_addr_list_t *isns_server_addr_list = NULL;
401fcf3ce44SJohn Forte 	isns_status_t dereg_stat, combined_dereg_stat;
402fcf3ce44SJohn Forte 
403fcf3ce44SJohn Forte 	/* Look up the iSNS Server address(es) based on the specified ISID */
404fcf3ce44SJohn Forte 	if (discover_isns_server(lhba_handle, &isns_server_addr_list) !=
405fcf3ce44SJohn Forte 	    ISNS_OK) {
406fcf3ce44SJohn Forte 		return (isns_no_svr_found);
407fcf3ce44SJohn Forte 	}
408fcf3ce44SJohn Forte 	ASSERT(isns_server_addr_list != NULL);
409fcf3ce44SJohn Forte 	if (isns_server_addr_list->al_out_cnt == 0) {
410fcf3ce44SJohn Forte 		isns_svr_lst_sz = sizeof (iscsi_addr_list_t);
411fcf3ce44SJohn Forte 		kmem_free(isns_server_addr_list, isns_svr_lst_sz);
412fcf3ce44SJohn Forte 		isns_server_addr_list = NULL;
413fcf3ce44SJohn Forte 		return (isns_no_svr_found);
414fcf3ce44SJohn Forte 	}
415fcf3ce44SJohn Forte 
416fcf3ce44SJohn Forte 	combined_dereg_stat = isns_ok;
417fcf3ce44SJohn Forte 	for (i = 0; i < isns_server_addr_list->al_out_cnt; i++) {
418fcf3ce44SJohn Forte 		dereg_stat = do_isns_dev_dereg(
419fcf3ce44SJohn Forte 		    &isns_server_addr_list->al_addrs[i],
420fcf3ce44SJohn Forte 		    node_name);
421fcf3ce44SJohn Forte 		if (dereg_stat == isns_ok) {
422fcf3ce44SJohn Forte 			if (combined_dereg_stat != isns_ok) {
423fcf3ce44SJohn Forte 				combined_dereg_stat = isns_op_partially_failed;
424fcf3ce44SJohn Forte 			}
425fcf3ce44SJohn Forte 		} else {
426fcf3ce44SJohn Forte 			if (combined_dereg_stat == isns_ok) {
427fcf3ce44SJohn Forte 				combined_dereg_stat = isns_op_partially_failed;
428fcf3ce44SJohn Forte 			}
429fcf3ce44SJohn Forte 		}
430fcf3ce44SJohn Forte 	}
431fcf3ce44SJohn Forte 
432fcf3ce44SJohn Forte 	/* Free the server list. */
433fcf3ce44SJohn Forte 	list_space = sizeof (iscsi_addr_list_t);
434fcf3ce44SJohn Forte 	if (isns_server_addr_list->al_out_cnt > 0) {
435fcf3ce44SJohn Forte 		list_space += (sizeof (iscsi_addr_t) *
436fcf3ce44SJohn Forte 		    (isns_server_addr_list->al_out_cnt - 1));
437fcf3ce44SJohn Forte 	}
438fcf3ce44SJohn Forte 	kmem_free(isns_server_addr_list, list_space);
439fcf3ce44SJohn Forte 	isns_server_addr_list = NULL;
440fcf3ce44SJohn Forte 
441fcf3ce44SJohn Forte 	/* Cleanup ESI/SCN thread. */
442fcf3ce44SJohn Forte 	esi_scn_thr_cleanup();
443fcf3ce44SJohn Forte 
444fcf3ce44SJohn Forte 	return (combined_dereg_stat);
445fcf3ce44SJohn Forte }
446fcf3ce44SJohn Forte 
447fcf3ce44SJohn Forte isns_status_t
isns_dereg_one_server(entry_t * isns_server,uint8_t * node_name,boolean_t is_last_isns_server_b)448fcf3ce44SJohn Forte isns_dereg_one_server(entry_t *isns_server,
449fcf3ce44SJohn Forte 	uint8_t *node_name,
450fcf3ce44SJohn Forte 	boolean_t is_last_isns_server_b)
451fcf3ce44SJohn Forte {
452fcf3ce44SJohn Forte 	iscsi_addr_t *ap;
453fcf3ce44SJohn Forte 	isns_status_t dereg_stat;
454fcf3ce44SJohn Forte 
455fcf3ce44SJohn Forte 	ap = (iscsi_addr_t *)kmem_zalloc(sizeof (iscsi_addr_t), KM_SLEEP);
456fcf3ce44SJohn Forte 	ap->a_port = isns_server->e_port;
457fcf3ce44SJohn Forte 	ap->a_addr.i_insize = isns_server->e_insize;
458fcf3ce44SJohn Forte 	if (isns_server->e_insize == sizeof (struct in_addr)) {
459fcf3ce44SJohn Forte 		ap->a_addr.i_addr.in4.s_addr = (isns_server->e_u.u_in4.s_addr);
460fcf3ce44SJohn Forte 	} else if (isns_server->e_insize == sizeof (struct in6_addr)) {
461fcf3ce44SJohn Forte 		bcopy(&(isns_server->e_u.u_in6.s6_addr),
462fcf3ce44SJohn Forte 		    ap->a_addr.i_addr.in6.s6_addr,
463fcf3ce44SJohn Forte 		    sizeof (struct in6_addr));
464fcf3ce44SJohn Forte 	} else {
465fcf3ce44SJohn Forte 		kmem_free(ap, sizeof (iscsi_addr_t));
466fcf3ce44SJohn Forte 		return (isns_op_failed);
467fcf3ce44SJohn Forte 	}
468fcf3ce44SJohn Forte 
469fcf3ce44SJohn Forte 	dereg_stat = do_isns_dev_dereg(ap, node_name);
470fcf3ce44SJohn Forte 
471fcf3ce44SJohn Forte 	kmem_free(ap, sizeof (iscsi_addr_t));
472fcf3ce44SJohn Forte 
473fcf3ce44SJohn Forte 	if (is_last_isns_server_b == B_TRUE) {
474fcf3ce44SJohn Forte 		/*
475fcf3ce44SJohn Forte 		 * Clean up ESI/SCN thread resource if it is the
476fcf3ce44SJohn Forte 		 * last known iSNS server.
477fcf3ce44SJohn Forte 		 */
478fcf3ce44SJohn Forte 		esi_scn_thr_cleanup();
479fcf3ce44SJohn Forte 	}
480fcf3ce44SJohn Forte 
481fcf3ce44SJohn Forte 	return (dereg_stat);
482fcf3ce44SJohn Forte }
483fcf3ce44SJohn Forte 
484fcf3ce44SJohn Forte isns_status_t
isns_query(uint8_t * lhba_handle,uint8_t * node_name,uint8_t * node_alias,uint32_t node_type,isns_portal_group_list_t ** pg_list)485fcf3ce44SJohn Forte isns_query(uint8_t *lhba_handle,
486fcf3ce44SJohn Forte 	uint8_t *node_name,
487fcf3ce44SJohn Forte 	uint8_t *node_alias,
488fcf3ce44SJohn Forte 	uint32_t node_type,
489fcf3ce44SJohn Forte 	isns_portal_group_list_t **pg_list)
490fcf3ce44SJohn Forte {
491fcf3ce44SJohn Forte 	return (do_isns_query(B_TRUE,
492fcf3ce44SJohn Forte 	    lhba_handle,
493fcf3ce44SJohn Forte 	    (uint8_t *)"",
494fcf3ce44SJohn Forte 	    node_name,
495fcf3ce44SJohn Forte 	    node_alias,
496fcf3ce44SJohn Forte 	    node_type,
497fcf3ce44SJohn Forte 	    pg_list));
498fcf3ce44SJohn Forte }
499fcf3ce44SJohn Forte 
500fcf3ce44SJohn Forte /* ARGSUSED */
501fcf3ce44SJohn Forte isns_status_t
isns_query_one_server(iscsi_addr_t * isns_server_addr,uint8_t * lhba_handle,uint8_t * node_name,uint8_t * node_alias,uint32_t node_type,isns_portal_group_list_t ** pg_list)502fcf3ce44SJohn Forte isns_query_one_server(iscsi_addr_t *isns_server_addr,
503fcf3ce44SJohn Forte 	uint8_t *lhba_handle,
504fcf3ce44SJohn Forte 	uint8_t *node_name,
505fcf3ce44SJohn Forte 	uint8_t *node_alias,
506fcf3ce44SJohn Forte 	uint32_t node_type,
507fcf3ce44SJohn Forte 	isns_portal_group_list_t **pg_list)
508fcf3ce44SJohn Forte {
509fcf3ce44SJohn Forte 	return (do_isns_dev_attr_query_all_nodes(isns_server_addr,
510fcf3ce44SJohn Forte 	    node_name,
511fcf3ce44SJohn Forte 	    node_alias,
512fcf3ce44SJohn Forte 	    pg_list));
513fcf3ce44SJohn Forte }
514fcf3ce44SJohn Forte 
515fcf3ce44SJohn Forte isns_status_t
isns_query_one_node(uint8_t * target_node_name,uint8_t * lhba_handle,uint8_t * source_node_name,uint8_t * source_node_alias,uint32_t source_node_type,isns_portal_group_list_t ** pg_list)516fcf3ce44SJohn Forte isns_query_one_node(uint8_t *target_node_name,
517fcf3ce44SJohn Forte 	uint8_t *lhba_handle,
518fcf3ce44SJohn Forte 	uint8_t *source_node_name,
519fcf3ce44SJohn Forte 	uint8_t *source_node_alias,
520fcf3ce44SJohn Forte 	uint32_t source_node_type,
521fcf3ce44SJohn Forte 	isns_portal_group_list_t **pg_list)
522fcf3ce44SJohn Forte {
523fcf3ce44SJohn Forte 	return (do_isns_query(B_FALSE,
524fcf3ce44SJohn Forte 	    lhba_handle,
525fcf3ce44SJohn Forte 	    target_node_name,
526fcf3ce44SJohn Forte 	    source_node_name,
527fcf3ce44SJohn Forte 	    source_node_alias,
528fcf3ce44SJohn Forte 	    source_node_type,
529fcf3ce44SJohn Forte 	    pg_list));
530fcf3ce44SJohn Forte }
531fcf3ce44SJohn Forte 
532fcf3ce44SJohn Forte /* ARGSUSED */
533fcf3ce44SJohn Forte isns_status_t
isns_query_one_server_one_node(iscsi_addr_t * isns_server_addr,uint8_t * target_node_name,uint8_t * lhba_handle,uint8_t * source_node_name,uint8_t * source_node_alias,uint32_t source_node_type,isns_portal_group_list_t ** pg_list)534fcf3ce44SJohn Forte isns_query_one_server_one_node(iscsi_addr_t *isns_server_addr,
535fcf3ce44SJohn Forte 	uint8_t *target_node_name,
536fcf3ce44SJohn Forte 	uint8_t *lhba_handle,
537fcf3ce44SJohn Forte 	uint8_t *source_node_name,
538fcf3ce44SJohn Forte 	uint8_t *source_node_alias,
539fcf3ce44SJohn Forte 	uint32_t source_node_type,
540fcf3ce44SJohn Forte 	isns_portal_group_list_t **pg_list) {
541fcf3ce44SJohn Forte 	/* Not supported yet. */
542fcf3ce44SJohn Forte 	*pg_list = NULL;
543fcf3ce44SJohn Forte 	return (isns_op_failed);
544fcf3ce44SJohn Forte }
545fcf3ce44SJohn Forte 
546fcf3ce44SJohn Forte /* ARGSUSED */
547fcf3ce44SJohn Forte static
548fcf3ce44SJohn Forte int
discover_isns_server(uint8_t * lhba_handle,iscsi_addr_list_t ** isns_server_addrs)549fcf3ce44SJohn Forte discover_isns_server(uint8_t *lhba_handle,
550fcf3ce44SJohn Forte 	iscsi_addr_list_t **isns_server_addrs)
551fcf3ce44SJohn Forte {
552fcf3ce44SJohn Forte 	entry_t e;
553fcf3ce44SJohn Forte 	int i;
554fcf3ce44SJohn Forte 	int isns_server_count = 1;
555fcf3ce44SJohn Forte 	int list_space;
556fcf3ce44SJohn Forte 	void *void_p;
557fcf3ce44SJohn Forte 
558fcf3ce44SJohn Forte 	/*
559fcf3ce44SJohn Forte 	 * Use supported iSNS server discovery method to find out all the
560fcf3ce44SJohn Forte 	 * iSNS servers. For now, only static configuration method is
561fcf3ce44SJohn Forte 	 * supported.
562fcf3ce44SJohn Forte 	 */
563fcf3ce44SJohn Forte 	isns_server_count = 0;
564fcf3ce44SJohn Forte 	void_p = NULL;
565fcf3ce44SJohn Forte 	persistent_isns_addr_lock();
566fcf3ce44SJohn Forte 	while (persistent_isns_addr_next(&void_p, &e) == B_TRUE) {
567fcf3ce44SJohn Forte 		isns_server_count++;
568fcf3ce44SJohn Forte 	}
569fcf3ce44SJohn Forte 	persistent_isns_addr_unlock();
570fcf3ce44SJohn Forte 
571fcf3ce44SJohn Forte 	list_space = sizeof (iscsi_addr_list_t);
572fcf3ce44SJohn Forte 	if (isns_server_count > 0) {
573fcf3ce44SJohn Forte 		list_space += (sizeof (iscsi_addr_t) * (isns_server_count - 1));
574fcf3ce44SJohn Forte 	}
575fcf3ce44SJohn Forte 	*isns_server_addrs = (iscsi_addr_list_t *)kmem_zalloc(list_space,
576fcf3ce44SJohn Forte 	    KM_SLEEP);
577fcf3ce44SJohn Forte 	(*isns_server_addrs)->al_out_cnt = isns_server_count;
578fcf3ce44SJohn Forte 
579fcf3ce44SJohn Forte 	persistent_isns_addr_lock();
580fcf3ce44SJohn Forte 	i = 0;
581fcf3ce44SJohn Forte 	void_p = NULL;
582fcf3ce44SJohn Forte 	while (persistent_isns_addr_next(&void_p, &e) == B_TRUE) {
583fcf3ce44SJohn Forte 		iscsi_addr_t *ap;
584fcf3ce44SJohn Forte 
585fcf3ce44SJohn Forte 		ap = &((*isns_server_addrs)->al_addrs[i]);
586fcf3ce44SJohn Forte 		ap->a_port = e.e_port;
587fcf3ce44SJohn Forte 		ap->a_addr.i_insize = e.e_insize;
588fcf3ce44SJohn Forte 		if (e.e_insize == sizeof (struct in_addr)) {
589fcf3ce44SJohn Forte 			ap->a_addr.i_addr.in4.s_addr = (e.e_u.u_in4.s_addr);
590fcf3ce44SJohn Forte 		} else if (e.e_insize == sizeof (struct in6_addr)) {
591fcf3ce44SJohn Forte 			bcopy(&e.e_u.u_in6.s6_addr,
592fcf3ce44SJohn Forte 			    ap->a_addr.i_addr.in6.s6_addr,
593fcf3ce44SJohn Forte 			    sizeof (struct in6_addr));
594fcf3ce44SJohn Forte 		} else {
595fcf3ce44SJohn Forte 			kmem_free(*isns_server_addrs, list_space);
596fcf3ce44SJohn Forte 			*isns_server_addrs = NULL;
597fcf3ce44SJohn Forte 			return (ISNS_BAD_SVR_ADDR);
598fcf3ce44SJohn Forte 		}
599fcf3ce44SJohn Forte 		i++;
600fcf3ce44SJohn Forte 	}
601fcf3ce44SJohn Forte 	persistent_isns_addr_unlock();
602fcf3ce44SJohn Forte 
603fcf3ce44SJohn Forte 	return (ISNS_OK);
604fcf3ce44SJohn Forte }
605fcf3ce44SJohn Forte 
606fcf3ce44SJohn Forte static
607fcf3ce44SJohn Forte int
create_esi_scn_thr(uint8_t * lhba_handle,iscsi_addr_t * isns_server_address)608fcf3ce44SJohn Forte create_esi_scn_thr(uint8_t *lhba_handle, iscsi_addr_t *isns_server_address)
609fcf3ce44SJohn Forte {
6106362598eSbing zhao - Sun Microsystems - Beijing China 	void *listening_so  = NULL;
6116362598eSbing zhao - Sun Microsystems - Beijing China 	boolean_t found	    = B_FALSE;
612fcf3ce44SJohn Forte 
613fcf3ce44SJohn Forte 	ASSERT(lhba_handle != NULL);
614fcf3ce44SJohn Forte 	ASSERT(isns_server_address != NULL);
615fcf3ce44SJohn Forte 
616fcf3ce44SJohn Forte 	/*
617fcf3ce44SJohn Forte 	 * Bringing up of the thread should happen regardless of the
618fcf3ce44SJohn Forte 	 * subsequent registration status. That means, do not destroy the
619fcf3ce44SJohn Forte 	 * ESI/SCN thread already created.
620fcf3ce44SJohn Forte 	 */
621fcf3ce44SJohn Forte 	/* Check and create ESI/SCN thread. */
622fcf3ce44SJohn Forte 	mutex_enter(&esi_scn_thr_mutex);
6236362598eSbing zhao - Sun Microsystems - Beijing China 
6246362598eSbing zhao - Sun Microsystems - Beijing China 	/* Determine local port and address. */
6256362598eSbing zhao - Sun Microsystems - Beijing China 	found = find_local_portal(isns_server_address,
6266362598eSbing zhao - Sun Microsystems - Beijing China 	    NULL, &listening_so);
6276362598eSbing zhao - Sun Microsystems - Beijing China 	if (found == B_FALSE) {
6286362598eSbing zhao - Sun Microsystems - Beijing China 		if (listening_so != NULL) {
6296362598eSbing zhao - Sun Microsystems - Beijing China 			iscsi_net->close(listening_so);
6306362598eSbing zhao - Sun Microsystems - Beijing China 		}
6316362598eSbing zhao - Sun Microsystems - Beijing China 		mutex_exit(&esi_scn_thr_mutex);
6326362598eSbing zhao - Sun Microsystems - Beijing China 		return (ISNS_CANNOT_FIND_LOCAL_ADDR);
6336362598eSbing zhao - Sun Microsystems - Beijing China 	}
6346362598eSbing zhao - Sun Microsystems - Beijing China 
635fcf3ce44SJohn Forte 	if (esi_scn_thr_id == NULL) {
636fcf3ce44SJohn Forte 		char thr_name[ISCSI_TH_MAX_NAME_LEN];
637fcf3ce44SJohn Forte 		int rval;
638fcf3ce44SJohn Forte 		isns_async_thread_arg_t *larg;
639fcf3ce44SJohn Forte 
640fcf3ce44SJohn Forte 		/* Assume the LHBA handle has a length of 4 */
641fcf3ce44SJohn Forte 		if (snprintf(thr_name, sizeof (thr_name) - 1,
642fcf3ce44SJohn Forte 		    "isns_client_esi_%x%x%x%x",
643fcf3ce44SJohn Forte 		    lhba_handle[0],
644fcf3ce44SJohn Forte 		    lhba_handle[1],
645fcf3ce44SJohn Forte 		    lhba_handle[2],
646fcf3ce44SJohn Forte 		    lhba_handle[3]) >=
647fcf3ce44SJohn Forte 		    sizeof (thr_name)) {
648fcf3ce44SJohn Forte 			esi_scn_thr_id = NULL;
649fcf3ce44SJohn Forte 			if (listening_so != NULL) {
650fcf3ce44SJohn Forte 				iscsi_net->close(listening_so);
651fcf3ce44SJohn Forte 				listening_so = NULL;
652fcf3ce44SJohn Forte 			}
653fcf3ce44SJohn Forte 			mutex_exit(&esi_scn_thr_mutex);
654fcf3ce44SJohn Forte 			return (ISNS_INTERNAL_ERR);
655fcf3ce44SJohn Forte 		}
656fcf3ce44SJohn Forte 
657fcf3ce44SJohn Forte 		larg = kmem_zalloc(sizeof (isns_async_thread_arg_t), KM_SLEEP);
658fcf3ce44SJohn Forte 		larg->lhba_handle = lhba_handle;
659fcf3ce44SJohn Forte 		larg->listening_so = listening_so;
660fcf3ce44SJohn Forte 		instance_listening_so = listening_so;
661fcf3ce44SJohn Forte 		esi_scn_thr_to_shutdown = B_FALSE;
662fcf3ce44SJohn Forte 		esi_scn_thr_id = iscsi_thread_create(NULL,
663fcf3ce44SJohn Forte 		    thr_name, isns_service_esi_scn, (void *)larg);
664fcf3ce44SJohn Forte 		if (esi_scn_thr_id == NULL) {
665fcf3ce44SJohn Forte 			if (listening_so != NULL) {
666fcf3ce44SJohn Forte 				iscsi_net->close(listening_so);
667fcf3ce44SJohn Forte 				listening_so = NULL;
668fcf3ce44SJohn Forte 				instance_listening_so = NULL;
669fcf3ce44SJohn Forte 			}
670fcf3ce44SJohn Forte 			mutex_exit(&esi_scn_thr_mutex);
671fcf3ce44SJohn Forte 			return (ISNS_INTERNAL_ERR);
672fcf3ce44SJohn Forte 		}
673fcf3ce44SJohn Forte 
674fcf3ce44SJohn Forte 		rval = iscsi_thread_start(esi_scn_thr_id);
675fcf3ce44SJohn Forte 		if (rval == B_FALSE) {
676fcf3ce44SJohn Forte 			iscsi_thread_destroy(esi_scn_thr_id);
677fcf3ce44SJohn Forte 			esi_scn_thr_id = NULL;
678fcf3ce44SJohn Forte 			if (listening_so != NULL) {
679fcf3ce44SJohn Forte 				iscsi_net->close(listening_so);
680fcf3ce44SJohn Forte 				listening_so = NULL;
681fcf3ce44SJohn Forte 				instance_listening_so = NULL;
682fcf3ce44SJohn Forte 			}
683fcf3ce44SJohn Forte 			mutex_exit(&esi_scn_thr_mutex);
684fcf3ce44SJohn Forte 			return (ISNS_INTERNAL_ERR);
685fcf3ce44SJohn Forte 		}
68649311b35SJack Meng 		(void) iscsi_thread_send_wakeup(esi_scn_thr_id);
687fcf3ce44SJohn Forte 	}
688fcf3ce44SJohn Forte 	mutex_exit(&esi_scn_thr_mutex);
689fcf3ce44SJohn Forte 
690fcf3ce44SJohn Forte 	return (ISNS_OK);
691fcf3ce44SJohn Forte }
692fcf3ce44SJohn Forte 
693fcf3ce44SJohn Forte static
694fcf3ce44SJohn Forte void
register_isns_client(void * arg)695fcf3ce44SJohn Forte register_isns_client(void *arg)
696fcf3ce44SJohn Forte {
697fcf3ce44SJohn Forte 	isns_reg_arg_t *reg_args;
698fcf3ce44SJohn Forte 	isns_status_t status;
699fcf3ce44SJohn Forte 
700fcf3ce44SJohn Forte 	reg_args = (isns_reg_arg_t *)arg;
701fcf3ce44SJohn Forte 
702fcf3ce44SJohn Forte 	/* Deregister stale registration (if any). */
703fcf3ce44SJohn Forte 	status = do_isns_dev_dereg(reg_args->isns_server_addr,
704fcf3ce44SJohn Forte 	    reg_args->node_name);
705fcf3ce44SJohn Forte 
706fcf3ce44SJohn Forte 	if (status == isns_open_conn_err) {
707fcf3ce44SJohn Forte 		/* Cannot open connection to the server. Stop proceeding. */
708fcf3ce44SJohn Forte 		kmem_free(reg_args->isns_server_addr, sizeof (iscsi_addr_t));
709fcf3ce44SJohn Forte 		reg_args->isns_server_addr = NULL;
710fcf3ce44SJohn Forte 		kmem_free(reg_args->node_name, reg_args->node_name_len);
711fcf3ce44SJohn Forte 		reg_args->node_name = NULL;
712fcf3ce44SJohn Forte 		kmem_free(reg_args->node_alias, reg_args->node_alias_len);
713fcf3ce44SJohn Forte 		reg_args->node_alias = NULL;
714fcf3ce44SJohn Forte 		kmem_free(reg_args, sizeof (isns_reg_arg_t));
715fcf3ce44SJohn Forte 		return;
716fcf3ce44SJohn Forte 	}
717fcf3ce44SJohn Forte 
718fcf3ce44SJohn Forte 	DTRACE_PROBE1(register_isns_client_dereg, isns_status_t, status);
719fcf3ce44SJohn Forte 
720fcf3ce44SJohn Forte 	/* New registration. */
721fcf3ce44SJohn Forte 	status =  do_isns_dev_attr_reg(reg_args->isns_server_addr,
722fcf3ce44SJohn Forte 	    reg_args->node_name, reg_args->node_alias, reg_args->node_type);
723fcf3ce44SJohn Forte 
724fcf3ce44SJohn Forte 	DTRACE_PROBE1(register_isns_client_reg, isns_status_t, status);
725fcf3ce44SJohn Forte 
726fcf3ce44SJohn Forte 	/* Cleanup */
727fcf3ce44SJohn Forte 	kmem_free(reg_args->isns_server_addr, sizeof (iscsi_addr_t));
728fcf3ce44SJohn Forte 	reg_args->isns_server_addr = NULL;
729fcf3ce44SJohn Forte 	kmem_free(reg_args->node_name, reg_args->node_name_len);
730fcf3ce44SJohn Forte 	reg_args->node_name = NULL;
731fcf3ce44SJohn Forte 	kmem_free(reg_args->node_alias, reg_args->node_alias_len);
732fcf3ce44SJohn Forte 	reg_args->node_alias = NULL;
733fcf3ce44SJohn Forte 	kmem_free(reg_args, sizeof (isns_reg_arg_t));
734fcf3ce44SJohn Forte }
735fcf3ce44SJohn Forte 
736fcf3ce44SJohn Forte static
737fcf3ce44SJohn Forte isns_status_t
do_isns_dev_attr_reg(iscsi_addr_t * isns_server_addr,uint8_t * node_name,uint8_t * node_alias,uint32_t node_type)738fcf3ce44SJohn Forte do_isns_dev_attr_reg(iscsi_addr_t *isns_server_addr,
739fcf3ce44SJohn Forte 	uint8_t *node_name, uint8_t *node_alias, uint32_t node_type)
740fcf3ce44SJohn Forte {
741fcf3ce44SJohn Forte 	int rcv_rsp_cnt = 0;
742fcf3ce44SJohn Forte 	int rsp_status;
743fcf3ce44SJohn Forte 	isns_pdu_t *in_pdu, *out_pdu;
744fcf3ce44SJohn Forte 	isns_status_t rval;
745fcf3ce44SJohn Forte 	size_t bytes_received, in_pdu_size = 0, out_pdu_size = 0;
746fcf3ce44SJohn Forte 	uint16_t xid;
747fcf3ce44SJohn Forte 	void *so = NULL;
748fcf3ce44SJohn Forte 
749fcf3ce44SJohn Forte 	out_pdu_size = isns_create_dev_attr_reg_pdu(
750fcf3ce44SJohn Forte 	    node_name,
751fcf3ce44SJohn Forte 	    node_alias,
752fcf3ce44SJohn Forte 	    node_type,
753fcf3ce44SJohn Forte 	    &xid, &out_pdu);
754fcf3ce44SJohn Forte 	if (out_pdu_size == 0) {
755fcf3ce44SJohn Forte 		return (isns_create_msg_err);
756fcf3ce44SJohn Forte 	}
757fcf3ce44SJohn Forte 
758fcf3ce44SJohn Forte 	ASSERT(out_pdu != NULL);
759fcf3ce44SJohn Forte 	ASSERT(out_pdu_size > 0);
760fcf3ce44SJohn Forte 
761fcf3ce44SJohn Forte 	so = isns_open(isns_server_addr);
762fcf3ce44SJohn Forte 	if (so == NULL) {
763fcf3ce44SJohn Forte 		/* Log a message and return */
764fcf3ce44SJohn Forte 		kmem_free(out_pdu, out_pdu_size);
765fcf3ce44SJohn Forte 		out_pdu = NULL;
766fcf3ce44SJohn Forte 		return (isns_open_conn_err);
767fcf3ce44SJohn Forte 	}
768fcf3ce44SJohn Forte 
769fcf3ce44SJohn Forte 	if (isns_send_pdu(so, out_pdu) != 0) {
770fcf3ce44SJohn Forte 		iscsi_net->close(so);
771fcf3ce44SJohn Forte 		kmem_free(out_pdu, out_pdu_size);
772fcf3ce44SJohn Forte 		out_pdu = NULL;
773fcf3ce44SJohn Forte 		return (isns_send_msg_err);
774fcf3ce44SJohn Forte 	}
775fcf3ce44SJohn Forte 
776fcf3ce44SJohn Forte 	/* Done with the out PDU - free it */
777fcf3ce44SJohn Forte 	kmem_free(out_pdu, out_pdu_size);
778fcf3ce44SJohn Forte 	out_pdu = NULL;
779fcf3ce44SJohn Forte 
780fcf3ce44SJohn Forte 	rcv_rsp_cnt = 0;
781fcf3ce44SJohn Forte 	rval = isns_ok;
782fcf3ce44SJohn Forte 	for (;;) {
783fcf3ce44SJohn Forte 		bytes_received = isns_rcv_pdu(so, &in_pdu, &in_pdu_size);
784fcf3ce44SJohn Forte 		ASSERT(bytes_received >= (size_t)0);
785fcf3ce44SJohn Forte 		if (bytes_received == 0) {
786fcf3ce44SJohn Forte 			ASSERT(in_pdu == NULL);
787fcf3ce44SJohn Forte 			ASSERT(in_pdu_size == 0);
788fcf3ce44SJohn Forte 			rval = isns_rcv_msg_err;
789fcf3ce44SJohn Forte 			break;
790fcf3ce44SJohn Forte 		}
791fcf3ce44SJohn Forte 
792fcf3ce44SJohn Forte 		ASSERT(in_pdu != NULL);
793fcf3ce44SJohn Forte 		ASSERT(in_pdu_size > 0);
794fcf3ce44SJohn Forte 
795fcf3ce44SJohn Forte 		if (ntohs(in_pdu->xid) != xid) {
796fcf3ce44SJohn Forte 			rcv_rsp_cnt++;
797fcf3ce44SJohn Forte 			if (rcv_rsp_cnt < MAX_RCV_RSP_COUNT) {
798fcf3ce44SJohn Forte 				continue;
799fcf3ce44SJohn Forte 			} else {
800fcf3ce44SJohn Forte 				/* Exceed maximum receive count. */
801fcf3ce44SJohn Forte 				kmem_free(in_pdu, in_pdu_size);
802fcf3ce44SJohn Forte 				in_pdu = NULL;
803fcf3ce44SJohn Forte 				rval = isns_no_rsp_rcvd;
804fcf3ce44SJohn Forte 				break;
805fcf3ce44SJohn Forte 			}
806fcf3ce44SJohn Forte 		}
807fcf3ce44SJohn Forte 
808fcf3ce44SJohn Forte 		rsp_status = isns_process_dev_attr_reg_rsp(in_pdu);
809fcf3ce44SJohn Forte 		if (rsp_status != ISNS_RSP_SUCCESSFUL) {
810fcf3ce44SJohn Forte 			if (rsp_status == ISNS_RSP_SRC_UNAUTHORIZED) {
811fcf3ce44SJohn Forte 				rval = isns_op_partially_failed;
812fcf3ce44SJohn Forte 			} else {
813fcf3ce44SJohn Forte 				rval = isns_op_failed;
814fcf3ce44SJohn Forte 			}
815fcf3ce44SJohn Forte 		}
816fcf3ce44SJohn Forte 		kmem_free(in_pdu, in_pdu_size);
817fcf3ce44SJohn Forte 		in_pdu = NULL;
818fcf3ce44SJohn Forte 		break;
819fcf3ce44SJohn Forte 	}
820fcf3ce44SJohn Forte 
821fcf3ce44SJohn Forte 	if (rval != isns_ok) {
822fcf3ce44SJohn Forte 		iscsi_net->close(so);
823fcf3ce44SJohn Forte 		return (rval);
824fcf3ce44SJohn Forte 	}
825fcf3ce44SJohn Forte 
826fcf3ce44SJohn Forte 	/* Always register SCN */
827fcf3ce44SJohn Forte 	out_pdu_size = isns_create_scn_reg_pdu(
828fcf3ce44SJohn Forte 	    node_name, node_alias,
829fcf3ce44SJohn Forte 	    &xid, &out_pdu);
830fcf3ce44SJohn Forte 	if (out_pdu_size == 0) {
831fcf3ce44SJohn Forte 		iscsi_net->close(so);
832fcf3ce44SJohn Forte 		return (isns_create_msg_err);
833fcf3ce44SJohn Forte 	}
834fcf3ce44SJohn Forte 
835fcf3ce44SJohn Forte 	ASSERT(out_pdu != NULL);
836fcf3ce44SJohn Forte 	ASSERT(out_pdu_size > 0);
837fcf3ce44SJohn Forte 
838fcf3ce44SJohn Forte 	if (isns_send_pdu(so, out_pdu) != 0) {
839fcf3ce44SJohn Forte 		iscsi_net->close(so);
840fcf3ce44SJohn Forte 		kmem_free(out_pdu, out_pdu_size);
841fcf3ce44SJohn Forte 		out_pdu = NULL;
842fcf3ce44SJohn Forte 		return (isns_send_msg_err);
843fcf3ce44SJohn Forte 	}
844fcf3ce44SJohn Forte 
845fcf3ce44SJohn Forte 	/* Done with the out PDU - free it */
846fcf3ce44SJohn Forte 	kmem_free(out_pdu, out_pdu_size);
847fcf3ce44SJohn Forte 	out_pdu = NULL;
848fcf3ce44SJohn Forte 
849fcf3ce44SJohn Forte 	rcv_rsp_cnt = 0;
850fcf3ce44SJohn Forte 	for (;;) {
851fcf3ce44SJohn Forte 		bytes_received = isns_rcv_pdu(so, &in_pdu, &in_pdu_size);
852fcf3ce44SJohn Forte 		ASSERT(bytes_received >= (size_t)0);
853fcf3ce44SJohn Forte 		if (bytes_received == 0) {
854fcf3ce44SJohn Forte 			ASSERT(in_pdu == NULL);
855fcf3ce44SJohn Forte 			ASSERT(in_pdu_size == 0);
856fcf3ce44SJohn Forte 			rval = isns_rcv_msg_err;
857fcf3ce44SJohn Forte 			break;
858fcf3ce44SJohn Forte 		}
859fcf3ce44SJohn Forte 
860fcf3ce44SJohn Forte 		ASSERT(in_pdu != NULL);
861fcf3ce44SJohn Forte 		ASSERT(in_pdu_size > 0);
862fcf3ce44SJohn Forte 
863fcf3ce44SJohn Forte 		if (ntohs(in_pdu->xid) != xid) {
864fcf3ce44SJohn Forte 			rcv_rsp_cnt++;
865fcf3ce44SJohn Forte 			if (rcv_rsp_cnt < MAX_RCV_RSP_COUNT) {
866fcf3ce44SJohn Forte 				continue;
867fcf3ce44SJohn Forte 			} else {
868fcf3ce44SJohn Forte 				/* Exceed maximum receive count. */
869fcf3ce44SJohn Forte 				kmem_free(in_pdu, in_pdu_size);
870fcf3ce44SJohn Forte 				in_pdu = NULL;
871fcf3ce44SJohn Forte 				rval = isns_no_rsp_rcvd;
872fcf3ce44SJohn Forte 				break;
873fcf3ce44SJohn Forte 			}
874fcf3ce44SJohn Forte 		}
875fcf3ce44SJohn Forte 
876fcf3ce44SJohn Forte 		rsp_status = isns_process_scn_reg_rsp(in_pdu);
877fcf3ce44SJohn Forte 		if (rsp_status != ISNS_RSP_SUCCESSFUL) {
878fcf3ce44SJohn Forte 			rval = isns_op_failed;
879fcf3ce44SJohn Forte 		}
880fcf3ce44SJohn Forte 		kmem_free(in_pdu, in_pdu_size);
881fcf3ce44SJohn Forte 		in_pdu = NULL;
882fcf3ce44SJohn Forte 		break;
883fcf3ce44SJohn Forte 	}
884fcf3ce44SJohn Forte 
885fcf3ce44SJohn Forte 	iscsi_net->close(so);
886fcf3ce44SJohn Forte 
887fcf3ce44SJohn Forte 	return (rval);
888fcf3ce44SJohn Forte }
889fcf3ce44SJohn Forte 
890fcf3ce44SJohn Forte static
891fcf3ce44SJohn Forte isns_status_t
do_isns_dev_dereg(iscsi_addr_t * isns_server_addr,uint8_t * node_name)892fcf3ce44SJohn Forte do_isns_dev_dereg(iscsi_addr_t *isns_server_addr,
893fcf3ce44SJohn Forte 	uint8_t *node_name)
894fcf3ce44SJohn Forte {
895fcf3ce44SJohn Forte 	int rcv_rsp_cnt = 0;
896fcf3ce44SJohn Forte 	int rsp_status;
897fcf3ce44SJohn Forte 	isns_pdu_t *in_pdu, *out_pdu;
898fcf3ce44SJohn Forte 	isns_status_t rval;
899fcf3ce44SJohn Forte 	size_t bytes_received, in_pdu_size = 0, out_pdu_size = 0;
900fcf3ce44SJohn Forte 	uint16_t xid;
901fcf3ce44SJohn Forte 	void *so = NULL;
902fcf3ce44SJohn Forte 
903fcf3ce44SJohn Forte 	out_pdu_size = isns_create_dev_dereg_pdu(
904fcf3ce44SJohn Forte 	    node_name,
905fcf3ce44SJohn Forte 	    &xid, &out_pdu);
906fcf3ce44SJohn Forte 	if (out_pdu_size == 0) {
907fcf3ce44SJohn Forte 		return (isns_create_msg_err);
908fcf3ce44SJohn Forte 	}
909fcf3ce44SJohn Forte 
910fcf3ce44SJohn Forte 	ASSERT(out_pdu != NULL);
911fcf3ce44SJohn Forte 	ASSERT(out_pdu_size > 0);
912fcf3ce44SJohn Forte 
913fcf3ce44SJohn Forte 	so = isns_open(isns_server_addr);
914fcf3ce44SJohn Forte 	if (so == NULL) {
915fcf3ce44SJohn Forte 		/* Log a message and return */
916fcf3ce44SJohn Forte 		kmem_free(out_pdu, out_pdu_size);
917fcf3ce44SJohn Forte 		out_pdu = NULL;
918fcf3ce44SJohn Forte 		return (isns_open_conn_err);
919fcf3ce44SJohn Forte 	}
920fcf3ce44SJohn Forte 
921fcf3ce44SJohn Forte 	if (isns_send_pdu(so, out_pdu) != 0) {
922fcf3ce44SJohn Forte 		iscsi_net->close(so);
923fcf3ce44SJohn Forte 		kmem_free(out_pdu, out_pdu_size);
924fcf3ce44SJohn Forte 		out_pdu = NULL;
925fcf3ce44SJohn Forte 		return (isns_send_msg_err);
926fcf3ce44SJohn Forte 	}
927fcf3ce44SJohn Forte 
928fcf3ce44SJohn Forte 	/* Done with the out PDU - free it */
929fcf3ce44SJohn Forte 	kmem_free(out_pdu, out_pdu_size);
930fcf3ce44SJohn Forte 	out_pdu = NULL;
931fcf3ce44SJohn Forte 
932fcf3ce44SJohn Forte 	rcv_rsp_cnt = 0;
933fcf3ce44SJohn Forte 	rval = isns_ok;
934fcf3ce44SJohn Forte 	for (;;) {
935fcf3ce44SJohn Forte 		bytes_received = isns_rcv_pdu(so, &in_pdu, &in_pdu_size);
936fcf3ce44SJohn Forte 		ASSERT(bytes_received >= (size_t)0);
937fcf3ce44SJohn Forte 		if (bytes_received == 0) {
938fcf3ce44SJohn Forte 			ASSERT(in_pdu == NULL);
939fcf3ce44SJohn Forte 			ASSERT(in_pdu_size == 0);
940fcf3ce44SJohn Forte 			rval = isns_rcv_msg_err;
941fcf3ce44SJohn Forte 			break;
942fcf3ce44SJohn Forte 		}
943fcf3ce44SJohn Forte 
944fcf3ce44SJohn Forte 		ASSERT(in_pdu != NULL);
945fcf3ce44SJohn Forte 		ASSERT(in_pdu_size > 0);
946fcf3ce44SJohn Forte 
947fcf3ce44SJohn Forte 		if (ntohs(in_pdu->xid) != xid) {
948fcf3ce44SJohn Forte 			rcv_rsp_cnt++;
949fcf3ce44SJohn Forte 			if (rcv_rsp_cnt < MAX_RCV_RSP_COUNT) {
950fcf3ce44SJohn Forte 				continue;
951fcf3ce44SJohn Forte 			} else {
952fcf3ce44SJohn Forte 				/* Exceed maximum receive count. */
953fcf3ce44SJohn Forte 				kmem_free(in_pdu, in_pdu_size);
954fcf3ce44SJohn Forte 				in_pdu = NULL;
955fcf3ce44SJohn Forte 				rval = isns_no_rsp_rcvd;
956fcf3ce44SJohn Forte 				break;
957fcf3ce44SJohn Forte 			}
958fcf3ce44SJohn Forte 		}
959fcf3ce44SJohn Forte 
960fcf3ce44SJohn Forte 		rsp_status = isns_process_dev_attr_dereg_rsp(in_pdu);
961fcf3ce44SJohn Forte 		if (rsp_status != ISNS_RSP_SUCCESSFUL) {
962fcf3ce44SJohn Forte 			rval = isns_op_failed;
963fcf3ce44SJohn Forte 		}
964fcf3ce44SJohn Forte 		kmem_free(in_pdu, in_pdu_size);
965fcf3ce44SJohn Forte 		in_pdu = NULL;
966fcf3ce44SJohn Forte 		break;
967fcf3ce44SJohn Forte 	}
968fcf3ce44SJohn Forte 
969fcf3ce44SJohn Forte 	if (rval != isns_ok) {
970fcf3ce44SJohn Forte 		iscsi_net->close(so);
971fcf3ce44SJohn Forte 		return (rval);
972fcf3ce44SJohn Forte 	}
973fcf3ce44SJohn Forte 
974fcf3ce44SJohn Forte 	/* Always deregister SCN */
975fcf3ce44SJohn Forte 	out_pdu_size = isns_create_scn_dereg_pdu(
976fcf3ce44SJohn Forte 	    node_name,
977fcf3ce44SJohn Forte 	    &xid, &out_pdu);
978fcf3ce44SJohn Forte 	if (out_pdu_size == 0) {
979fcf3ce44SJohn Forte 		iscsi_net->close(so);
980fcf3ce44SJohn Forte 		return (isns_create_msg_err);
981fcf3ce44SJohn Forte 	}
982fcf3ce44SJohn Forte 
983fcf3ce44SJohn Forte 	ASSERT(out_pdu != NULL);
984fcf3ce44SJohn Forte 	ASSERT(out_pdu_size > 0);
985fcf3ce44SJohn Forte 
986fcf3ce44SJohn Forte 	if (isns_send_pdu(so, out_pdu) != 0) {
987fcf3ce44SJohn Forte 		iscsi_net->close(so);
988fcf3ce44SJohn Forte 		kmem_free(out_pdu, out_pdu_size);
989fcf3ce44SJohn Forte 		out_pdu = NULL;
990fcf3ce44SJohn Forte 		return (isns_send_msg_err);
991fcf3ce44SJohn Forte 	}
992fcf3ce44SJohn Forte 
993fcf3ce44SJohn Forte 	/* Done with the out PDU - free it */
994fcf3ce44SJohn Forte 	kmem_free(out_pdu, out_pdu_size);
995fcf3ce44SJohn Forte 	out_pdu = NULL;
996fcf3ce44SJohn Forte 
997fcf3ce44SJohn Forte 	rcv_rsp_cnt = 0;
998fcf3ce44SJohn Forte 	for (;;) {
999fcf3ce44SJohn Forte 		bytes_received = isns_rcv_pdu(so, &in_pdu, &in_pdu_size);
1000fcf3ce44SJohn Forte 		ASSERT(bytes_received >= (size_t)0);
1001fcf3ce44SJohn Forte 		if (bytes_received == 0) {
1002fcf3ce44SJohn Forte 			ASSERT(in_pdu == NULL);
1003fcf3ce44SJohn Forte 			ASSERT(in_pdu_size == 0);
1004fcf3ce44SJohn Forte 			rval = isns_rcv_msg_err;
1005fcf3ce44SJohn Forte 			break;
1006fcf3ce44SJohn Forte 		}
1007fcf3ce44SJohn Forte 
1008fcf3ce44SJohn Forte 		ASSERT(in_pdu != NULL);
1009fcf3ce44SJohn Forte 		ASSERT(in_pdu_size > 0);
1010fcf3ce44SJohn Forte 
1011fcf3ce44SJohn Forte 		if (ntohs(in_pdu->xid) != xid) {
1012fcf3ce44SJohn Forte 			rcv_rsp_cnt++;
1013fcf3ce44SJohn Forte 			if (rcv_rsp_cnt < MAX_RCV_RSP_COUNT) {
1014fcf3ce44SJohn Forte 				continue;
1015fcf3ce44SJohn Forte 			} else {
1016fcf3ce44SJohn Forte 				/* Exceed maximum receive count. */
1017fcf3ce44SJohn Forte 				kmem_free(in_pdu, in_pdu_size);
1018fcf3ce44SJohn Forte 				in_pdu = NULL;
1019fcf3ce44SJohn Forte 				rval = isns_no_rsp_rcvd;
1020fcf3ce44SJohn Forte 				break;
1021fcf3ce44SJohn Forte 			}
1022fcf3ce44SJohn Forte 		}
1023fcf3ce44SJohn Forte 
1024fcf3ce44SJohn Forte 		rsp_status = isns_process_scn_dereg_rsp(in_pdu);
1025fcf3ce44SJohn Forte 		if (rsp_status != ISNS_RSP_SUCCESSFUL) {
1026fcf3ce44SJohn Forte 			rval = isns_op_failed;
1027fcf3ce44SJohn Forte 		}
1028fcf3ce44SJohn Forte 		kmem_free(in_pdu, in_pdu_size);
1029fcf3ce44SJohn Forte 		in_pdu = NULL;
1030fcf3ce44SJohn Forte 		break;
1031fcf3ce44SJohn Forte 	}
1032fcf3ce44SJohn Forte 
1033fcf3ce44SJohn Forte 	iscsi_net->close(so);
1034fcf3ce44SJohn Forte 
1035fcf3ce44SJohn Forte 	return (rval);
1036fcf3ce44SJohn Forte }
1037fcf3ce44SJohn Forte 
1038fcf3ce44SJohn Forte static
1039fcf3ce44SJohn Forte isns_status_t
do_isns_query(boolean_t is_query_all_nodes_b,uint8_t * lhba_handle,uint8_t * target_node_name,uint8_t * source_node_name,uint8_t * source_node_alias,uint32_t source_node_type,isns_portal_group_list_t ** pg_list)1040fcf3ce44SJohn Forte do_isns_query(boolean_t is_query_all_nodes_b,
1041fcf3ce44SJohn Forte 	uint8_t *lhba_handle,
1042fcf3ce44SJohn Forte 	uint8_t *target_node_name,
1043fcf3ce44SJohn Forte 	uint8_t *source_node_name,
1044fcf3ce44SJohn Forte 	uint8_t *source_node_alias,
1045fcf3ce44SJohn Forte 	uint32_t source_node_type,
1046fcf3ce44SJohn Forte 	isns_portal_group_list_t **pg_list)
1047fcf3ce44SJohn Forte {
1048fcf3ce44SJohn Forte 	int i, j, k;
1049fcf3ce44SJohn Forte 	int combined_num_of_pgs, combined_pg_lst_sz,
1050fcf3ce44SJohn Forte 	    isns_svr_lst_sz,
1051fcf3ce44SJohn Forte 	    tmp_pg_list_sz,
1052fcf3ce44SJohn Forte 	    tmp_pg_lists_sz;
1053fcf3ce44SJohn Forte 	iscsi_addr_list_t *isns_server_addr_list = NULL;
1054fcf3ce44SJohn Forte 	isns_portal_group_t *pg;